Input
Data Input
한 줄 텍스트를 입력받는 필드.
Usage
단일 라인 텍스트 입력. 이름·검색어·짧은 값
import
import
import { Input } from '@mildang/design-system/Input';예제를 복사해 쓸 때 필요한 준비
• @mildang/icons 를 따로 설치한다. DS 패키지에 아이콘 컴포넌트가 포함되지 않는다.
API Reference
Input Props
Prop
Type
Default
string
지정 안 함
boolean
지정 안 함
string
지정 안 함
ReactNode
지정 안 함
boolean
false
boolean
false
boolean
false
string
지정 안 함
string
지정 안 함
boolean
지정 안 함
string
지정 안 함
FocusEventHandler<HTMLInputElement | HTMLTextAreaElement>
지정 안 함
ChangeEventHandler<HTMLInputElement | HTMLTextAreaElement>
지정 안 함
FocusEventHandler<HTMLInputElement | HTMLTextAreaElement>
지정 안 함
FormEventHandler<HTMLInputElement | HTMLTextAreaElement>
지정 안 함
KeyboardEventHandler<HTMLInputElement | HTMLTextAreaElement>
지정 안 함
KeyboardEventHandler<HTMLInputElement | HTMLTextAreaElement>
지정 안 함
"xs" | "sm" | "md" | "lg" | "xl"
md
ReactNode
지정 안 함
boolean
false
string
지정 안 함
boolean
false
예제
기본 사용
placeholder 만 준 한 줄 입력 — 폼에 쓸 때는 Field 로 감싸 라벨과 오류 문구를 함께 붙입니다.
import type { ComponentProps } from 'react';
import { Input } from '@mildang/design-system/Input';
const STORY_DEFAULT_ARGS = { ...({}), ...({ placeholder: 'Enter text...', size: 'md', ghost: false }) } as ComponentProps<typeof Input>;
const InputDemoExampleRender = (args: ComponentProps<typeof Input>) => <Input {...args} />;
export default function InputDemoExample(props: Partial<ComponentProps<typeof Input>>) {
const mergedProps = { ...STORY_DEFAULT_ARGS, ...props } as ComponentProps<typeof Input>;
return InputDemoExampleRender(mergedProps);
}
크기
xs부터 xl까지 높이를 비교합니다. 한 폼 안에서는 크기를 섞지 않고 md 를 기준으로 둡니다.
import { Input } from '@mildang/design-system/Input';
import Eye from '@mildang/icons/react/eye';
const InputSizesExample = () => (
<div style={{ display: 'flex', flexDirection: 'column', gap: '12px', width: '320px' }}>
{(['xs', 'sm', 'md', 'lg', 'xl'] as const).map((size) => (
<div key={size} style={{ display: 'flex', alignItems: 'center', gap: '12px' }}>
<span style={{ width: '24px', fontSize: '12px', color: '#666', flexShrink: 0 }}>{size}</span>
<Input
size={size}
placeholder={`size=${size}`}
startAdornment={<Eye />}
endAdornment={<Eye />}
fullWidth
/>
</div>
))}
</div>
);
export default InputSizesExample;
상태
기본·오류·비활성을 나란히 둡니다. error 는 테두리만 바꾸므로 사유는 HelpText 로 함께 적습니다.
import { Text } from '@mildang/design-system/Text';
import { Input } from '@mildang/design-system/Input';
import Eye from '@mildang/icons/react/eye';
const InputDisabledExample = () => (
<div style={{ display: 'flex', flexDirection: 'column', gap: '16px', width: '300px' }}>
<div>
<Text variant="title-sm-medium" mb="8px">
Disabled (empty)
</Text>
<Input disabled placeholder="Placeholder" fullWidth />
</div>
<div>
<Text variant="title-sm-medium" mb="8px">
Disabled (with value)
</Text>
<Input disabled defaultValue="입력된 텍스트" fullWidth />
</div>
<div>
<Text variant="title-sm-medium" mb="8px">
Disabled + Adornments
</Text>
<Input
disabled
defaultValue="010-1234-5678"
startAdornment={<Eye />}
endAdornment={<Eye />}
fullWidth
/>
</div>
</div>
);
export default InputDisabledExample;
StatusGuide
import { Text } from '@mildang/design-system/Text';
import { Input } from '@mildang/design-system/Input';
import Eye from '@mildang/icons/react/eye';
const InputStatusGuideExample = () => (
<div style={{ display: 'flex', flexDirection: 'column', gap: '16px', width: '500px' }}>
<div>
<Text variant="title-sm-medium" mb="8px">
Inactive
</Text>
<Input placeholder="Default state" endAdornment={<Eye />} />
</div>
<div>
<Text variant="title-sm-medium" mb="8px">
Error
</Text>
<Input error placeholder="Error state" endAdornment={<Eye />} />
</div>
<div>
<Text variant="title-sm-medium" mb="8px">
Warning
</Text>
<Input warning placeholder="Warning state" endAdornment={<Eye />} />
</div>
<div>
<Text variant="title-sm-medium" mb="8px">
Success
</Text>
<Input success placeholder="Success state" endAdornment={<Eye />} />
</div>
</div>
);
export default InputStatusGuideExample;
WithAdornments
import type { ComponentProps } from 'react';
import { Input } from '@mildang/design-system/Input';
import { Button } from '@mildang/design-system/Button';
import Eye from '@mildang/icons/react/eye';
const STORY_DEFAULT_ARGS = { ...({}), ...({ ghost: false }) } as ComponentProps<typeof Input>;
const InputWithAdornmentsExampleRender = (args: ComponentProps<typeof Input>) => {
const inputProps = args;
return (
<div style={{ display: 'flex', flexDirection: 'column', gap: 16, width: 400 }}>
<Input
size="lg"
defaultValue="010-1234-5678"
endAdornment={
<Button size="sm" variant="tertiary">
인증
</Button>
}
{...inputProps}
/>
<Input startAdornment={<Eye />} size="lg" defaultValue="mildang@email.com" {...inputProps} />
<Input endAdornment={<>Kg</>} startAdornment={<Eye />} placeholder="Enter text..." size="xl" />
<Input endAdornment={<>Kg</>} startAdornment={<Eye />} placeholder="Enter text..." size="lg" />
<Input endAdornment={<>Kg</>} startAdornment={<Eye />} placeholder="Enter text..." size="md" />
<Input endAdornment={<>Kg</>} startAdornment={<Eye />} placeholder="Enter text..." size="sm" />
<Input endAdornment={<>Kg</>} startAdornment={<Eye />} placeholder="Enter text..." size="xs" />
</div>
);
};
export default function InputWithAdornmentsExample(props: Partial<ComponentProps<typeof Input>>) {
const mergedProps = { ...STORY_DEFAULT_ARGS, ...props } as ComponentProps<typeof Input>;
return InputWithAdornmentsExampleRender(mergedProps);
}
Ghost
import type { ComponentProps } from 'react';
import { Input } from '@mildang/design-system/Input';
const STORY_DEFAULT_ARGS = { ...({}), ...({ ghost: true }) } as ComponentProps<typeof Input>;
const InputGhostExampleRender = (args: ComponentProps<typeof Input>) => <Input placeholder="Search" size="lg" {...args} />;
export default function InputGhostExample(props: Partial<ComponentProps<typeof Input>>) {
const mergedProps = { ...STORY_DEFAULT_ARGS, ...props } as ComponentProps<typeof Input>;
return InputGhostExampleRender(mergedProps);
}
MaxLength
import { useState } from 'react';
import { Input } from '@mildang/design-system/Input';
import { Text } from '@mildang/design-system/Text';
const InputMaxLengthExample = function Render() {
const MAX = 4;
const [year, setYear] = useState('');
return (
<div style={{ display: 'flex', flexDirection: 'column', gap: 12, width: 320 }}>
<Input
placeholder="ex) 1999"
maxLength={MAX}
inputMode="numeric"
value={year}
onChange={(e) => setYear(e.target.value)}
endAdornment={
<>
{year.length}/{MAX}
</>
}
fullWidth
/>
<Text variant="body-md" color="neutral.text.low">
{MAX}자를 넘겨 입력해도 브라우저가 막습니다.
</Text>
</div>
);
};
export default InputMaxLengthExample;
NativeAttributes
import { Input } from '@mildang/design-system/Input';
const InputNativeAttributesExample = () => (
<div style={{ display: 'flex', flexDirection: 'column', gap: 16, width: 320 }}>
<Input placeholder="ex) 1999" maxLength={4} inputMode="numeric" fullWidth />
<Input placeholder="010-0000-0000" type="tel" autoComplete="tel" fullWidth />
<Input placeholder="읽기 전용" defaultValue="수정 불가" readOnly fullWidth />
</div>
);
export default InputNativeAttributesExample;
CustomStyle
import { Input } from '@mildang/design-system/Input';
const InputCustomStyleExample = () => (
<div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>
<Input width="30px" placeholder="" size="sm" />
<Input width="120px" placeholder="120px" size="md" />
<Input width="300px" placeholder="300px" size="lg" />
<Input width="500px" placeholder="500px" size="lg" />
<Input placeholder="fullWidth" size="lg" fullWidth />
</div>
);
export default InputCustomStyleExample;
StateMatrix
import type { ComponentProps } from 'react';
import { Input } from '@mildang/design-system/Input';
import { Text } from '@mildang/design-system/Text';
/** Figma 상태 매트릭스: 행=상태(Inactive/Hover/Active/Focus/Focus&Text/Disable), 열=타입(Default/Error/Warning/Success) */
const MATRIX_TYPES = [
{ key: 'default', label: 'Default', props: {} },
{ key: 'error', label: 'Error', props: { error: true } },
{ key: 'warning', label: 'Warning', props: { warning: true } },
{ key: 'success', label: 'Success', props: { success: true } },
] as const;
const MATRIX_ROWS = [
{ key: 'inactive', label: 'Inactive', value: '', pseudo: null },
{ key: 'hover', label: 'Hover', value: '', pseudo: 'hover' },
{ key: 'active', label: 'Active', value: 'text', pseudo: null },
{ key: 'focus', label: 'Focus', value: '', pseudo: 'focus' },
{ key: 'focus-text', label: 'Focus & Text', value: 'text', pseudo: 'focus' },
{ key: 'disable', label: 'Disable', value: 'text', pseudo: null, disabled: true },
] as const;
const cellId = (rowKey: string, typeKey: string) => `matrix-${rowKey}-${typeKey}`;
const STORY_DEFAULT_ARGS = { ...({}), ...({ size: 'xl' }) } as ComponentProps<typeof Input>;
const InputStateMatrixExampleRender = (args: ComponentProps<typeof Input>) => (
<div
style={{
display: 'grid',
gridTemplateColumns: `120px repeat(${MATRIX_TYPES.length}, 240px)`,
gap: '16px 24px',
alignItems: 'center',
padding: '8px',
}}
>
<div />
{MATRIX_TYPES.map((type) => (
<Text key={type.key} variant="title-sm-medium" color="neutral.text.low">
{type.label}
</Text>
))}
{MATRIX_ROWS.flatMap((row) => [
<Text key={`${row.key}-label`} variant="title-sm-medium">
{row.label}
</Text>,
...MATRIX_TYPES.map((type) => (
<Input
key={`${row.key}-${type.key}`}
size={args.size}
placeholder="placeholder"
defaultValue={row.value || undefined}
disabled={'disabled' in row ? row.disabled : false}
_containerId={cellId(row.key, type.key)}
fullWidth
{...type.props}
/>
)),
])}
</div>
);
export default function InputStateMatrixExample(props: Partial<ComponentProps<typeof Input>>) {
const mergedProps = { ...STORY_DEFAULT_ARGS, ...props } as ComponentProps<typeof Input>;
return InputStateMatrixExampleRender(mergedProps);
}