Files
HMDesign/docs/components/input.md
T

134 lines
8.2 KiB
Markdown

# Input
현재 HM 구현의 기준 문서. 공통 원칙은 `docs/guidelines/프로젝트-지침.md`(§6, §7), Token 구조 원칙은 `테마-토큰-가이드.md`를 따른다. 이 문서는 Input 고유의 API·Token·상태·결정만 기록한다.
## 1. 상태
| 항목 | 내용 |
|---|---|
| 구현 상태 | HM 스타일 적용 완료 (`hm-input` class 없음) |
| 기준일 | 2026-10-02 |
| 기반 | shadcn/ui Input (native `<input>`) |
| 대표 Story | `Components/Form/Input` → `All` (이름 "Input") |
| 보류 | 아래 §11 |
## 2. 적용 근거
- **ui_viz Confirmed**: size·padding-x(input.md §24, §16), border/radius/색(§10, §11, D-005), Focus/Error 표현.
- **ui_viz owner decision**: size별 value·placeholder 글자(§9, §21 `INPUT_VALUE_ROLE_FOLLOWS_SIZE`).
- **HM 사용자 결정**: Disabled opacity `0.6`(2026-10-02, §10).
- **shadcn 유지**: native input 동작, `file:` 스타일 class, disabled 포인터/커서 처리.
- **ui_viz 미정의**: 아래 §11 참조.
## 3. 기본 규격
| Size | Height(min) | Padding-x | Font / Line-height |
|---|---|---|---|
| `small` | 28 | 10 | 12 / 18 |
| `medium` | 34 | 12 | 14 / 20 |
| `large` (기본) | 42 | 12 | 16 / 24 |
- 높이는 `min-height`, 한 줄 텍스트는 가운데.
- Border 1px(`--hm-sem-stroke-input-default`), radius `--hm-radius-input`, face `--hm-sem-bg-surface`, 글자색 `--hm-sem-fg-primary`, weight 400.
- Placeholder: `--hm-sem-fg-placeholder`, `opacity: 1`.
## 4. 상태 규격
| 상태 | 값 | 근거 |
|---|---|---|
| Default | 위 기본 규격 | ui_viz Confirmed |
| Focus (`:focus-visible`) | border 1.5px `--hm-sem-stroke-input-focus`, shadow/glow 없음, padding으로 0.5px 보정해 값이 움직이지 않음 | ui_viz Confirmed |
| Error (`[aria-invalid="true"]`) | border 1.5px `--hm-sem-action-destructive`, ring 없음 | ui_viz Confirmed |
| Error + Keyboard Focus | Destructive border 유지 + HM Focus Semantic 3px / 50% outer ring, `outline: none` | 2026-10-06 사용자 결정 |
| Disabled | White face 유지, `opacity: 0.6`, `cursor: not-allowed`, `pointer-events: none` | face: ui_viz Confirmed / opacity: 사용자 결정 |
| Readonly (`[readonly]`) | 박스 없음(border 0, padding-x 0, 투명 face), dim 없음, 항상 Large 치수 | ui_viz |
| Hover / Active | 정의 없음(별도 스타일 없음) | ui_viz 미정의 |
Focus ring chain은 `--ring` → `--hm-sem-stroke-input-focus` → `--hm-color-border-focus`다. Error border는 `--hm-input-error-border-color` → `--hm-sem-action-destructive`를 따른다. 일반 Focus / Readonly의 기존 표현은 유지하며, editable Invalid + Focus에서 UA outline 의존을 제거했다.
## 5. API
```
Input:
size?: native <input size> (number)
→
size?: "small" | "medium" | "large" 기본 "large"
```
- native `size`(글자 수 폭)를 대체한다. native 속성이 CSS 폭과 무관해 쓰임이 없다는 판단(지침 §6.7).
- 출력 속성: `data-slot="input"`, `data-size`.
- 상태는 새 prop이 아니라 native 속성으로 준다: `aria-invalid`, `disabled`, `readOnly`.
- Field(Label, Required 별표, Helper/Error 문구)는 Input에 포함하지 않는다. 소비 조합이다.
## 6. Token
Component Mapping 위치: `packages/ui/src/theme/input.css` (`--hm-input-*`).
- 재사용한 공통 Semantic: `--hm-radius-input`, `--hm-sem-bg-surface`, `--hm-sem-fg-primary`, `--hm-sem-fg-placeholder`, `--hm-sem-stroke-input-default`, `--hm-sem-stroke-input-focus`, `--hm-sem-action-destructive`(Semantic 참조).
- Input 전용 값: `--hm-input-height-{sm,md,lg}`, `--hm-input-padding-x-*`, `--hm-input-font-size-*`, `--hm-input-line-height-*`, `--hm-input-state-border-width`(1.5px).
- Primitive 신규 추가 없음.
- Button의 높이 Token(`--hm-button-height-*`)·Select 높이와 값이 겹쳐도 alias하지 않는다. 각 ui_viz 규격이 따로 확정한 값이다.
- Disabled opacity는 Token이 아니라 `ui/input.tsx`의 `disabled:opacity-60`으로 적용된다(§11).
## 7. shadcn / Radix에서 유지한 항목
native `<input>` 동작 전체(`type`, `file:` 스타일 class, `placeholder`), `data-slot`, `cn(..., className)`, `transition-colors`, `outline-none`, disabled의 `pointer-events-none`/`cursor-not-allowed`. Radix 사용 없음.
## 8. HM에서 변경한 항목
- `size` API 교체, 기본 Large, `data-size` 추가.
- shadcn의 기본 높이/padding/border/ring/dark class 제거 → theme CSS가 담당.
- 일반 Focus는 border 1.5px로 표시, Error 단독은 ring 없음. Error + `:focus-visible`만 독립 Focus ring을 표시한다.
- Readonly 전용 표현 추가.
- `hm-input` class 제거.
## 9. Storybook
- 대표 Story `All`("Input"): 구역 `sizes`, `default`, `focus`, `error`, `error-message`, `disabled`, `readonly`. Focus는 `play` 함수로 실제 focus를 준다.
- verification(`tags: ["verification"]`): `Default`, `Focus`, `Error`, `InvalidFocus`, `ErrorMessage`, `Required`, `Disabled`, `Readonly`, `Sizes`("Compare Sizes"), `Small`, `Medium`, `Large`, `Playground`(HM 전용).
- Error Message·Required 표시는 Story 안의 조합 예시이며 Input 컴포넌트의 일부가 아니다.
- sidebar는 `All` 하나만 보이는 1뎁스. 운영 규칙은 지침 §6.3, §7 참조.
## 10. 사용자 확정 결정
**2026-10-02**
- Input Disabled opacity `0.6` 확정.
- ui_viz에서 Temporary로 기록된 이력이 있으나, 현재 HM 구현에서는 사용자 결정이 우선한다. 이전의 "Temporary → 미적용" 판단은 이 결정으로 superseded.
- 이 값은 Input에 대한 현재 최종값이다. 전체 디자인 시스템 공통 Disabled opacity로 자동 확대하지 않는다.
- 근거: Select 작업에서 확정된 Disabled 시각 intent와의 정합. Select Trigger도 `0.6`(select.md 참조).
## 11. 미확정 / 보류
- ui_viz 미정의: Hover, Active 표현, Error 메시지 컴포넌트, Input 내부 아이콘/clear 버튼.
- Disabled opacity `0.6`은 Input 한정 사용자 결정이다. 다른 컴포넌트에 적용하지 않는다.
- `file:` 타입 스타일은 shadcn 기본이며 HM 규격 없음.
- Readonly에서 Disabled 조합 동작은 별도로 확인하지 않았다.
## 12. 관련 파일
```
packages/ui/src/components/ui/input.tsx
packages/ui/src/theme/input.css
src/components/input.stories.tsx
src/components/story-board.tsx
```
## 13. 검증 상태
- TypeScript, `npm run build`: 통과(2026-10-02).
- Storybook computed style: `Components/Form/Input` Disabled `opacity` = `0.6` 확인.
- Story: `All`의 구역 7개와 verification Story ID 존재 확인.
- 2026-10-06 ui_viz Storybook 화면 비교(1280/768/390, Chromium): 대표 Story 7구역의 컨트롤·Label·Error 문구 computed style 일치, placeholder 색, Focus·Error 경계, Error+Focus의 outline 유지, 긴 값 가로 스크롤 일치. Readonly는 ui_viz `<p>` 대신 native `input[readonly]`로 같은 42px·16/24 표시. Error Message·Required Story에 ui_viz처럼 placeholder를 넣음(Story만 변경).
- 미확인: 브라우저별 렌더(Chromium 외).
### Invalid + Focus 검증 (2026-10-07)
- Focus ring: `--ring` → `--hm-sem-stroke-input-focus` → `--hm-color-border-focus`. Invalid border: 기존 `--hm-sem-action-destructive`. 새 Runtime Role / Production Error prop / 메시지 컴포넌트 없음.
- Chromium computed style: Invalid border `rgb(211, 47, 47)`, Invalid + Keyboard Focus box-shadow `color(srgb 0.14902 0.4 0.317647 / 0.5) 0px 0px 0px 3px`, `outline-style: none`. Invalid 단독은 `box-shadow: none`.
- Theme Designer UI에서 Focus `#c75b00`, Destructive `#d41466`, Active `#007f73`, Accent `#ffd36d`로 분리. Invalid border `rgb(212, 20, 102)` + Focus shadow `color(srgb 0.780392 0.356863 0 / 0.5) 0px 0px 0px 3px` 확인.
- `npm run typecheck`, `npm run build`, `npm run build-storybook` 통과. 기존 문서 예시 CSS warning 및 Storybook chunk 크기 / plugin timing warning 유지.
- 검증 범위: Chromium 환경. 다른 브라우저의 렌더링은 별도 확인이 필요하다.
- 대표 `All`과 숨김 `InvalidFocus` 확인. 일반 Focus는 border만 변경, Small/Medium/Large 28/34/42px 및 12/14/16px 유지. Readonly border 0 / padding 0, Disabled opacity 0.6 유지. Border CSS 계약 1.5px, 이 브라우저 환경의 computed border-width는 1px으로 정규화; padding 보정은 11.5px 유지. 기존 non-invalid Readonly의 UA outline 정책은 이번 범위에서 유지.