10 KiB
10 KiB
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에서 변경한 항목
sizeAPI 교체, 기본 Large,data-size추가.- shadcn의 기본 높이/padding/border/ring/dark class 제거 → theme CSS가 담당.
- 일반 Focus는 border 1.5px로 표시, Error 단독은 ring 없음. Error +
:focus-visible만 독립 Focus ring을 표시한다. - Readonly 전용 표현 추가.
hm-inputclass 제거.
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-11 최종 사용자 결정 — Disabled Input Label
- Input Story 소비 조합(
src/components/input.stories.tsx의Specimen)의 Disabled Label은 기존text-muted-foreground→--muted-foreground→--hm-sem-fg-secondary색(#6E6759)을 유지하고,input.disabled일 때만opacity-60을 적용한다. HEX·Semantic Token·공개 Input API는 변경하지 않는다. - Disabled Input 컨트롤
0.6, 소비 Label0.6, 부모 Field1이다. 형제 요소에 각각 적용하여 중첩 opacity를 만들지 않는다. 기본·readOnly·Error Label은 기존1을 유지한다(Disabled가 아닌 경우). - 공통 Label Component의 Disabled
0.5는 유지한다. Helper Text(#6E6759)와 Error Message(#D32F2F)도 기존 구현을 유지하며 이번 변경 대상이 아니다. - 이전 검토의 “Label 100% 유지”는 당시 선택이며 현재 최종 결정은 Disabled Input Story Label
60%다. 아래 2026-10-02 승인과 2026-10-06 검증은 당시 기록으로 보존하며, 이번 Label 정책의 현재 검증을 대신하지 않는다. - 실제 소비 화면은 자동으로 확대 수정하지 않는다. 신규 화면의 공개 Label 재사용·control 연결 계약은 유지하며, 공통 Label의 Disabled 정책을 이 Story 결정으로 대체하지 않는다.
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/InputDisabledopacity=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>대신 nativeinput[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-shadowcolor(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 borderrgb(212, 20, 102)+ Focus shadowcolor(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 정책은 이번 범위에서 유지.
Disabled Input Label 검증 (2026-10-11)
- 실제 Storybook(Chromium/Edge): Disabled Label
rgb(110, 103, 89)/ opacity0.6, Input0.6, 부모와 모든 조상 opacity1. 공통 Label Disabled0.5, Input Default/readOnly/Error Label1유지. - 실제 배경
rgb(245, 240, 229)에서 합성색 약#A49E91, 대비 약2.35:1(원본 100% 약4.93:1). 일반 텍스트4.5:1보다 낮으며, 실제 disabled 컨트롤에 연결된 비활성 UI 라벨의 WCAG 1.4.3 예외와 구분한다. 사용자 확정 정책은 유지하고 가독성 우려를 기록한다. - Default/Disabled/Readonly/Error/Error Message/Playground 및 대표 All 390/768/1280/1440px,
htmlFor/control 연결·편집·readOnly·disabled focus·문서 overflow 확인. Typecheck, UI build, Storybook build 통과. Guard FAIL 0, 원본NOT VERIFIED보존. 검증 범위와 제한.