- Usage types are now Web / SW (general mode, viewer mode) / OrgChart / mixed. Shared AI_GUIDE step 1 asks for the SW mode only when the request or the project setting (HMDesign 사용 유형: SW 일반 | SW 뷰어) leaves it open; examples B0/B1/B2 cover "HMDesign SW로 화면을 만들어 주세요", general and viewer. - Missing-component handling in three steps (reuse in the chosen type/mode -> build with that mode's tokens -> HMDesign-consistent style, reported as "AI 구성 값 — 디자인 확인 필요"), plus SW general/viewer separation rules. - sw/ai: AI_USAGE §0 mode selection, catalog §8 lists all 33 SWViewer* exports, DESIGN_RULES §11 viewer tokens, PATTERNS 7 viewer composition; examples B/F marked as general mode. ui/ai and org-chart/ai aligned with the new types. - AGENTS_SNIPPET, AGENTS.md and MAINTAINING updated; copies synced. - scripts/ai-docs.mjs: shared-copy check ignores CRLF/LF (core.autocrlf=true checks out packages/sw as LF and the rest as CRLF). - Verification record updated (code samples typechecked, built and rendered).
114 lines
7.7 KiB
Markdown
114 lines
7.7 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(주색) | `#123328` | `--hm-sem-palette-green-default` |
|
|
| Green 진한 글자 | `#0A221D` | `--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-*` |
|
|
| 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를 확인했다.
|