Files
HMDesign/docs/components/select.md
shkim4 4c29894e56 refactor(storybook): simplify component and preview examples
Drop page / section descriptions, state notes and repeated captions from
the representative Stories of 44 components, the Patterns, Center
Graphic and OrgChart pages. Value readouts, spec lists and captions hide
only on the representative page; hidden verification Stories keep them.
Tabs Default API and the Filter Bar draft / applied counts move to the
hidden DefaultApi and DraftApplied Stories; Center Overview is hidden
with its direct URL kept. Story IDs are unchanged.

Align the component, pattern and OrgChart docs with the pages, point the
quality reference check at the DraftApplied Story, and make the P8
styles check expect no section header on the preview-only Expanded page.
2026-10-23 00:28:05 +09:00

12 KiB
Raw Permalink Blame History

Select

현재 HM 구현의 기준 문서. 공통 원칙은 docs/guidelines/프로젝트-지침.md(§6, §7), Token 구조 원칙은 테마-토큰-가이드.md를 따른다. 이 문서는 Select 고유의 API·Token·상태·결정만 기록한다.

1. 상태

항목 내용
구현 상태 HM 스타일 적용 완료 (hm-select-trigger class 없음)
기준일 2026-10-02
기반 shadcn/ui Select, Radix Select
대표 Story Components/Form/Select → All (이름 "Select")
보류 Item Disabled, 일반 Focus 두께 등 (§11)

2. 적용 근거

  • ui_viz Confirmed: size/높이(select.md §1.1 D-004, §8), 색·border(§10, §1.3, D-005, M06), indicator glyph(§7, 사용자 제공 Source), Trigger/Content 연결 윤곽(§8).
  • ui_viz BASELINE_VALUE: padding-x 12, gap 12, option 높이 42(§8, §17) — "현재 적용 계약"으로 표기된 값.
  • HM 사용자 결정: Trigger Disabled opacity 0.6(2026-10-02, §10).
  • shadcn/Radix 유지: 구조·접근성·positioning(§7).
  • HM 사용자 결정(2026-10-06): Error는 Destructive border, Keyboard Focus는 독립 Focus Semantic ring.

3. 기본 규격

Size 외곽 Trigger 내부 높이 Trigger 글자
medium 34 32 14 / 20 / 400
large (기본) 44 42 16 / 24 / 400
  • 높이는 min-height = 내부 높이 + 1px border × 2.
  • Padding-x 12, gap 12, border 1px --hm-sem-stroke-input-default, radius --hm-radius-input, face --hm-sem-bg-surface.
  • Placeholder([data-placeholder]): --hm-sem-fg-placeholder.
  • Trigger와 Value는 min-width: 0; 긴 placeholder/선택값은 한 줄 ellipsis로 줄고 18px indicator를 밀지 않는다. ui_viz 공개 Story에 없던 현재 HM 복원력 규칙이며 parity 판정 근거로 쓰지 않는다.
  • Icon: HM glyph, 18×18 viewBox, M5 7 L9 11 L13 7, stroke 1.50542, 색 #2d2d2d(--hm-select-indicator-color).
  • Content: Trigger와 같은 폭(--radix-select-trigger-width), border 1px focus 색, bottom일 때 아래쪽만 radius.
  • Option: Trigger의 size를 따른다. min-height 42(두 size 공통, ui_viz §8), padding-x 12, 글자 Medium 14/20/400(Medium Trigger와 동일) · Large 16/24/400, radius 0. ui_viz는 Medium Option 글자 Role을 TBD로 남겼고, 2026-10-06 Trigger 값에 맞추기로 했다(사용자 요청). 높이·폭은 size로 바꾸지 않는다(Content = Trigger 외곽 폭).
  • size 전달: SelectTrigger size가 유일한 지정처다. Select가 내부 context로 받아 Portal된 SelectContent의 data-size로 노출하고, select.css가 [data-slot="select-content"][data-size]로 Option profile을 정한다. SelectContent·SelectItem에는 size prop이 없다.

4. 상태 규격

상태 값 근거
Default 위 기본 규격 ui_viz Confirmed
Focus (:focus) border 색 → --hm-sem-stroke-input-focus, 두께 1px 유지 ui_viz Confirmed (1.5px 두께는 ui_viz FOLLOW_UP으로 보류)
Open ([data-state="open"]) border 색 → focus 색, 위쪽 모서리만 round(리스트와 이어짐) ui_viz Confirmed
Selected (Item [data-state="checked"]) Hover와 같은 배경 면(--hm-sem-surface-highlight, Accent 45%), border·check icon 없음 표현: ui_viz Confirmed / 색: shadcn Token(accent)
Highlighted (Item focus:/data-highlighted) Accent 45%(--hm-sem-surface-highlight) 위와 동일
Disabled (Trigger :disabled) Default paint 유지, opacity: 0.6, cursor: not-allowed opacity: 사용자 결정
Disabled (Item data-disabled) shadcn 기본 opacity-50, 포인터 차단 미검증(§11)
Invalid (aria-invalid="true") border 1px --hm-sem-action-destructive, Error ring 없음 2026-10-06 사용자 결정
Invalid + Keyboard Focus (:focus-visible) Destructive border 유지 + Focus Semantic 3px / 50% outer ring 위와 동일
Invalid + Open Trigger Destructive border, 연결 seam은 Neutral. Content의 기존 Surface / Focus outer border / Accent 45% Option 유지 위와 동일
Disabled Invalid Destructive border + 기존 opacity 0.6, focus 불가 위와 동일

5. API

SelectTrigger size:
  "sm" | "default"
  →
  "medium" | "large"      기본 "large"

SelectContent sideOffset:
  shadcn 기본 4
  →
  기본 -1  (Trigger와 1px border를 공유)

SelectItem:
  children 앞의 ItemIndicator(check icon) 제거. children만 ItemText로 렌더.
  • Select, SelectValue, SelectGroup, SelectLabel, SelectSeparator, 스크롤 버튼은 shadcn API 그대로.
  • 출력 속성: data-slot="select-trigger", data-size. HM 전용 error/open/focused prop은 없다. 상태는 Radix 속성(data-state, data-placeholder, data-highlighted, data-side)과 :disabled로 적용한다.

6. Token

Component Mapping 위치: packages/ui/src/theme/select.css (--hm-select-*).

  • 재사용한 공통 Semantic: --hm-radius-input(radius), --hm-sem-bg-surface, --hm-sem-fg-primary, --hm-sem-fg-placeholder, --hm-sem-stroke-input-default, --hm-sem-stroke-input-focus.
  • Select 전용 값: --hm-select-control-height-{md,lg}(32/42), --hm-select-padding-x, --hm-select-gap, --hm-select-option-height, --hm-select-font-size-*, --hm-select-disabled-opacity, --hm-select-indicator-color.
  • indicator는 --hm-select-indicator-color → --hm-sem-palette-indicator를 참조한다(Default #2d2d2d). 신규 Primitive 없음.
  • Input·Button과 값(42 등)이 겹쳐도 alias하지 않는다. 각 ui_viz 규격이 따로 확정한 값이다.
  • --hm-select-disabled-opacity: 0.6은 Select 전용 Component Token이며 Input의 Disabled와 공유하지 않는다.

7. shadcn / Radix에서 유지한 항목

Radix Root/Trigger/Portal/Content/Viewport/Item/ItemText 구조, 키보드 조작·typeahead·focus 관리, Portal, popper positioning(position="popper", align="start"), 스크롤 버튼, 열림/닫힘 animation class, data-slot, cn(..., className), Trigger의 native aria-invalid 전달, Item의 data-disabled 처리.

8. HM에서 변경한 항목

  • Size API(sm|default → medium|large), 기본 large, data-size.
  • sideOffset 기본 -1, Content 폭을 Trigger 폭에 맞춤, Trigger/Content 연결형 윤곽.
  • chevron 아이콘을 HM glyph(inline SVG)로 교체.
  • Item check indicator 제거, Selected를 배경 면으로 표현.
  • shadcn Trigger의 높이·padding·border·focus ring class 제거 → theme CSS가 담당.
  • hm-select-trigger class 제거.
  • 변경하지 않음: 스크롤 버튼의 lucide chevron(ChevronUp/Down).

9. Storybook

  • 대표 Story All("Select"): Sizes(Medium / Large 비교, 각 Trigger로 실제 목록 열기) → States(selected, disabled, disabled-placeholder) → Invalid / Focus(invalid, invalid-disabled). 2026-10-22 Overview의 default·로드 시 열린 open 예시는 대표 화면에서 뺐다. 열린 목록은 숨김 Open, 크기별 수치 목록은 숨김 Sizes("Compare Sizes")에서 확인한다. size 생략 시 Large(§5)는 그대로다.
  • verification(tags: ["verification"]): Default, Open, Selected, Disabled, Sizes("Compare Sizes"), Medium, Large, LongContent, Scroll, Playground(HM 전용).
  • Disabled Story 구성: Trigger 비활성 상태들(placeholder 포함).
  • InvalidFocus verification Story: 앞/뒤 버튼 사이의 Invalid Trigger와 Disabled Invalid Trigger. Tab / Shift+Tab, Enter / Space, Escape 및 focus return을 실제 키보드로 확인한다.
  • LongContent와 Scroll은 ui_viz 공개 Story parity가 아니라 좁은 폭·긴 값·Radix scroll 회귀를 확인하는 HM 전용 Story다.
  • sidebar는 All 하나만 보이는 1뎁스. 운영 규칙은 지침 §6.3, §7 참조.

10. 사용자 확정 결정

2026-10-02

  • Select Trigger Disabled opacity 0.6 확정(select.css의 --hm-select-disabled-opacity).
  • 같은 날 Input Disabled 0.6도 확정되었다(input.md 참조). 현재 적용 범위는 Input / Select이며 전체 디자인 시스템 Disabled opacity로 자동 확대하지 않는다.
  • Select Item의 Disabled opacity는 이 결정에 포함하지 않는다. Trigger와 같은 규격이라고 판단하지 않는다.

11. 미확정 / 보류

  • Item Disabled: 현재 shadcn 기본 opacity-50. 사용자 결정·ui_viz 근거 없음. 미검증.
  • FOLLOW_UP(ui_viz): Focus/Open 상태의 border 1.5px 두께.
  • ui_viz 미정의: Group/Label/Separator 규격, 스크롤 버튼 규격, item-aligned position. Error 표현은 2026-10-06 HM 사용자 결정이 우선한다.
  • BASELINE_VALUE: padding-x 12, gap 12, option 42는 "현재 적용 계약"이며 별도 Confirmed 결정은 아니다.
  • Selected/Highlighted는 현재 공통 Accent 45% 정책을 쓴다. ui_viz Temporary 표기는 도입 당시 근거다.

12. 관련 파일

packages/ui/src/components/ui/select.tsx
packages/ui/src/theme/select.css
src/components/select.stories.tsx
src/components/story-board.tsx

13. 검증 상태

  • 2026-10-05: npm run typecheck, npm run build, npm run build-storybook 통과. 기존 generated CSS의 bg-[var(...)] 경고와 500kB chunk warning은 유지된다.
  • Storybook computed style: Medium/Large Trigger 34/44px, padding-x 12px, radius 4px, border 1px, Option 42px·16/24/400, Disabled Trigger opacity 0.6 확인.
  • Open: Trigger와 Content 폭 동일, sideOffset=-1 접점, Focus/Open #123328, Content border/radius/shadow와 Portal listbox 확인.
  • Interaction: click open, ArrowUp/Down, Home/End, typeahead, Enter select, Escape, focus return, Disabled open 차단, 32개 Option의 wheel/keyboard scroll 확인.
  • Responsive: 1280/768/390px에서 popup clipping·문서 가로 overflow 없음. 390px의 280px Trigger에서 긴 placeholder/선택값 ellipsis와 indicator 비중첩 확인.
  • Story: All의 공개 구역 4개와 숨김 LongContent/Scroll verification Story 확인.
  • 미확인/보류: Item Disabled 시각, collision으로 side="top"이 된 연결 윤곽의 별도 디자인(원 ui_viz도 viewport edge flip TBD), 브라우저별 렌더 차이.

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 환경. 다른 브라우저의 렌더링은 별도 확인이 필요하다.
  • 숨김 InvalidFocus에서 Closed Invalid / Tab Focus / Invalid Open / 방향키 강조 / Disabled Invalid 확인. Invalid border computed 1px; Tab 전후 shadow none → 3px Focus ring. Tab은 Disabled를 건너뛰고, Shift+Tab으로 복귀. Enter / Space open, ArrowDown 이동, Escape close 및 Trigger focus return 확인.
  • Invalid + Open은 Trigger Destructive border와 Neutral seam rgb(222, 219, 210)을 동시에 유지. Popup white Surface, 외곽 rgb(199, 91, 0)(Focus), Selected / Highlighted color(srgb 1 0.827451 0.427451 / 0.45)(Accent) 확인. Popup에 Error 색 없음. 대표 All 회귀 확인.