# Input

Input 컴포넌트는 사용자로부터 텍스트 입력을 받기 위한 기본 컴포넌트입니다. 다양한 스타일, 크기 및 기능을 지원합니다.

> 💡 **Form 구성 시 내장 prop 사용을 권장합니다**
>
> 이 컴포넌트는 `label`, `helperText` 등의 Form 요소를 자체적으로 지원합니다.
> Form을 구성할 때 Typography로 별도의 label이나 helperText를 만드는 대신, 컴포넌트의 내장 prop을 사용하세요.

```tsx
<Input />
```

| Field                       | Description | Default |
| --------------------------- | ----------- | ------- |
| color                       | —           | —       |
| size                        | —           | —       |
| variant                     | —           | —       |
| label                       | —           | —       |
| helperText                  | —           | —       |
| error                       | —           | —       |
| required                    | —           | —       |
| disabled                    | —           | —       |
| value                       | —           | —       |
| defaultValue                | —           | —       |
| onChange                    | —           | —       |
| name                        | —           | —       |
| placeholder                 | —           | —       |
| type                        | —           | —       |
| startDecorator              | —           | —       |
| endDecorator                | —           | —       |
| enableClearable             | —           | —       |
| disableTogglePasswordButton | —           | —       |
| sx                          | —           | —       |
| className                   | —           | —       |

## 기본형

Input의 기본 형태입니다. 사용자의 텍스트 입력을 받는 단일 라인 필드입니다.

```tsx
<Input />
```

## 변형(Variants)

Input은 네 가지 변형을 지원합니다: `solid`, `soft`, `outlined`, `plain`

```tsx
<>
  <Input placeholder="Type in here…" variant="solid" />
  <Input placeholder="Type in here…" variant="soft" />
  <Input placeholder="Type in here…" variant="outlined" />
  <Input placeholder="Type in here…" variant="plain" />
</>
```

## 크기(Sizes)

Input은 세 가지 크기를 지원합니다: `sm`, `md`, `lg`

```tsx
<>
  <Input {...args} size="lg" />
  <Input {...args} size="md" />
  <Input {...args} size="sm" />
</>
```

## 레이블 및 도움말 텍스트

Input 컴포넌트에 `label`과 `helperText` 속성을 추가하여 사용자에게 추가 정보를 제공할 수 있습니다.

### 레이블(Label)

`label` 속성을 사용하여 Input 위에 레이블을 표시할 수 있습니다.

```tsx
<>
  <Input placeholder="Type in here…" label="Label" />
</>
```

### 도움말 텍스트(Helper Text)

`helperText` 속성을 사용하여 Input 아래에 추가 정보를 제공할 수 있습니다.

```tsx
<>
  <Input placeholder="Type in here…" helperText="I'm helper text" />
</>
```

## 상태(States)

### 비활성화(Disabled)

`disabled` 속성을 사용하여 Input을 비활성화할 수 있습니다.

```tsx
<Input disabled />
```

### 오류 상태(Error)

`error` 속성을 사용하여 오류 상태를 표시할 수 있습니다.

```tsx
<>
  <Input placeholder="Invalid input" label="label" error />
</>
```

### 필수 값(Required)

`required` 속성을 사용하여 필수 입력 필드임을 표시할 수 있습니다.

```tsx
<Input
  placeholder="Type in here..."
  helperText="I'm helper text"
  label="Label"
  required
/>
```

## 장식자(Decorators)

Input 컴포넌트는 `startDecorator`와 `endDecorator` 속성을 통해 입력 필드의 시작과 끝 부분에 아이콘, 버튼 또는 기타 요소를 추가할 수 있습니다.

```tsx
<Stack spacing={3}>
  <Input placeholder="Amount" startDecorator={{
    dollar: '$',
    baht: '฿',
    yen: '¥'
  }[currency]} endDecorator={<React.Fragment>
  <Divider orientation="vertical" />
  <Select variant="plain" value={currency} options={[{
    value: 'dollar',
    label: 'US dollar'
  }, {
    value: 'baht',
    label: 'Thai baht'
  }, {
    value: 'yen',
    label: 'Japanese yen'
  }]} onChange={e => setCurrency(e.target.value!)} slotProps={{
    listbox: {
      variant: 'outlined'
    }
  }} sx={{
    mr: -1.5,
    '&:hover': {
      bgcolor: 'transparent'
    }
  }} />
</React.Fragment>} sx={{
width: 300
}} />
<Input placeholder="Your location" startDecorator={<Button variant="soft" color="neutral" startDecorator={<LocationOn />}>
  Locate
</Button>} sx={{
width: 300
}} />
</Stack>
```

`endDecorator`와 `enableClearable`을 함께 사용하면 다음과 같습니다:

```tsx
<Input
  placeholder="Type in here…"
  label="Label"
  enableClearable
  endDecorator={<Chip color="primary">Hi</Chip>}
/>
```

## 지울 수 있는 입력(Clearable Input)

`enableClearable` 속성을 사용하여 Input에 내용을 지울 수 있는 버튼을 추가할 수 있습니다.

```tsx
<>
  <Input placeholder="Type in here…" label="Label" enableClearable />
</>
```

## 비밀번호 입력(Password Input)

`type="password"` 속성을 사용하면 비밀번호 입력 필드가 생성되며, 자동으로 비밀번호 표시/숨김 토글 버튼이 추가됩니다.

```tsx
<Stack spacing={3}>
  <Typography level="body-md">Default password input with toggle button:</Typography>
  <Input {...args} placeholder="Enter password" type="password" label="Password" />

  <Typography level="body-md">Disabled password input:</Typography>
  <Input {...args} placeholder="Enter password" type="password" label="Disabled Password" disabled />

  <Typography level="body-md">Password input with toggle button disabled:</Typography>
  <Input {...args} placeholder="Enter password" type="password" label="No Toggle" disableTogglePasswordButton />
</Stack>
```

### 비밀번호 토글 비활성화

비밀번호 입력 필드의 토글 버튼은 `disableTogglePasswordButton` 속성을 사용하여 비활성화할 수 있습니다.

```tsx
<Stack spacing={3}>
  <Typography level="body-md">Default password input with toggle button:</Typography>
  <Input {...args} placeholder="Enter password" type="password" label="Password" />

  <Typography level="body-md">Disabled password input:</Typography>
  <Input {...args} placeholder="Enter password" type="password" label="Disabled Password" disabled />

  <Typography level="body-md">Password input with toggle button disabled:</Typography>
  <Input {...args} placeholder="Enter password" type="password" label="No Toggle" disableTogglePasswordButton />
</Stack>
```

### 비밀번호 입력의 제한 사항

비밀번호 입력 필드(`type="password"`)에서는 `endDecorator`를 사용할 수 없습니다. 이는 비밀번호 토글 버튼이 해당 위치를 차지하기 때문입니다.

```tsx
<Stack spacing={3}>
  <Typography level="body-md">When type="password", the endDecorator is not supported:</Typography>
  <Input {...args} placeholder="Enter password" type="password" label="Password with endDecorator (will show warning)" endDecorator={<Chip color="primary">Hi</Chip>} />

  <Typography level="body-md">The password toggle button takes precedence:</Typography>
  <Input {...args} placeholder="Enter password" type="password" label="Password" />
</Stack>
```

## 폼 컨트롤(Form Control)

Input 컴포넌트는 `label`, `helperText`, `error` 속성을 조합하여 완전한 폼 컨트롤을 구성할 수 있습니다.

```tsx
<>
  <Input placeholder="Type in here..." helperText="I'm helper text" label="Label" />
  <Input placeholder="Invalid input" helperText="I'm helper text" label="Label" error />
</>
```

## 상태 관리

### 제어 컴포넌트(Controlled Component)

Input은 React의 제어 컴포넌트로 사용할 수 있습니다. `value`와 `onChange` 속성을 사용하여 상태를 관리합니다.

```tsx
<>
  <Input placeholder="Type in here…" label="Label" enableClearable value={value} onChange={handleChange} />
</>
```

### 비제어 컴포넌트(Uncontrolled Component)

`defaultValue` 속성을 사용하여 비제어 컴포넌트로도 사용 가능합니다.

## 접근성(Accessibility)

Input 컴포넌트는 웹 접근성 표준을 준수합니다:

- 적절한 레이블과 연결되어 있습니다.
- 키보드 탐색이 가능합니다.
- 오류 상태는 시각적으로 명확하게 표시됩니다.

## 테스팅(Testing)

### Testing Library 참고사항

- `type="password"` 속성을 가진 Input을 Testing Library로 찾을 때는 항상 `textbox` 역할(role)로 찾아야 합니다.
- 이는 ARIA 명세에 따라 `password` 입력이 특별한 role을 갖지 않고 기본적으로 `textbox` role을 사용하기 때문입니다.

```tsx
// 비밀번호 입력 필드를 찾는 예시
const passwordInput = screen.getByRole('textbox', { name: /비밀번호/i });
```

**참고 이슈:**

- [W3C ARIA: Should there be a role=password?](https://github.com/w3c/aria/issues/935)
- [Testing Library: How to find password inputs](https://github.com/testing-library/dom-testing-library/issues/567)
