Component
Input
한 줄 텍스트와 숫자를 받는 HTML input 래퍼입니다.
Playground
옵션을 조절하며 화면과 사용 코드를 함께 확인하세요.
PC 1280px
Controls
비어 있을 때 힌트
control 높이
필드 표면
elevation 아래 불투명 테마 배경
오류 시각 상태와 aria-invalid
비활성
아이콘 컴포넌트, 문자열, ReactNode 또는 null을 전달합니다.
아이콘 컴포넌트, 문자열, ReactNode 또는 null을 전달합니다.
Code
import { Input } from '@amineslab/ui'
import { Mail, Check } from '@amineslab/ui/icons'
function slotText(value: string) {
return value.startsWith('text:') ? value.slice(5) : value;
}
function slotKind(value: string): 'none' | 'icon' | 'node' | 'text' {
if (value === 'icon' || value === 'node' || value === 'none')
return value;
return 'text';
}
function renderInputSlot(value: string, icon: typeof Mail) {
switch (slotKind(value)) {
case 'none':
return null;
case 'icon':
return icon;
case 'node':
return <span className="font-semibold">단위</span>;
case 'text':
return slotText(value);
}
}
export default function ExamplePreview() {
return ((<Input aria-label="이메일" opaque={false} disabled={false} invalid={false} startAdornment={renderInputSlot("icon", Mail)} placeholder={"name@example.com"} size={"md"} variant={"filled"} endAdornment={renderInputSlot("none", Check)}/>))
}Props
@amineslab/ui에서 Input를 가져옵니다.
import { Input } from '@amineslab/ui'Input
HTML <input> 요소의 표준 속성을 그대로 받습니다.
| Name | Type | Default | Description |
|---|---|---|---|
opaque | boolean | false | 반투명 elevation 아래에 불투명한 테마 배경을 깝니다. Button의 opaque와 같습니다. |
variant | 'filled' | 'outline' | 'filled' | 입력 필드의 표면 표현입니다. |
size | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'md' | 입력 요소의 높이와 내부 여백입니다. |
invalid | boolean | false | 오류 시각 상태와 aria-invalid를 활성화합니다. |
startAdornment | ReactNode | IconComponent | - | Mail 같은 아이콘 컴포넌트는 16px·보조색으로 표시합니다. 텍스트는 보조색·말줄임을 적용하고 슬롯 너비만큼 입력 여백을 확보합니다. ReactNode도 전달할 수 있습니다. |
endAdornment | ReactNode | IconComponent | - | Check 같은 아이콘 컴포넌트는 16px·보조색으로 표시합니다. 텍스트는 보조색·말줄임을 적용하고 슬롯 너비만큼 입력 여백을 확보합니다. ReactNode도 전달할 수 있습니다. |
wrapperClassName | string | - | 입력 장식 래퍼에 추가할 클래스입니다. |
Examples
자주 쓰는 조합을 살펴보고, 필요한 예시의 코드를 펼쳐 확인하세요.
Sizes
import { type ComponentPropsWithoutRef } from 'react'
import { cn } from '@amineslab/ui/utils'
import { type ControlSize, Input } from '@amineslab/ui'
const controlSizes = ['xs', 'sm', 'md', 'lg', 'xl'] as const satisfies readonly ControlSize[];
const sizes = controlSizes;
function ExampleStack({ className, compact = false, fullWidth = false, ...props }: ComponentPropsWithoutRef<'div'> & {
compact?: boolean;
fullWidth?: boolean;
}) {
return (<div {...props} className={cn('grid', compact ? 'w-auto gap-2' : fullWidth ? 'w-full gap-4' : 'w-full max-w-[360px] gap-3', className)}/>);
}
export default function ExamplePreview() {
return ((<ExampleStack>
{sizes.map((size) => (<Input aria-label={`검색 ${size}`} key={size} placeholder={`Size ${size}`} size={size}/>))}
</ExampleStack>))
}Left and right slots
startAdornment과 endAdornment은 아이콘 컴포넌트, 문자열, ReactNode를 받습니다. 아이콘은 컴포넌트 참조만 전달하고, 단위나 접두어는 문자열로 바로 넣을 수 있습니다.
₩
원
할인
%
import { type ComponentPropsWithoutRef } from 'react'
import { cn } from '@amineslab/ui/utils'
import { Input } from '@amineslab/ui'
import { Search, Mail, Check } from '@amineslab/ui/icons'
function ExampleStack({ className, compact = false, fullWidth = false, ...props }: ComponentPropsWithoutRef<'div'> & {
compact?: boolean;
fullWidth?: boolean;
}) {
return (<div {...props} className={cn('grid', compact ? 'w-auto gap-2' : fullWidth ? 'w-full gap-4' : 'w-full max-w-[360px] gap-3', className)}/>);
}
export default function ExamplePreview() {
return ((<ExampleStack>
<Input aria-label="검색" startAdornment={Search} placeholder="검색"/>
<Input aria-label="이메일" startAdornment={Mail} endAdornment={Check} defaultValue="hello@example.com"/>
<Input aria-label="금액" startAdornment="₩" endAdornment="원" defaultValue="12,000"/>
<Input aria-label="할인율" startAdornment={<span className="font-semibold">할인</span>} endAdornment={<span className="text-brand">%</span>} defaultValue="10"/>
</ExampleStack>))
}States
import { type ComponentPropsWithoutRef } from 'react'
import { cn } from '@amineslab/ui/utils'
import { Input } from '@amineslab/ui'
function ExampleStack({ className, compact = false, fullWidth = false, ...props }: ComponentPropsWithoutRef<'div'> & {
compact?: boolean;
fullWidth?: boolean;
}) {
return (<div {...props} className={cn('grid', compact ? 'w-auto gap-2' : fullWidth ? 'w-full gap-4' : 'w-full max-w-[360px] gap-3', className)}/>);
}
export default function ExamplePreview() {
return ((<ExampleStack>
<Input aria-label="이메일 오류" defaultValue="hello@amineslab" invalid/>
<Input aria-label="이메일 비활성" defaultValue="hello@amineslab.com" disabled/>
</ExampleStack>))
}TextField로 사용하기
TextField는 기본 입력에 label·required·description·error를 함께 제공합니다. FormStack 안에 직접 넣으며 FormField로 다시 감싸지 않습니다.
라벨·설명·필수 표시를 Field가 함께 처리합니다.
import { useState } from 'react'
import { TextField } from '@amineslab/ui'
const fieldDescription = '라벨·설명·필수 표시를 Field가 함께 처리합니다.';
function TextFieldExample() {
const [value, setValue] = useState('');
return (<TextField label="이름" description={fieldDescription} required value={value} onValueChange={setValue} placeholder="이름을 입력해 주세요"/>);
}
export default function ExamplePreview() {
return (<TextFieldExample />)
}사용 기준
권장하는 사용
- 입력값에 맞는 HTML `type`과 `autocomplete`을 지정합니다.
피해야 할 사용
- 숫자 키패드가 필요하다는 이유만으로 식별자에 number type을 쓰지 마세요.
접근성
화면에 맞는 이름을 제공하고, 키보드만으로 작업을 마칠 수 있는지 확인하세요.
Tab: input으로 포커스 이동