- 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.
115 lines
8.0 KiB
Markdown
115 lines
8.0 KiB
Markdown
# Web(@hm-design/ui) 디자인 규칙
|
|
|
|
출처: `@hm-design/ui/theme.css`(원본 `src/theme/primitives.css`·`default.css`·컴포넌트별 `theme/*.css`)에 실제 선언된 값. 이 문서와 그 CSS에 없는 값은 확정값이 아닙니다. 새 UI는 아래 변수를 `var(--…)`로 읽고 HEX·px 값을 새로 만들지 않습니다. 참고할 변수가 없을 때만 [AI_USAGE.md](./AI_USAGE.md) §1-5 ③으로 구성하고 "AI 구성 값 — 디자인 확인 필요"로 보고합니다.
|
|
|
|
- 토큰 범위: `:root, [data-hm-theme]`. Runtime Theme(`@hm-design/ui/theme`)가 같은 변수를 바꿉니다.
|
|
- Light/Dark 분기 없음. 컴포넌트 CSS에 `html`·`body`·`*` 규칙을 추가하지 않습니다.
|
|
- 이름을 추측하지 않습니다. 특히 `--hm-sem-text-*`, `--hm-sem-border-*`, `--hm-sem-stroke-divider`는 **선언되어 있지 않습니다**(아래 표의 이름을 씀). 없는 토큰을 fallback 색으로 감추지 않습니다.
|
|
- Tailwind utility로는 shadcn 매핑 utility(`bg-card`, `text-primary`, `text-muted-foreground` 등)를 쓸 수 있습니다. HM 값과 다를 수 있는 임의 utility 색(`bg-green-700` 등)은 쓰지 않습니다.
|
|
|
|
## 1. 기본 팔레트 (primitives → `--hm-sem-palette-*`)
|
|
|
|
| 역할 | 값 | 변수 |
|
|
|---|---|---|
|
|
| Green(주색) | `#164434` | `--hm-sem-palette-green-default` |
|
|
| Green 진한 글자 | `#11372D` | `--hm-sem-palette-green-dark-1` |
|
|
| Green Focus·Active | `#266651` | `--hm-sem-palette-green-light-2` |
|
|
| Green Tint(강조 면) | `#BDDFD4` | `--hm-sem-palette-green-tint` |
|
|
| Beige(콘텐츠 면) | `#F5F0E5` | `--hm-sem-palette-beige-light` |
|
|
| Warm neutral | dark `#6E6759`, mid `#9A9284`, pale `#DEDBD2`, muted `#F4F1EA` | `--hm-sem-palette-warm-neutral-dark` / `-mid` / `-pale` / `-muted` |
|
|
| Red | `#D32F2F` | `--hm-sem-palette-red-danger` |
|
|
| Gray placeholder | `#999999` | `--hm-sem-palette-neutral-gray-500` |
|
|
| White / Black | `#FFFFFF` / `#000000` | `--hm-sem-palette-white` / `--hm-sem-palette-black` |
|
|
|
|
Brown·Orange 계열 팔레트(`--hm-sem-palette-brown-*`, `--hm-sem-palette-orange-*`)도 선언되어 있으며 Button `secondary`(Brown)·`modify`(Orange) 역할에 쓰입니다. 새 UI는 팔레트보다 §2의 Semantic 변수를 우선합니다.
|
|
|
|
## 2. Semantic 색·면 (새 UI가 읽는 변수)
|
|
|
|
| 역할 | 변수 | 기본 |
|
|
|---|---|---|
|
|
| 페이지·콘텐츠 배경 | `--hm-sem-bg-content` | Beige |
|
|
| 카드·팝업 표면 | `--hm-sem-bg-surface` | White |
|
|
| 보조 면 | `--hm-sem-bg-subtle` | warm-neutral-muted |
|
|
| 브랜드 배경(gradient) | `--hm-sem-bg-brand`, `--hm-sem-bg-brown`, `--hm-sem-bg-orange` | 세로 gradient(GNB·Brand 버튼 면) |
|
|
| 기본 글자 | `--hm-sem-fg-primary` | green-dark-1 |
|
|
| 보조 글자 | `--hm-sem-fg-secondary` | warm-neutral-dark |
|
|
| placeholder | `--hm-sem-fg-placeholder` | gray-500 |
|
|
| 일반 테두리 | `--hm-sem-stroke-default` | warm-neutral-mid |
|
|
| 입력 테두리 | `--hm-sem-stroke-input-default` | warm-neutral-pale |
|
|
| Focus 테두리 | `--hm-sem-stroke-input-focus` | green-light-2 |
|
|
| 주 액션 / 위 글자 | `--hm-sem-action-primary` / `--hm-sem-on-action-primary` | Green / White |
|
|
| 취소 액션 | `--hm-sem-action-cancel` | warm-neutral-dark |
|
|
| 위험 액션 | `--hm-sem-action-destructive` | Red |
|
|
| 오류 상태(잠정) | `--hm-sem-status-error` | `#B3261E` |
|
|
| 강조 면 / 위 글자 | `--hm-sem-accent` / `--hm-sem-on-accent` | green-tint / `#123328` |
|
|
| 선택(Active) / 위 글자 | `--hm-sem-state-active` / `--hm-sem-on-state-active` | green-light-2 / White |
|
|
| 하이라이트 | `--hm-sem-surface-highlight` | accent 45% |
|
|
| Floating(Popover·Menu·Tooltip 류) | `--hm-sem-floating-background`, `-border-width`(1px), `-border-color`, `-radius`, `-shadow` | White, 입력 테두리, 4px, `0 0 12px` 검정 20% |
|
|
| Overlay(Dim) | `--hm-sem-overlay-background` | 검정 10% |
|
|
|
|
## 3. Typography
|
|
|
|
| 항목 | 값 |
|
|
|---|---|
|
|
| 글꼴 | `--hm-font-family-base`: "Noto Sans KR", "Malgun Gothic", sans-serif (글꼴 파일 포함) |
|
|
| Weight | **400 / 500 / 700만**(600 없음). `--hm-font-weight-medium`(500), `--hm-font-weight-bold`(700). 카드·Dialog 제목 700 |
|
|
| Card 제목 | 20 / 28px / 700 (`--hm-card-title-*`) |
|
|
| Dialog | 제목 20 / 28 / 700, 설명 14 / 20, 본문 16 / 24 (`--hm-dialog-*`) |
|
|
| Button | sm 12/18, default 13/20, lg 15/22. Brand 700, Standard(solid·outline) 500 |
|
|
| Input | small 12, medium 14, large 16 (weight 400) |
|
|
|
|
## 4. 크기·간격·Radius
|
|
|
|
| 항목 | 값 | 변수 |
|
|
|---|---|---|
|
|
| 기본 control 높이 | 34px | `--hm-control-height-md` |
|
|
| Button 높이(min) | sm 28 · default 34 · lg 42, padding-x 10 · 14 · 18 | — |
|
|
| Input 높이 | small 28 · medium 34 · large 42(기본), padding-x 10 · 12 · 12 | `--hm-input-*` |
|
|
| Select Trigger 높이 | medium 34 · large 44(기본) | — |
|
|
| Control radius | 4px | `--hm-radius-control-md` → `--hm-radius-button`, `--hm-radius-input`, `--hm-radius-select`, `--hm-radius-container` |
|
|
| Card | border 1px, padding 24px, radius 4px, 그림자 없음 | `--hm-card-*` |
|
|
| LNB(Desktop) | 열 240px, 메뉴 14/28/700, 1뎁스 행 48 · 2·3뎁스 행 42, Profile 48, 콘텐츠 접점 18. 모바일 Header 56 · 링크 44 | `--hm-lnb-width`, `--hm-lnb-item-*`, `--hm-lnb-subitem-*`, `--hm-lnb-third-*`, `--hm-lnb-profile-min-height`, `--hm-lnb-join` |
|
|
| Dialog | radius 8px, padding 24px, Header 아래 16px, Footer 위 16px, 버튼 간격 8px, 그림자 `0 0 12px` 검정 20% | `--hm-dialog-*` |
|
|
|
|
## 5. 상태
|
|
|
|
| 상태 | 규칙(실제 CSS) |
|
|
|---|---|
|
|
| Button Hover·Pressed(brand·solid) | 면 위 검정 20% inset overlay. transition·눌림 이동 없음 |
|
|
| Button Hover(outline) | 역할 색으로 채우고 흰 글자. Red outline은 Red 8% 면 |
|
|
| Disabled | Button·Input·Select `opacity: 0.6` + `cursor: not-allowed`, 기본 면 유지 (전역 Disabled 토큰 아님) |
|
|
| Input Focus | 테두리만 1.5px `--hm-sem-stroke-input-focus`(그림자·glow 없음) |
|
|
| Invalid | `aria-invalid="true"` → 오류 테두리, 키보드 Focus 시 3px 50% ring |
|
|
| ReadOnly(Input) | 상자 없이 글자만, 흐리지 않음 |
|
|
| Focus(그 밖) | shadcn 기본 `focus-visible` ring 유지 |
|
|
| 선택 | `--hm-sem-state-active` / `--hm-sem-on-state-active` |
|
|
|
|
새 상호작용 UI는 이 표의 같은 상태 규칙을 따르고, 가능하면 상태를 가진 기존 컴포넌트(`Button`, `Toggle`, `Input`)를 안쪽에 써서 상태를 다시 만들지 않습니다.
|
|
|
|
## 6. 스크롤바
|
|
|
|
- 스크롤 영역이 필요하면 `ScrollArea`(Radix)를 씁니다. 막대는 Hover·스크롤 중에 표시됩니다.
|
|
- 값: 두께 10px(`--hm-scroll-area-scrollbar-size`), thumb `--hm-sem-stroke-default`, Hover `--hm-sem-fg-secondary`, radius 9999px.
|
|
- 브라우저 기본 스크롤바를 CSS(`::-webkit-scrollbar`)로 새로 꾸미지 않습니다.
|
|
|
|
## 7. Overlay·Panel 레이아웃
|
|
|
|
- 모달 = `Dialog`(Header · Body(스크롤) · Footer). 확인 = `AlertDialog`. 측면 상세 = `Sheet`. 하단 작업 = `Drawer`. 비모달 보조 = `Popover`.
|
|
- 새 Panel 모양이 필요하면 `Card`(White `surface` / Beige `content`)로 만듭니다. Floating 모양이 꼭 필요하면 `--hm-sem-floating-*`만 읽습니다.
|
|
- Dim은 `--hm-sem-overlay-background`.
|
|
- Scoped Theme(`[data-hm-theme]`)는 body Portal(SelectContent·PopoverContent·DatePicker 팝업)에 자동 전달되지 않습니다.
|
|
|
|
## 8. 아이콘
|
|
|
|
- `lucide-react`(패키지 의존성)의 아이콘을 씁니다. Button 안 아이콘 기본 크기는 16px(`size-4`, shadcn 기본).
|
|
- 아이콘 색은 글자색을 상속합니다. 아이콘 전용 색 토큰은 없습니다.
|
|
|
|
## 9. 새 컴포넌트 체크리스트
|
|
|
|
1. 같은 역할의 기존 컴포넌트·Pattern이 없는지 [COMPONENT_CATALOG.md](./COMPONENT_CATALOG.md)에서 확인했다.
|
|
2. 소비 프로젝트에 작성했고 패키지 파일·`hm-*`/`data-slot` 규칙을 덮어쓰지 않았다.
|
|
3. 면·글자·테두리·radius는 §2·§4 변수만 읽는다. HEX·임의 px 없음.
|
|
4. 버튼·입력·선택은 기존 컴포넌트를 안쪽에 썼다(상태 재구현 없음).
|
|
5. Font Weight 400/500/700, 글꼴은 상속(`--hm-font-family-base`).
|
|
6. Label·키보드·Focus 복귀·Disabled를 확인했다.
|