feat(ui): standardize LNB sizing and active depth effect

- Adopt the official LNB desktop spec as package defaults: 240px column,
  14px menu text, 48px 1-depth rows and 42px 2/3-depth rows, with new
  item/subitem padding-block and profile min-height tokens.
- Match --hm-lnb-current-depth to the Storybook Manager selected item:
  sampled soft inset falloff (left/top/bottom) and a fade over the last
  quarter, keeping the concave corners and content join.
- Drop the size overrides from the LNB Story CSS and update the LNB, GNB
  and Dashboard docs, AI guides and the theme verification baseline.
This commit is contained in:
shkim4 committed 2026-11-09 21:34:28 +09:00
1 parent 89f265ae2f
commit e42b67c53a
9 files changed
+95 -75

No files matched your search

+3 -3
View File
@@ -162,9 +162,9 @@ ui-viz에서 확인한 구조(실제 파일: `compositions/dashboard-variant-spe
| 영역 | ui-viz 구조 | 현재 HM 대응 | 이번 구현 |
|---|---|---|---|
| 조립 | Variant A(LNB 272 + 콘텐츠), Variant B(GNB 70 + 콘텐츠), Variant C(Compact 48). **GNB+LNB 동시 사용 예 없음** | `DashboardLayout` | slot 방식. 둘 다 / 하나만 |
| 조립 | Variant A(LNB 240 + 콘텐츠. 2026-11-09 이전 272), Variant B(GNB 70 + 콘텐츠), Variant C(Compact 48). **GNB+LNB 동시 사용 예 없음** | `DashboardLayout` | slot 방식. 둘 다 / 하나만 |
| GNB | 70px green, 콘텐츠와 12px 접점 | `GNB` | slot `header` |
| LNB | 272px green, 콘텐츠와 18px 접점 | `LNB` | slot `sidebar` |
| LNB | 240px green(2026-11-09 이전 272), 콘텐츠와 18px 접점 | `LNB` | slot `sidebar` |
| Content surface | `#F5F0E5`, padding 34, 접점 쪽 radius(LNB 18 / GNB 12), 그림자 `-8px 0 18px`(LNB) · `0 -8px 18px`(GNB) rgba(7,30,24,.18), 별도 border 없음 | 신규 | `DashboardMain` |
| 스크롤 | "메뉴/헤더는 고정, 콘텐츠 영역에서만 스크롤"(Confirmed). `overflow-y:auto`, `overscroll-behavior: contain` | 신규 | `DashboardMain`이 스크롤 소유 |
| Page heading | breadcrumb 12px(정적 `p`, 컴포넌트 아님) → 제목 28 → 설명, space-between·align end·gap 24, **하단 20px** | Breadcrumb + 신규 Pattern | `PageHeader` |
@@ -260,7 +260,7 @@ Compact / Sidebar mobile hide: NONE
| 항목 | ui-viz | 현재 HM | 분류 |
|---|---|---|---|
| GNB 70 / LNB 272 | 같음 | `--hm-gnb-height` / `--hm-lnb-width` | MATCHED |
| GNB 70 / LNB 240 | 같음(LNB 폭은 2026-11-09 공식 규격 채택, ui-viz 272와 다름) | `--hm-gnb-height` / `--hm-lnb-width` | MATCHED |
| 콘텐츠 면 색·padding 34 | `#F5F0E5`, 34 | 같음 | MATCHED |
| 접점 radius (LNB 18 / GNB 12), shadow | 같음 | 같음. 소유를 Dashboard로 이동 | MATCHED |
| 헤더·메뉴 고정, 콘텐츠만 스크롤 | 같음 | `DashboardMain` 스크롤 | MATCHED |
+2 -2
View File
@@ -183,7 +183,7 @@ src/patterns/gnb.stories.tsx
공용 `@hm-design/ui/theme.css`의 opt-in HTML attribute 계약:
- 프레임: `data-hm-gnb-layout="sidebar"`. 소비자가 높이를 지정하며 Grid가 GNB의 자연 높이와 남은 본문 높이를 배분한다.
- 본문: 프레임의 직계 `data-hm-gnb-body`. Desktop은 기존 `--hm-lnb-width` 열 + 가용 콘텐츠 열, Mobile은 콘텐츠 한 열이다.
- 본문: 프레임의 직계 `data-hm-gnb-body`. Desktop은 기존 `--hm-lnb-width` 열 + 가용 콘텐츠 열, Mobile은 콘텐츠 한 열이다. 열 폭과 항목 크기는 LNB 공식 규격(2026-11-09: 240px, 14px, 1뎁스 48px·2/3뎁스 42px)을 그대로 따르며 GNB 전용 override는 두지 않는다.
- Sidebar: 본문의 직계 `<LNB data-hm-gnb-sidebar>`. 기존 `data-slot="lnb"`는 유지한다. 이 Reference 범위에서 본문과 같은 배경, 세로 divider 한 개를 사용한다. Green은 Primary, `data-hm-color="brown"`은 기존 Brown 팔레트로 선택·Hover를 표현한다. 펼침 화살표는 유지하며 아이콘은 선택적으로 전달한다. 신규 AI GNB_ONLY에는 Sidebar를 추가하지 않는다.
- Main: 본문의 직계 `<main data-hm-gnb-main>`. 공용 CSS가 면·접점·스크롤을 제공하며 콘텐츠 padding은 소비자가 정한다. GNB의 상단 접점과 LNB의 측면 접점은 기존 값을 재사용한다.
@@ -284,4 +284,4 @@ export function Example() {
사용자 메뉴와 콘텐츠 padding은 기존 GNB 사용 예제에 따라 소비자가 추가한다. Theme Source, LNB 원본, Runtime 계약, 공개 API는 변경하지 않는다. 공통 요약은 [AGENTS.md](../../AGENTS.md), 탐색 경로는 [Reference Index](../guidelines/component-pattern-reference.md)를 따른다.
검증(2026-10-08, 기존 Storybook 6024): 1440px Sidebar 272px / Green Light 2, 2·3Depth 선택·그룹 Enter/Space·Hover·선택 경로·메뉴 스크롤 확인. 768px·375px에서 GNB 56px / Sidebar 숨김 / Main 전체 폭 / 흰 Sheet 1개 / 링크 44px·14px / 선택 시 닫기·Escape·포커스 복귀 확인. 열린 Sheet에서 Desktop 복귀 시 닫힘과 선택 경로 보존 확인. 기존 GNB Overview·LNB 대표 메뉴·Dashboard Header computed style 비교 동일, 검사한 화면의 Console error 없음. 앱 TypeScript 검사 통과. 전체 프로젝트 회귀 테스트와 실기기 터치 검증은 수행하지 않았다.
검증(2026-10-08, 기존 Storybook 6024): 1440px Sidebar 272px(당시 값. 2026-11-09부터 LNB 규격 240px) / Green Light 2, 2·3Depth 선택·그룹 Enter/Space·Hover·선택 경로·메뉴 스크롤 확인. 768px·375px에서 GNB 56px / Sidebar 숨김 / Main 전체 폭 / 흰 Sheet 1개 / 링크 44px·14px / 선택 시 닫기·Escape·포커스 복귀 확인. 열린 Sheet에서 Desktop 복귀 시 닫힘과 선택 경로 보존 확인. 기존 GNB Overview·LNB 대표 메뉴·Dashboard Header computed style 비교 동일, 검사한 화면의 Console error 없음. 앱 TypeScript 검사 통과. 전체 프로젝트 회귀 테스트와 실기기 터치 검증은 수행하지 않았다.
+16 -12
View File
@@ -81,10 +81,10 @@ Collapsible의 trigger/content는 `asChild`로 자체 `button`/`div`를 써서 C
| 항목 | 명세 | 구현 | 분류 |
|---|---|---|---|
| 글자 | 1·2뎁스 18/28/700, 3뎁스 18/24/500, 선택 700 | 같음 | MATCHED |
| 3뎁스 행 | 최소 48, 상하 12, 링크 padding-left 88(2뎁스 68 + 20) | 같음 (1·2뎁스 56 유지) | MATCHED |
| 글자 | 1·2뎁스 18/28/700, 3뎁스 18/24/500, 선택 700 | 크기만 14로 변경: 1·2뎁스 14/28/700, 3뎁스 14/24/500, 선택 700 유지 | INTENTIONAL_CHANGE (2026-11-09) |
| 3뎁스 행 | 최소 48, 상하 12, 링크 padding-left 88(2뎁스 68 + 20) | 최소 42, 상하 9, padding-left 88 유지 (1뎁스 48, 2뎁스 42) | INTENTIONAL_CHANGE (2026-11-09) |
| 3뎁스 글자 장식 | 외곽선·그림자 없음 | 같음 | MATCHED |
| 긴 이름 | 줄바꿈, 행 높이 증가 | 48 / 72 / 96 (1·2·3줄), ellipsis 없음, 가로 overflow 0 | MATCHED |
| 긴 이름 | 줄바꿈, 행 높이 증가 | 3뎁스 기준 42 / 66 / 90 (1·2·3줄, 24px 줄 + 상하 9), ellipsis 없음, 가로 overflow 0. 2026-11-09 이전 값은 48 / 72 / 96 | INTENTIONAL_CHANGE (2026-11-09) |
| 선택 | Beige + `--hm-sem-action-primary`, 오른쪽 곡선 | 기존 current 규칙 그대로(폭 +1, 위·아래 오목 곡선) | MATCHED |
| 상위 경로 | 1·2뎁스 노랑, 접혀도 유지 | `current` → `--hm-yellow-accent` | MATCHED |
| 연결선 | 3뎁스만, 1px, 세로선 x 68, 가로 12, 글자까지 8, 행 세로 중앙, 마지막 행 중앙에서 끝 | 행마다 background 2겹(세로 `1px × 100%`, 마지막 행 `1px × 50%`, 가로 `12 × 1` at `calc(50% - 0.5px)`). DOM·tab stop·aria 없음 | MATCHED / IMPLEMENTATION_CHANGE(명세의 "배경 레이어" 방식) |
@@ -153,11 +153,11 @@ LNB Mode가 Desktop Brand/Profile과 Mobile Header/Sheet Profile을 담당한다
| 항목 | ui-viz | 최종 HM | 분류 |
|---|---|---|---|
| 폭 | track 272, visual 290(오른쪽 18 bleed) | 열 272(`--hm-lnb-width`), 뒤로 18(`--hm-lnb-join`) 같은 색 연장 | MATCHED (연장은 `::after`) |
| 폭 | track 272, visual 290(오른쪽 18 bleed) | 열 240(`--hm-lnb-width`, 2026-11-09 공식 규격 채택), 뒤로 18(`--hm-lnb-join`) 같은 색 연장 | INTENTIONAL_CHANGE (폭만 ui-viz 272와 다름, 연장은 `::after`) |
| 배경 | 90° 5-stop `#123328/#205241/#266651/#249473/#266651` 0/30/50/90/100%, 트랙 폭, 트랙 밖 `#266651` | 같음 (`--hm-green-*`) | MATCHED |
| 상단 | 위 28, 브랜드 padding 0 10 22, 메뉴 위 20 | 위 28, 브랜드 inset 30(=20+10), 아래 22, 메뉴 위 20 | MATCHED |
| 브랜드 | 로고 조건부, 위 로고·아래 서비스명, eyebrow 11/700, 이름 17 | 같음 | MATCHED |
| 항목 | 18/28/700, 최소 56, padding 14 12 14 18, White, 아이콘 20 opacity .5, 글자 테두리 1.5px + 그림자 `1px 2px 1px` | 같음 | MATCHED |
| 항목 | 18/28/700, 최소 56, padding 14 12 14 18, White, 아이콘 20 opacity .5, 글자 테두리 1.5px + 그림자 `1px 2px 1px` | 14/28/700, 1뎁스 최소 48(padding 상하 10), 2뎁스 최소 42(상하 7). 색·아이콘·글자 테두리는 같음 | INTENTIONAL_CHANGE (2026-11-09) |
| hover | Black 10%, 콘텐츠 경계까지, 시작 쪽 radius 4 | 같음 | MATCHED |
| current | Beige + `#123328`, 왼쪽 radius 8, 오른쪽 20+1 연장, 위·아래 18 오목 곡선, 안쪽 깊이 그림자(마지막 25% fade), 글자 효과 없음 | 같음. 깊이는 span 대신 background gradient 3겹으로 근사 | MATCHED / IMPLEMENTATION_CHANGE |
| nested(2뎁스) | 상위 = disclosure 버튼, 화살표 접힘 → 펼침 90°, 펼친 그룹 Black 8% + 1px `#266651` 선 + 왼쪽 radius 8, 하위 padding-left 68, 하단 8, 하위 선택 시 상위 노랑 `#FFC600` | 같음. HM Collapsible(Radix) 사용 | MATCHED / IMPLEMENTATION_CHANGE |
@@ -175,13 +175,15 @@ LNB Mode가 Desktop Brand/Profile과 Mobile Header/Sheet Profile을 담당한다
| Token | 값 |
|---|---|
| `--hm-lnb-width` | 272px (1023px 이하에서 0px) |
| `--hm-lnb-width` | 240px (1023px 이하에서 0px) |
| `--hm-lnb-join` | 18px. 콘텐츠 둥근 모서리·bleed |
| `--hm-lnb-background` / `-background-end` | 5-stop gradient / `#266651` |
| item | min-height 56, 18/28/700, gap 12, 아이콘 20, 글자 테두리 1.5px |
| item | 1뎁스 min-height 48(`--hm-lnb-item-min-height`) + padding-block 10(`--hm-lnb-item-padding-block`), 14/28/700(`--hm-lnb-item-font-size`), gap 12, 아이콘 20, 글자 테두리 1.5px |
| `--hm-lnb-subitem-*` | 2뎁스(그룹 안 직속 링크·중첩 그룹 trigger) min-height 42(`-min-height`), padding-block 7(`-padding-block`), padding-start 68 |
| `--hm-lnb-profile-min-height` | 48px. Profile 높이는 3뎁스 행과 독립이다 |
| current | `--hm-sem-bg-content` + `--hm-sem-action-primary`, radius 8 0 0 8 |
| group | open face Black 8%, 선 1px `--hm-sem-palette-green-light-2`, 하위 padding-start 68, current 글자 `--hm-sem-palette-yellow-accent` |
| `--hm-lnb-third-*` | min-height 48, padding-block 12, text padding-start 88(메뉴 행 기준), line-height 24, weight 500 / current 700, connector x `= --hm-lnb-subitem-padding-start`(68)·length 12·width 1, 모든 상태에서 `--hm-sem-palette-green-tint` 40%. 실제 link는 connector 끝부터 시작 |
| `--hm-lnb-third-*` | min-height 42, padding-block 9, text padding-start 88(메뉴 행 기준), line-height 24, weight 500 / current 700, connector x `= --hm-lnb-subitem-padding-start`(68)·length 12·width 1, 모든 상태에서 `--hm-sem-palette-green-tint` 40%. 실제 link는 connector 끝부터 시작 |
새 Primitive: `--hm-yellow-accent: #ffc600`(`primitives.css`). ui-viz `color.action.accent-on-green`이며 HM 팔레트에 없어 추가했다. 그 외 새 Semantic은 없다.
@@ -212,11 +214,11 @@ viewport 높이 shell에서 모바일 Header와 main을 세로 flex로 배분할
> HISTORICAL_RECORD: 아래 날짜별 geometry·상태 측정은 당시 기록이다. 현재 링크 interaction 범위·connector 색은 §3a/§5, Profile interaction은 §7을 따른다.
- 1280: current 항목 x 20→273, 높이 56, 18/28/700, Beige `#F5F0E5`/`#123328`, radius `8 0 0 8`, 그룹·하위 x 20→272. 하위 선택 시 상위 `rgb(255,198,0)`, 접힌 채여도 유지. 긴 이름은 줄바꿈(112px), 스크롤 영역은 메뉴만 스크롤하고 profile은 아래 22px 고정. 그룹 trigger Enter로 펼침.
- 1280(당시 값. 2026-11-09부터 공식 규격은 열 240, 1뎁스 48·2/3뎁스 42, 14px): current 항목 x 20→273, 높이 56, 18/28/700, Beige `#F5F0E5`/`#123328`, radius `8 0 0 8`, 그룹·하위 x 20→272. 하위 선택 시 상위 `rgb(255,198,0)`, 접힌 채여도 유지. 긴 이름은 줄바꿈(112px), 스크롤 영역은 메뉴만 스크롤하고 profile은 아래 22px 고정. 그룹 trigger Enter로 펼침.
- 1000px: 열 `display:none`, 가로 overflow 없음. 390px은 GNB 모바일 메뉴로 대체.
- `npm run typecheck`, `npm run build` 통과. 기존 primitive Story 변화 없음.
- 3뎁스(2026-10-06, Storybook): 위 §3a 수치를 computed style로 확인(1280 열 272, 3뎁스 x 20 → 272/선택 273, 그룹 2개 모두 x 20·폭 252, 안쪽 그룹 배경 투명·`::before` 없음). 키보드: Enter로 바깥 그룹 접힘(노랑 유지, 3뎁스·선 사라짐), Space로 다시 펼침(안쪽 그룹 열림 유지), Tab → 안쪽 그룹 Enter로 접힘. trigger는 `button` + `aria-expanded`/`aria-controls`, 선택 링크 `aria-current="page"`, focus-visible 흰 outline. 기존 Selected Child 수치 변화 없음(2뎁스 68/56/700, 그룹 하단 8, 선 1px).
- 3뎁스(2026-10-06, Storybook): 위 §3a 수치를 computed style로 확인(당시 1280 열 272, 3뎁스 x 20 → 272/선택 273, 그룹 2개 모두 x 20·폭 252, 안쪽 그룹 배경 투명·`::before` 없음). 키보드: Enter로 바깥 그룹 접힘(노랑 유지, 3뎁스·선 사라짐), Space로 다시 펼침(안쪽 그룹 열림 유지), Tab → 안쪽 그룹 Enter로 접힘. trigger는 `button` + `aria-expanded`/`aria-controls`, 선택 링크 `aria-current="page"`, focus-visible 흰 outline. 기존 Selected Child 수치 변화 없음(2뎁스 68/56/700, 그룹 하단 8, 선 1px).
- 스크롤 소유(2026-10-06, Storybook): 열 = flex column, brand·profile `flex: none`, `LNBNav`만 `flex: 1 1 auto; min-height: 0; overflow-y: auto`(열 overflow 없음, 높이는 Story shell / Dashboard Layout이 결정). 메뉴 위 20을 nav margin 2 + padding 18에서 nav padding 20(`--hm-lnb-nav-padding-top`)으로 옮겨 스크롤 영역이 brand 바로 아래에서 시작(첫 항목 y 그대로). 측정: Scroll(460) nav 93.7→370 = brand bottom → profile top, client 276 / scroll 830, 최하단 마지막 항목 bottom 351.7(= nav bottom − 18); Third Level Scroll(460) client 276 / scroll 990, 3뎁스 선택 행·곡선·연결선 함께 스크롤; Dashboard Third Level 1280·1024×600 nav 163.7→510, client 346 / scroll 526, 최하단 491.7. 1023px 열 `display:none`, 가로 overflow 없음.
@@ -230,7 +232,9 @@ viewport 높이 shell에서 모바일 Header와 main을 세로 flex로 배분할
Collapsible, Navigation Menu 등 기존 primitive 코드·theme CSS는 수정하지 않았다. `primitives.css`에 `--hm-yellow-accent` 한 줄만 추가했다.
**공용 패키지 기본값 vs Storybook 전용 오버라이드:** 이 문서의 공용 패키지 기본 규격(열 272px, 메뉴 18px, 행 56px 등)과 `packages/ui`·Theme Token은 변경하지 않았다. `Patterns/Layout/LNB` 대표 Story(`src/patterns/lnb.stories.tsx`)만 `src/patterns/lnb.stories.css`로 PC 열 너비 240px(1024px 이상, 최소 너비 212px), 메뉴 폰트 14px, 행 높이 depth1 48px·depth2·3 42px를 Storybook 표시용으로 덮어쓴다(`.hm-lnb-story` 범위 안에서만 적용하며 소비 프로젝트에는 영향이 없다).
**공식 기본 규격 (2026-11-09):** PC 열 240px, 메뉴 14px, 행 높이 1뎁스 48px·2/3뎁스 42px를 `packages/ui/src/theme/lnb.css`의 공식 기본값으로 채택했다. 이전 값(272px, 18px, 56px / 3뎁스 48px)은 위 날짜별 검증 기록에만 남는다. 모바일 규격(`--hm-lnb-mobile-*`)과 `DashboardSidebar`(자체 `--hm-dashboard-sidebar-width` 272px)는 변경하지 않았다. GNB ONLY 내부 Sidebar는 LNB 부품과 `--hm-lnb-width`를 재사용하므로 같은 규격(240px / 14px / 48px / 42px)을 따른다. 소비 프로젝트는 크기를 Storybook 화면이 아니라 `--hm-lnb-*` 토큰에서 읽어야 하며, 새 CSS 변수는 `--hm-lnb-item-padding-block`, `--hm-lnb-subitem-min-height`, `--hm-lnb-subitem-padding-block`, `--hm-lnb-profile-min-height` 4개다.
**Storybook 전용 표시(`src/patterns/lnb.stories.css`):** `Patterns/Layout/LNB` 대표 Story만 `.hm-lnb-story` 범위 안에서 최소 너비 212px, 브랜드 아래 padding 8px, Profile 글자(14/12/700), 구분선을 덮어쓴다. 크기 규격은 더 이상 덮어쓰지 않는다.
## 10. 남은 차이
@@ -243,7 +247,7 @@ Collapsible, Navigation Menu 등 기존 primitive 코드·theme CSS는 수정하
| 실기기, 1024~1280 사이 시각 | 미확인 |
| 4뎁스 이상 | 명세 없음. 3뎁스 규칙만 정의(더 깊이 중첩하면 3뎁스 모양이 반복된다) |
| 선택 경로 전체 연결선을 선택색으로 칠할지 | 현재 모든 connector는 Green Tint 40%를 유지한다(§3a/§5). 선택은 Beige 면 + Primary 글자 + 700 weight로 표현하며, 경로 전체 선의 선택색은 별도 결정 전까지 적용하지 않는다 |
| LNB 모바일 Sheet 그룹 접기·상위 current 표시 | 현재 링크 목록 방식. Desktop 18px / Mobile 14px 유지 |
| LNB 모바일 Sheet 그룹 접기·상위 current 표시 | 현재 링크 목록 방식. Desktop 14px(2026-11-09, 이전 18px) / Mobile 14px 유지 |
| LNB Mobile Header 공개 API | 구현 완료. GNB/Dashboard 의존성 없음 |
## 11. 관련 파일