113 lines
7.0 KiB
Markdown
113 lines
7.0 KiB
Markdown
# Dropdown Menu
|
|
|
|
현재 HM 구현의 기준 문서. 공통 원칙은 `docs/guidelines/프로젝트-지침.md`(§6, §7), Token 구조 원칙은 `테마-토큰-가이드.md`를 따른다. 이 문서는 Dropdown Menu 고유의 API·Token·상태·결정만 기록한다. Floating 계열 공통 사항은 §14.
|
|
|
|
## 1. 상태
|
|
|
|
| 항목 | 내용 |
|
|
|---|---|
|
|
| 구현 상태 | 구현 완료 (현재 HM 규격) |
|
|
| 기준일 | 2026-10-02 |
|
|
| 기반 | shadcn/ui Dropdown Menu (Radix `DropdownMenu`) |
|
|
| 대표 Story | `Components/Overlay/Dropdown Menu` → `All` (이름 "Dropdown Menu") |
|
|
| 보류 | 아래 §11 |
|
|
|
|
## 2. 적용 근거
|
|
|
|
- **참고 근거**: 외부 ui_viz Reference (ZIP 미포함)의 기존 테스트 규격에는 Dropdown Menu 규격이 없다(인벤토리에 "상세 디자인·API 보류"). Select의 option 목록 패턴(높이·hover 면)만 참고했다.
|
|
- **현재 HM 규격**: 아래 §3~§4. 현재 HM Semantic 체계(surface, fg, stroke, destructive)와 Select option의 highlight 면(shadcn `accent`)에 맞춰 새로 정했다.
|
|
- **구현 방식**: shadcn / Radix Dropdown Menu 구조를 유지하고 theme CSS로 HM 스타일을 연결. 상태는 Radix 속성(`data-highlighted`, `data-disabled`, `data-state`)만 쓴다.
|
|
- **보류**: §11.
|
|
|
|
## 3. 기본 규격 (현재 HM 규격)
|
|
|
|
| 항목 | 값 | 비고 |
|
|
|---|---|---|
|
|
| Surface | `--hm-sem-bg-surface` (White) | Semantic |
|
|
| Border | 1px `--hm-sem-stroke-input-default` | Dialog·Card와 같은 윤곽색 |
|
|
| Radius | `--hm-radius-container` (4px) | 공통 container radius |
|
|
| Shadow | `0 0 12px rgb(0 0 0 / .2)` | HM의 기존 floating 그림자 |
|
|
| Content padding | 4px | |
|
|
| Item | min-height 36px, padding-x 12px, gap 8px, radius 2px | |
|
|
| Typography | 14 / 20 / 400 | Label·Shortcut은 12px (Label 12/18/500) |
|
|
| 전경 | `--hm-sem-fg-primary` / Label·Shortcut `--hm-sem-fg-secondary` | |
|
|
| Separator | 1px `--hm-sem-stroke-input-default`, Content 폭 전체 | |
|
|
| Check / Radio | 16px indicator 열(12px 안쪽), shadcn `CheckIcon`, 8px 채운 원 | shadcn 아이콘 유지 |
|
|
| Sub menu chevron | shadcn `ChevronRightIcon` | |
|
|
|
|
## 4. 상태 규격
|
|
|
|
| 상태 | 값 |
|
|
|---|---|
|
|
| Default | 위 기본 규격 |
|
|
| Highlighted (`data-highlighted`) | 배경 Accent 45%(`--hm-sem-surface-highlight`), 전경 `--accent-foreground` (포인터 hover와 키보드 이동 공통) |
|
|
| Disabled (`data-disabled`) | shadcn `opacity-50`, 포인터 무시, 키보드 이동에서 제외 |
|
|
| Checked / Selected | `ItemIndicator`가 check 또는 원을 표시 (Radix `data-state`) |
|
|
| Sub menu open | SubTrigger `data-state="open"`이 Highlighted와 같은 면 유지 |
|
|
| Destructive (`variant="destructive"`) | 전경 `--hm-sem-action-destructive`, Highlighted 면 `--hm-color-action-destructive-hover` |
|
|
| Focus | 항목 자체 outline 없음(`outline-hidden`), Highlighted 면이 focus 표시 |
|
|
|
|
## 5. API
|
|
|
|
Radix Dropdown Menu props 그대로. export: `DropdownMenu`, `DropdownMenuTrigger`, `DropdownMenuContent`, `DropdownMenuGroup`, `DropdownMenuLabel`, `DropdownMenuItem`, `DropdownMenuCheckboxItem`, `DropdownMenuRadioGroup`, `DropdownMenuRadioItem`, `DropdownMenuSeparator`, `DropdownMenuShortcut`, `DropdownMenuSub`, `DropdownMenuSubTrigger`, `DropdownMenuSubContent`, `DropdownMenuPortal`.
|
|
|
|
- `DropdownMenuContent`: `sideOffset` 기본 4, Radix `align`·`side`·collision props.
|
|
- `DropdownMenuItem`: shadcn `variant="default" | "destructive"`, `inset`. 출력 `data-variant`.
|
|
- Label·CheckboxItem·RadioItem·SubTrigger: `inset`.
|
|
- 출력 속성: `data-slot="dropdown-menu-*"`, Radix `data-state`·`data-highlighted`·`data-disabled`·`data-side`.
|
|
|
|
## 6. Token
|
|
|
|
Component Mapping 위치: `packages/ui/src/theme/dropdown-menu.css` (`--hm-dropdown-menu-*`).
|
|
|
|
`background`, `text`, `border-width`, `border-color`, `radius`, `shadow`, `padding`, `item-height`, `item-padding-x`, `item-gap`, `item-radius`, `font-size`, `line-height`, `font-weight`, `highlight-background`, `highlight-text`, `destructive-text`, `destructive-highlight-background`, `label-*`, `shortcut-*`, `separator-color`, `indicator-size`, `radio-dot-size`. Semantic 또는 Theme palette만 참조하고 다른 컴포넌트의 Component Token은 쓰지 않는다. 신규 Primitive 없음.
|
|
|
|
## 7. shadcn / Radix에서 유지한 항목
|
|
|
|
Radix 구조·ARIA(`role=menu`, `menuitem*`)·키보드(방향키, Home/End, Enter/Space, 오른쪽 방향키 sub menu, Escape, typeahead)·focus 복귀, Portal·positioning·collision, `data-slot`, `cn(..., className)`, open/close animation(`data-open:`/`data-closed:` class), `z-50`, lucide 아이콘.
|
|
|
|
## 8. HM에서 변경한 항목
|
|
|
|
- shadcn의 색·`rounded`·`shadow`·`p-1`·`px-2 py-1.5`·`text-sm` 등 시각 class와 `focus:bg-accent` 계열을 제거하고 theme CSS + `data-highlighted`로 대체.
|
|
- Radio 표시를 별도 아이콘 import 대신 CSS 크기 token을 쓰는 원(`data-slot="dropdown-menu-radio-dot"`)으로 구현.
|
|
- Check / Radio indicator span에 `data-slot="dropdown-menu-item-indicator"` 추가(위치·크기 token용).
|
|
|
|
## 9. Storybook
|
|
|
|
- 대표 Story `All`("Dropdown Menu"): 트리거로 실제 메뉴를 연다(Label, Item + Shortcut, disabled, Separator, Checkbox, Radio Group, Sub menu, destructive).
|
|
- verification: `Open`(열린 상태, fullscreen).
|
|
|
|
## 10. 사용자 확정 결정
|
|
|
|
- 2026-10-02: ui-viz는 참고 자료이며 최종 기준은 현재 HM 구현과 이 문서다(작업 지시). 개별 수치에 대한 별도 결정은 없다.
|
|
|
|
## 11. 미확정 / 보류
|
|
|
|
- 수치(36px item, 12px padding, 4px content padding, 그림자 등)는 현재 HM 규격이며 디자인 확정 시 재검토.
|
|
- Disabled opacity는 shadcn 기본 50 유지(전역 Disabled 규칙 없음).
|
|
- Hover/Highlight 면은 Select와 같은 공통 Accent 45% 정책을 쓴다.
|
|
- icon 크기·check 위치(시작 위치) 등 icon 세부는 shadcn 기본 유지.
|
|
- Motion 규칙은 정의되지 않아 shadcn 기본 animation을 유지.
|
|
- 자체 scroll 처리(긴 목록)는 `max-h` available height + overflow로 둔다. 별도 규격 없음.
|
|
|
|
## 12. 관련 파일
|
|
|
|
```
|
|
packages/ui/src/components/ui/dropdown-menu.tsx
|
|
packages/ui/src/theme/dropdown-menu.css
|
|
packages/ui/src/theme.css (import)
|
|
packages/ui/src/index.ts (export)
|
|
src/components/dropdown-menu.stories.tsx
|
|
```
|
|
|
|
## 13. 검증 상태
|
|
|
|
- `npm run typecheck`, `npm run build`: 통과(2026-10-02).
|
|
- 실제 interaction(Browser pane): Enter로 열기, 방향키 이동(disabled 항목 건너뜀), Enter로 Checkbox 토글, Radio 선택 시 닫힘과 trigger focus 복귀, 오른쪽 방향키로 Sub menu 열림과 첫 항목 focus, Escape로 sub → menu 순서 닫힘과 trigger focus 복귀.
|
|
- computed style: Surface white, border `rgb(222,219,210)`, radius 4px, shadow `0 0 12px .2`, item 36px/14·20, Highlighted `rgb(189,223,212)`.
|
|
- 미확인: Home/End·typeahead 입력, 실제 pointer hover, 좁은 viewport collision 시각.
|
|
|
|
## 14. Floating 계열 공통
|
|
|
|
Popover·Tooltip·Hover Card와 surface(White, 1px pale border, 4px radius, 12px glow) 값이 같지만 각각 `--hm-<component>-*`를 둔다. 공통 Semantic 승격 후보는 `docs/components/popover.md` §14에 함께 기록했다.
|