Files
HMDesign/docs/components/navigation-menu.md

8.8 KiB
Raw Permalink Blame History

Navigation Menu

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

1. 상태

항목 내용
구현 상태 구현 완료 (현재 HM 규격)
기준일 2026-10-02
기반 shadcn/ui Navigation Menu (Radix NavigationMenu)
대표 Story Components/Navigation/Navigation Menu → All (이름 "Navigation Menu")
보류 아래 §11

2. 적용 근거

  • 참고 근거: 외부 ui_viz Reference (ZIP 미포함)의 기존 테스트 규격에는 Navigation Menu 규격이 없다. 현재 위치(Current) 의미와 Hover/Focus는 독립이라는 ui-viz의 navigation 안내만 참고했다.
  • 현재 HM 규격: 아래 §3~§4. 현재 HM Semantic 체계로 새로 정했다. Dropdown Menu의 운영 원칙(Radix 상태 속성, Escape, focus 복귀, Portal/viewport)만 참고하고 token은 참조하지 않았다.
  • 구현 방식: shadcn / Radix NavigationMenu 구조(Root, List, Item, Trigger, Content, Link, Viewport, Indicator) 유지, theme CSS로 HM 스타일 연결.
  • 역할 구분: 목적지 이동(링크) 중심이다. Dropdown Menu(명령)·Menubar(메뉴 바)와 접근성 모델이 다르다(role=menu가 아니라 disclosure + link).
  • 보류: §11.

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

항목 값
상위 Trigger / Link 높이 34px, padding 0 12px, radius 4px, 14 / 20 / 500, --hm-sem-fg-primary, 항목 gap 4px
Trigger indicator shadcn ChevronDownIcon 12px, open 시 180° 회전
Content / Viewport 면 --hm-sem-bg-surface, 1px --hm-sem-floating-border-color, radius 4px, shadow 0 0 12px rgb(0 0 0 / .2)
Content padding 8px, min-width 240px, 폭은 안의 내용이 정함
Content 안 Link(목적지) 세로 배치, padding 8px 12px, gap 2px, radius 2px. data-description 자식은 12 / 18 / 400 secondary
Indicator(화살표) shadcn 회전 사각형, --hm-sem-floating-border-color
열기 hover(Radix 기본 delay)·click·keyboard. 이동 animation은 shadcn 기본

4. 상태 규격

상태 값
Hover / Focus / Open (Trigger) 배경 --accent, 글자 --accent-foreground. Focus는 ring 모양 0 0 0 3px ring 50% 추가
Link Hover / Focus Trigger와 같은 면
Active Link (active) Radix data-active + aria-current="page". 글자 --hm-sem-action-primary, weight 700, 배경 --accent 45% (hover면 일반 hover 면)
Disabled Trigger opacity: 0.6(이 컴포넌트 값, 전역 Disabled 규칙으로 승격 안 함), cursor: not-allowed, native disabled
Open / Closed Radix data-state, 이동 방향은 data-motion (shadcn animation)

5. API

Radix NavigationMenu props 그대로. export: NavigationMenu, NavigationMenuList, NavigationMenuItem, NavigationMenuTrigger, NavigationMenuContent, NavigationMenuLink, NavigationMenuIndicator, NavigationMenuViewport.

  • NavigationMenu: viewport(기본 true, shadcn). false면 각 Content가 자기 Trigger 아래에 열린다. 출력 data-viewport.
  • NavigationMenuLink: active(현재 위치), asChild로 router Link 조합(router에 의존하지 않음). disabled link는 지원하지 않는다.
  • NavigationMenuTrigger: chevron 내장. disabled는 native 속성.
  • NavigationMenuIndicator: 선택 사용(Story의 viewport 예시에서 사용).
  • 2026-10-06 Visual QA: viewport 모드의 Item은 static으로 두어 Radix List wrapper가 Trigger의 offsetParent가 되도록 한다. viewport={false}에서만 Item의 relative anchor를 유지한다. Indicator에 임의 위치 보정값을 넣지 않는다. IndicatorAlignment verification Story는 서로 다른 label width의 첫·중간·마지막 Trigger와 두 viewport 모드를 검증한다.
  • 대표 Story의 고정 360/300px 내용은 좁은 화면에서 자연 폭을 사용한다. Desktop 폭도 Story frame container에 제한하며, 모바일 inline Content의 absolute 배치는 Story 범위에서만 적용한다(Production CSS 변경 없음).
  • 새 prop은 만들지 않았다. Content 안 title/description은 소비 조합이며 data-description 속성으로 보조 문구를 표시한다.

6. Token

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

height, padding-x, gap, radius, font-size|line-height|font-weight, text, icon-size, hover-background|text, active-background|text|font-weight, background, border-width|color, surface-radius, shadow, content-padding, content-min-width, item-padding|gap|radius, description-*, disabled-opacity. Semantic과 Theme palette(--hm-sem-floating-border-color)만 참조한다. --hm-dropdown-menu-*, --hm-tab-*, --hm-button-*는 참조하지 않는다. 신규 Primitive 없음.

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

Radix 구조·동작(hover open delay, Arrow 키와 Tab 이동, Escape 닫힘, focus 복귀, Viewport 크기 측정, Indicator 위치), ARIA(aria-expanded, aria-controls, aria-current), 이동 animation(data-motion), viewport/non-viewport 구조, chevron, data-slot, cn(..., className).

8. HM에서 변경한 항목

  • shadcn navigationMenuTriggerStyle(rounded-md, h-9, bg-background, hover/focus/open bg-accent/50)과 Content·Viewport의 bg-popover text-popover-foreground rounded-md border shadow 등을 제거하고 theme CSS로 이전.
  • Content 안 Link는 shadcn에서 별도 class로 꾸미던 것을 선택자(content 하위 link)로 처리.
  • Active Link 스타일(색·weight·배경)을 정의(shadcn은 data-[active=true]:bg-accent/50).

9. Storybook

  • 대표 Story All("Navigation Menu"): Viewport(기본)과 viewport={false} 두 구성을 한 페이지에 둔다. 제품(설명 있는 3 링크), 자료(2열 4 링크), 회사(현재 위치 링크), 문의(일반 링크), 준비 중(disabled Trigger).
  • verification: Default, No Viewport.
  • Story의 Content 폭은 style 인라인으로 지정한다(새 Story 파일의 Tailwind 임의값 클래스가 개발 서버에서 생성되지 않는 일이 있었다).

10. 사용자 확정 결정

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

11. 미확정 / 보류

  • 수치(34px, 12px padding, Content 240px 최소 폭, 그림자, Active 표현)는 현재 HM 규격이며 디자인 확정 시 재검토.
  • 모바일: Radix NavigationMenu는 데스크톱 GNB 구조다. 390px에서 Viewport의 폭은 Content 폭(Story에서 360px)을 따라가며 max-width 제한이 없어 우측 끝에 닿았다(가로 overflow는 없음). 모바일 navigation(햄버거, Sheet/Drawer 조합 등)은 GNB/Layout 단계에서 별도 패턴으로 검토한다.
  • disabled link 지원 없음. 필요하면 aria-disabled 규칙을 Pagination과 같은 방식으로 후속 검토.
  • Indicator 사용 여부와 색은 현재 선택 사항이며 별도 규격이 없다.
  • 열림/닫힘 Motion은 shadcn 기본.

12. 관련 파일

packages/ui/src/components/ui/navigation-menu.tsx
packages/ui/src/theme/navigation-menu.css
packages/ui/src/theme.css            (import)
packages/ui/src/index.ts             (export)
src/components/navigation-menu.stories.tsx

13. 검증 상태

  • 2026-10-06 Visual QA: 1280/1024/768/390px에서 제품 Trigger/Arrow center 48.8828/49px, 자료 118.6484/119px. 다른 label width(제품/기술 자료/지원 센터)도 Arrow 오차 절댓값 0.45px 이내. inline 모드의 각 Content가 자기 Trigger 아래에 열림 확인. 대표 Story 두 모드의 열린 패널이 viewport 안에 있고 페이지 가로 overflow 없음. typecheck, build, build-storybook 통과.

  • npm run typecheck, npm run build: 통과(2026-10-02).

  • 실제 interaction(Browser pane): 키보드로 Enter 열림(aria-expanded=true), Tab으로 Content 안 첫 링크, 다음 링크로 이동, Escape로 닫히고 Trigger로 focus 복귀, ArrowRight로 다음 상위 항목으로 이동, 마우스 hover로 해당 Content가 열림, 현재 위치 링크가 aria-current="page"·data-active·weight 700.

  • computed style: Viewport 흰 면, border rgb(222,219,210), radius 4px, shadow 0 0 12px .2. Content 폭이 안의 목록(360px) 폭에 맞춰 376px.

  • 390×844: 열린 Viewport 폭 378px, 좌측 16px에서 시작해 오른쪽 끝에 닿음(가로 overflow 없음). 한계는 §11.

  • 미확인: 닫힘 animation 시각, viewport={false} 구성의 열림(코드 경로는 Radix/shadcn 기본), 두 Content 사이 이동 animation 시각, ArrowDown으로 Content 진입.