Form
Input
크기, 비밀번호 표시, Enter 동작을 지원하는 텍스트 입력입니다.
Usage
기본 input 속성을 그대로 전달하며, 프로젝트 전용 size와 onEnter를 추가로 지원합니다.
Examples
Password
Enter
Enter를 눌러보세요.
Props
size?: 'small' | 'medium' | 'large'— 입력 높이, 기본값mediumonEnter?: (event, value) => void— Enter 입력 시 호출wrapperClass?: string— 바깥 wrapper class- 그 밖의 표준
input속성
Source
input
'use client'
import React, { forwardRef, PropsWithChildren, Ref, useCallback, useEffect, useState } from 'react'
import { iconSizeClasses, IInputProps, passwordClasses, sizeClasses } from '@/shared/ui/Input/types'
export default forwardRef<HTMLInputElement, IInputProps>(function DInput(
{
wrapperClass = '',
className = '',
size = 'medium',
type = 'text',
onEnter,
...props
}: PropsWithChildren<IInputProps>,
ref: Ref<HTMLInputElement>,
): React.JSX.Element {
const wrapperClasses = ['relative w-full', wrapperClass].filter((w) => !!w).join(' ')
const inputClasses = [
'flex w-full rounded-md border border-neutral-400 dark:border-neutral-500 disabled:cursor-not-allowed disabled:opacity-50 dark:bg-neutral-800',
sizeClasses[size],
type === 'password' && passwordClasses[size],
className,
]
.filter((w) => !!w)
.join(' ')
const [isShowPassword, setIsShowPassword] = useState<boolean>(false)
const handleClickViewPassword = useCallback(() => {
setIsShowPassword((prev) => !prev)
}, [])
const handleKeydown = useCallback(
(e: React.KeyboardEvent<HTMLInputElement>) => {
if (e.key === 'Enter') {
if (onEnter && typeof onEnter === 'function') {
onEnter(e, e.currentTarget.value)
}
}
},
[onEnter],
)
useEffect(() => {
setIsShowPassword(false)
}, [])
return (
<div className={`${wrapperClasses}`}>
<input
{...props}
type={isShowPassword ? 'text' : type}
className={`${inputClasses}`}
ref={ref}
onKeyDown={handleKeydown}
/>
{type === 'password' && (
<button
className={'absolute top-1/2 right-3 translate-y-[-50%]'}
onClick={handleClickViewPassword}
>
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
strokeWidth={1.5}
stroke="currentColor"
className={iconSizeClasses[size]}
>
{isShowPassword ? (
<>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M2.036 12.322a1.012 1.012 0 0 1 0-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178Z"
/>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z"
/>
</>
) : (
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M3.98 8.223A10.477 10.477 0 0 0 1.934 12C3.226 16.338 7.244 19.5 12 19.5c.993 0 1.953-.138 2.863-.395M6.228 6.228A10.451 10.451 0 0 1 12 4.5c4.756 0 8.773 3.162 10.065 7.498a10.522 10.522 0 0 1-4.293 5.774M6.228 6.228 3 3m3.228 3.228 3.65 3.65m7.894 7.894L21 21m-3.228-3.228-3.65-3.65m0 0a3 3 0 1 0-4.243-4.243m4.242 4.242L9.88 9.88"
/>
)}
</svg>
</button>
)}
</div>
)
})
input-examples
'use client'
import { useState } from 'react'
import Input from '@/shared/ui/Input'
export function InputBasicExample() {
return (
<div className="w-full max-w-sm space-y-3">
<Input aria-label="이름" placeholder="이름을 입력하세요" />
<Input aria-label="작은 입력" size="small" placeholder="Small" />
<Input aria-label="비활성 입력" disabled placeholder="Disabled" />
</div>
)
}
export function InputPasswordExample() {
return (
<div className="w-full max-w-sm">
<Input aria-label="비밀번호" type="password" placeholder="비밀번호" />
</div>
)
}
export function InputEnterExample() {
const [message, setMessage] = useState('Enter를 눌러보세요.')
return (
<div className="w-full max-w-sm space-y-2">
<Input aria-label="Enter 예제" onEnter={(_, value) => setMessage(`입력값: ${value}`)} />
<p aria-live="polite" className="text-sm">
{message}
</p>
</div>
)
}
Known limitations
현재 비밀번호 표시 버튼은 접근 가능한 이름과 명시적 type="button"이 없습니다. 현행 UI 보존 범위에서는 수정하지 않았으며, 접근성 개선 작업에서 보완해야 합니다.