ComponentsTextfield
Text Field Input
단일 줄 텍스트 입력 필드
텍스트 입력 필드 컴포넌트는 사용자로부터 텍스트 입력을 받는 폼 요소입니다.
기본 사용법
import { TextField, TextFieldInput, TextFieldTextarea,} from '@aift/ui/TextField';export default function Preview() { return ( <div className="max-w-md space-y-4"> <TextField> <TextFieldInput autoFocus placeholder="내용을 입력해주세요." /> </TextField> </div> );}Size
TextField의 크기를 설정할 수 있습니다.
'use client';import { TextField, TextFieldInput } from '@aift/ui/TextField';export default function Sizes() { return ( <div className="space-y-4"> <TextField size="xsmall"> <TextFieldInput placeholder="xsmall 크기" /> </TextField> <TextField size="small"> <TextFieldInput placeholder="small 크기" /> </TextField> <TextField size="medium"> <TextFieldInput placeholder="medium 크기" /> </TextField> <TextField size="large"> <TextFieldInput placeholder="large 크기" /> </TextField> <TextField size="xlarge"> <TextFieldInput placeholder="xlarge 크기" /> </TextField> </div> );}Label
TextField에 레이블을 추가할 수 있습니다.
'use client';import { TextField, TextFieldInput } from '@aift/ui/TextField';export default function Label() { return ( <div className="space-y-4"> <TextField label="레이블"> <TextFieldInput placeholder="레이블이 있는 입력 필드" /> </TextField> </div> );}Message
TextField의 상태에 따라 메시지를 표시할 수 있습니다.
오류 메시지가 표시됩니다
'use client';import { TextField, TextFieldInput } from '@aift/ui/TextField';export default function Message() { return ( <div className="space-y-4"> <TextField> <TextFieldInput placeholder="Enabled" /> </TextField> <TextField invalid errorMessage="오류 메시지가 표시됩니다"> <TextFieldInput placeholder="Error" /> </TextField> </div> );}TextFieldInput
TextField에 단일 줄 값을 입력할 수 있습니다.
Value:
'use client';import { useState } from 'react';import { TextField, TextFieldInput } from '@aift/ui/TextField';export default function Input() { const [value, setValue] = useState(''); return ( <div className="space-y-4"> <TextField value={value} onValueChange={(value) => setValue(value)}> <TextFieldInput placeholder="텍스트를 입력하세요" /> </TextField> <p>Value: {value}</p> </div> );}Required (Dot)
필수 입력 필드를 표시할 수 있습니다.
'use client';import { TextField, TextFieldInput } from '@aift/ui/TextField';export default function Required() { return ( <div className="space-y-4"> <TextField required label="필수입력 항목" > <TextFieldInput placeholder="필수 입력 항목입니다" /> </TextField> <TextField label="선택입력 항목"> <TextFieldInput placeholder="선택 입력 항목입니다" /> </TextField> </div> );}Disabled
TextField를 비활성화할 수 있습니다.
'use client';import { TextField, TextFieldInput } from '@aift/ui/TextField';export default function Disabled() { return ( <div className="space-y-4"> <TextField> <TextFieldInput placeholder="입력 가능한 필드" /> </TextField> <TextField disabled> <TextFieldInput placeholder="입력 불가능한 필드" /> </TextField> </div> );}Clear Button
입력 내용을 삭제할 수 있는 버튼을 추가할 수 있습니다. rightSlot prop을 사용하여 삭제 버튼을 추가할 수 있습니다.
'use client';import { TextField, TextFieldInput } from '@aift/ui/TextField';import { useState } from 'react';export default function ClearButton() { const [value1, setValue1] = useState(''); return ( <div className="space-y-4"> <TextField value={value1} onValueChange={(value) => setValue1(value)}> <TextFieldInput placeholder="입력 후 삭제 버튼을 클릭하세요" /> </TextField> <TextField clearButton={false}> <TextFieldInput placeholder="삭제 버튼이 없는 입력 필드" /> </TextField> </div> );}Color
TextField의 배경색을 설정할 수 있습니다.
'use client';import { TextField, TextFieldInput } from '@aift/ui/TextField';export default function Color() { return ( <div className="space-y-4"> <TextField color="white"> <TextFieldInput placeholder="흰색 배경 입력 필드" /> </TextField> <TextField color="gray"> <TextFieldInput placeholder="회색 배경 입력 필드" /> </TextField> </div> );}React Hook Form
React Hook Form을 사용하여 폼을 관리할 수 있습니다.
'use client';import { useController, useForm } from 'react-hook-form';import { TextField, TextFieldInput } from '@aift/ui/TextField';import { Button } from '@aift/ui/Button';import { useState } from 'react';interface FormData { name: string; address: string;}export default function ReactHookForm() { const { reset, handleSubmit, formState: { errors, isSubmitting }, control, } = useForm<FormData>({ mode: 'onSubmit', reValidateMode: 'onChange', defaultValues: { name: '', address: '', }, }); const { field: nameField } = useController({ name: 'name', control: control, rules: { required: '이름은 필수 입력입니다.', }, }); const { field: addressField } = useController({ name: 'address', control: control, }); const [formValue, setFormValue] = useState<FormData>(); const onSubmit = (data: FormData) => { setFormValue(data); }; return ( <form onSubmit={handleSubmit(onSubmit)} className="space-y-4"> <TextField required label="이름" invalid={!!errors.name} errorMessage={errors.name?.message as string} value={nameField.value} onValueChange={nameField.onChange} name={nameField.name} inputRef={nameField.ref} onBlur={nameField.onBlur} > <TextFieldInput placeholder="이름을 입력하세요" /> </TextField> <TextField label="주소" value={addressField.value} onValueChange={addressField.onChange} name={addressField.name} inputRef={addressField.ref} onBlur={addressField.onBlur} > <TextFieldInput placeholder="주소를 입력하세요" /> </TextField> <div className="flex gap-2"> <Button type="button" variant="outlined" onClick={() => reset()}> 초기화 </Button> <Button type="submit" disabled={isSubmitting} variant="contained" color="primary" > 제출 </Button> </div> {formValue && ( <div className="space-y-2 mt-8"> <p className="text-sm text-neutral-80 font-semibold"> 이름: {formValue.name} </p> <p className="text-sm text-neutral-80 font-semibold"> 주소: {formValue.address} </p> </div> )} </form> );}Props
TextField
| Prop | Type | Default | Description |
|---|---|---|---|
| children | ReactNode | 필수 | TextFieldInput 또는 TextFieldTextarea |
| label | string | - | 입력 필드 레이블 |
| labelSize | 'small' | 'medium' | 'small' | 레이블 타이포그래피 크기 |
| value | string | - | 입력 값 (제어 컴포넌트) |
| defaultValue | string | - | 비제어 모드 기본값 |
| onValueChange | (value: string) => void | - | 값 변경 시 문자열 콜백 |
| onChange | (e: ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => void | - | 네이티브 change 이벤트 |
| onBlur | (e: FocusEvent<HTMLInputElement | HTMLTextAreaElement>) => void | - | blur 이벤트 |
| onFocus | (e: FocusEvent<HTMLInputElement | HTMLTextAreaElement>) => void | - | focus 이벤트 |
| onKeyDown | (e: KeyboardEvent<HTMLInputElement | HTMLTextAreaElement>) => void | - | keydown 이벤트 |
| onKeyUp | (e: KeyboardEvent<HTMLInputElement | HTMLTextAreaElement>) => void | - | keyup 이벤트 |
| onKeyPress | (e: KeyboardEvent<HTMLInputElement | HTMLTextAreaElement>) => void | - | keypress 이벤트 |
| disabled | boolean | false | 비활성화 |
| required | boolean | false | 필수 입력(레이블에 표시) |
| invalid | boolean | - | 유효하지 않음(Field·접근성). 하단 오류 문구는 errorMessage와 함께 있을 때만 표시 |
| errorMessage | string | - | 오류 문구. 있으면 입력 테두리는 destructive; 하단 표시는 invalid가 true일 때만 |
| description | string | - | 도움말·설명(오류 문구가 없을 때 하단에 표시) |
| size | 'xsmall' | 'small' | 'medium' | 'large' | 'xlarge' | 'extra' | 'medium' | 입력 필드 크기 |
| status | 'default' | 'positive' | 'cautionary' | 'destructive' | 'info' | 'default' | InputClassVariantProps 상속 |
| color | 'white' | 'gray' | 'white' | 배경색 |
| variant | 'rounded' | 'rectangled' | 'plain' | 'circle' | 'rounded' | 스타일 변형 |
| radius | 'none' | 'small' | 'medium' | 'large' | 'extra' | 'full' | 'medium' | 테두리 반경 |
| leftSlot | ReactNode | - | 왼쪽 슬롯(아이콘 등) |
| rightSlot | ReactNode | - | 오른쪽 슬롯 |
| clearButton | boolean | true | 입력 지우기 버튼 표시 |
| id | string | - | input/필드 ID |
| name | string | - | input name |
| inputRef | Ref<HTMLInputElement> | - | 실제 input ref(RHF register·명시적 ref 병합) |
| rootRef | Ref<HTMLDivElement> | - | 래퍼(TextFieldInner 루트) ref |
| className | string | - | 루트 Field 레이아웃에 적용할 클래스 |
| controlClassName | string | - | 컨트롤 영역(보더/슬롯/TextFieldInput을 감싸는 박스)에 적용할 클래스 |
TextFieldInput
| Prop | Type | Default | Description |
|---|---|---|---|
| placeholder | string | - | 플레이스홀더 텍스트 |
| autoFocus | boolean | false | 자동 포커스 여부 |