Files
HMDesign/docs/components/command.md
T
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

7.0 KiB

Command

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

1. 상태와 성격

항목 내용
성격 Primitive component (검색 가능한 command/list). Combobox 자체가 아니다
구현 상태 구현 완료 (현재 HM 규격)
기준일 2026-10-02
기반 shadcn/ui Command = cmdk
대표 Story Components/Search & Date/Command → All (이름 "Command")
보류 아래 §11

2. 적용 근거

  • 참고 근거: 외부 ui_viz Reference (ZIP 미포함)의 기존 테스트 규격에는 Command가 없다(Search Field의 후보 목록은 다른 컴포넌트). 참고할 수치가 없었다.
  • 현재 HM 규격: 아래 §3~§4. 현재 HM Semantic/Primitive로 새로 정했다. Input·Popover·Dropdown Menu Token은 참조하지 않는다(Command Input은 Command 전용 Token).
  • 구현 방식: cmdk가 검색 필터링, 방향키/Home/End 이동, Enter 선택, disabled 건너뜀, 그룹, Empty, listbox/option ARIA를 소유한다. HM은 cmdk의 속성(data-selected, data-disabled, [cmdk-group-heading])에 시각을 연결한다.
  • 범위: 전역 Command Palette(CommandDialog)는 만들지 않았다(별도 고급 패턴).
  • 보류: §11.

3. 기본 규격 (현재 HM 규격)

항목 값
Command 흰 면(--hm-sem-bg-surface), 글자 --hm-sem-fg-primary, radius 4px. border·shadow 없음(Popover 등 컨테이너 안에서 쓰는 것을 전제)
Input 높이 40px, padding-x 12px, 14 / 20, 아래 1px --hm-sem-stroke-input-default 구분선, 검색 아이콘 16px --hm-sem-fg-secondary, placeholder --hm-sem-fg-placeholder
List 최대 높이 280px(넘치면 세로 scroll), padding 4px
Item 최소 높이 36px, padding-x 12px, gap 8px, radius 2px, 14 / 20, 아이콘 16px
Group heading 12 / 18 / 500, --hm-sem-fg-secondary, padding 6px 12px
Separator 1px --hm-sem-stroke-input-default, List 폭 전체
Shortcut 12px, --hm-sem-fg-secondary, letter-spacing .05em
Empty padding 24px 12px, 가운데, --hm-sem-fg-secondary

4. 상태 규격

상태 값
Highlighted (data-selected="true") 배경 Accent 45%(--hm-sem-surface-highlight), 글자 --accent-foreground. 포인터 hover와 키보드 이동이 공유
Disabled (data-disabled="true") opacity 0.6(이 컴포넌트 값, 전역 Disabled 규칙으로 승격 안 함), cursor not-allowed, 방향키 이동에서 제외
Empty 필터 결과가 없을 때 CommandEmpty 표시
Focus Input에 있음(outline-hidden). 이동은 Highlighted 면으로 표시

5. API

cmdk props 그대로. export: Command, CommandInput, CommandList, CommandEmpty, CommandGroup, CommandItem, CommandSeparator, CommandShortcut.

  • Command: value/onValueChange(highlight), filter(사용자 정의 필터), shouldFilter, loop, label.
  • CommandItem: value, keywords, disabled, onSelect.
  • CommandInput: Input + 검색 아이콘 wrapper(data-slot="command-input-wrapper")를 포함한다.
  • 필터링은 cmdk 기본(fuzzy) 그대로이며 HM이 검색 알고리즘을 만들지 않았다.
  • 접근성: CommandInput은 role="combobox", aria-expanded, aria-controls(listbox), aria-autocomplete="list"; CommandList는 role="listbox"; CommandItem은 role="option".

6. Dependency

  • cmdk ^1.1.1 (packages/ui에 추가, shadcn Command의 기반). CENTER 패키지에는 추가하지 않았다.

7. Token

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

background, text, radius, input-*(height, padding-x, gap, font, placeholder, icon), divider-color, list-max-height|padding, item-*(height, padding-x, gap, radius, font), highlight-background|text, group-label-*, shortcut-*, empty-*, disabled-opacity. Semantic과 Primitive(--hm-warm-neutral-pale)만 참조한다. 신규 Primitive와 Semantic 없음. 이 CSS는 cmdk 내부 속성에 맞춘 일반 CSS이며 @layer를 쓰지 않는다(className으로 Command의 높이 등을 바꾸는 것은 TSX class 영역).

8. cmdk에서 유지한 항목

필터링과 정렬, 키보드(ArrowUp/Down, Home/End, Enter, disabled 건너뜀), 그룹 숨김(결과 없는 그룹), Empty, data-selected/data-disabled, listbox/option ARIA, 마우스 hover가 highlight를 옮기는 동작.

9. Storybook

  • 대표 Story All("Command"): Search + disabled item(선택 로그는 숨김 Search에만 표시), Groups·icons·shortcut(CalendarIcon, UserIcon, SettingsIcon), Long list(30개, List가 scroll)를 한 페이지에 둔다. 테두리 박스는 Story 조합이다.
  • verification: Search, Grouped.

10. 사용자 확정 결정

  • 2026-10-02: ui-viz는 참고 자료이며 최종 기준은 현재 HM 구현과 이 문서다(작업 지시). 개별 수치에 대한 별도 결정은 없다.

11. 미확정 / 보류

  • 수치(40px Input, 36px Item, 280px List 최대 높이)는 현재 HM 규격이며 디자인 확정 시 재검토.
  • Command Palette(CommandDialog, 전역 단축키 호출)는 별도 패턴으로 남겼다.
  • 로딩 상태(Command.Loading), 중첩 페이지는 스타일링하지 않았다.
  • 선택됨(value) 표시는 Command에 없다(highlight와 다르다). Combobox가 check 아이콘으로 따로 표시한다.
  • Command의 Escape는 Command 자체에서는 하는 일이 없다(Popover/Dialog 안에서는 컨테이너가 닫는다).

12. 관련 파일

packages/ui/src/components/ui/command.tsx
packages/ui/src/theme/command.css
packages/ui/package.json             (dependency: cmdk)
packages/ui/src/theme.css            (import)
packages/ui/src/index.ts             (export)
src/components/command.stories.tsx

13. 검증 상태

  • npm run typecheck, npm run build: 통과(2026-10-02).
  • ARIA(Browser pane): Input role=combobox·aria-expanded=true·aria-controls·aria-autocomplete=list, List role=listbox, Item role=option, disabled Item에 data-disabled="true".
  • keyboard: 첫 항목이 처음부터 highlight, ArrowDown으로 이동(비활성 항목 건너뜀: 바나나 → 포도), Enter로 선택(onSelect 로그 갱신), 그룹 간 이동(ArrowUp 환경설정 → 프로필), End로 마지막 활성 항목(비활성 결제는 제외).
  • 검색: 한글 "바나" 입력 시 바나나만 표시, 결과 없는 "zzz"는 Empty 문구, 입력을 지우면 전체 4개로 복귀하고 첫 항목이 highlight. Escape는 Input focus를 유지(Command 단독에서는 동작 없음).
  • computed style: Input 래퍼 40px, List 최대 280px·padding 4px, Item 36px·padding 0 12px·14/20, Highlighted rgb(189,223,212), Group heading 12px/500 rgb(110,103,89), Shortcut 12px.
  • 미확인: 긴 List의 키보드 scroll 시각, 모바일 폭(Combobox 안에서만 확인), pointer hover 시각, CommandItem의 keywords 외 사용자 정의 filter.