style(admin): unify text color hierarchy with foundation gray

This commit is contained in:
shkim4 committed 2026-11-11 14:33:58 +09:00
1 parent 5ffe56a9aa
commit 0486cecd5c
26 files changed
+186 -52

No files matched your search

+28 -8
View File
@@ -6,9 +6,9 @@
|---|---|---|---|---|---|
| `color.bg.content` | `--hm-sem-bg-content` | `#f5f0e5` | 콘텐츠 면 | Yes | gnb, lnb |
| `color.bg.surface` | `--hm-sem-bg-surface` | `#ffffff` | 기본/카드/입력 면 | Yes | checkbox, radio, switch, slider, badge, table, input, select, button, gnb |
| `color.fg.primary` | `--hm-sem-fg-primary` | `#11372d` | 주요 텍스트 | Yes | calendar, pagination, badge, table, input, select, gnb |
| `color.fg.secondary` | `--hm-sem-fg-secondary` | `#6e6759` | 보조 텍스트 | Yes | calendar, pagination, badge, table, gnb |
| `color.fg.placeholder` | `--hm-sem-fg-placeholder` | `#999999` | Placeholder | Yes | input, select |
| `color.fg.primary` | `--hm-sem-fg-primary` | `#212121` | 주요 텍스트 | Yes | calendar, pagination, badge, table, input, select, gnb |
| `color.fg.secondary` | `--hm-sem-fg-secondary` | `#616161` | 보조 텍스트 | Yes | calendar, pagination, badge, table, gnb |
| `color.fg.placeholder` | `--hm-sem-fg-placeholder` | `#757575` | Placeholder | Yes | input, textarea, select, combobox, date-picker, command |
| `color.action.primary` | `--hm-sem-action-primary` | `#164434` | Strong / Primary ink | Yes | checkbox/radio hover, slider Hover/Drag halo, pagination current, badge default, button outline, navigation current ink |
| `color.action.cancel` | `--hm-sem-action-cancel` | `#6e6759` | 공개 취소 역할 | Yes | Button `variant="cancel"` + `appearance="outline"` |
| `color.action.destructive` | `--hm-sem-action-destructive` | `#d32f2f` | 오류/위험 역할 | Yes | checkbox, radio, badge, input, button |
@@ -51,7 +51,7 @@
| `color.palette.green-light-2` | `--hm-sem-palette-green-light-2` | `#266651` | 선택적 Theme 팔레트: green-light-2 | Yes | checkbox, radio, switch, slider, progress, calendar, table, input, select, gnb, lnb |
| `color.palette.green-light-1` | `--hm-sem-palette-green-light-1` | `#205241` | 선택적 Theme 팔레트: green-light-1 | Yes | table, button, lnb |
| `color.palette.green-default` | `--hm-sem-palette-green-default` | `#164434` | 선택적 Theme 팔레트: green-default | Yes | checkbox, radio, slider, calendar, pagination, badge, select, button, gnb, lnb |
| `color.palette.green-dark-1` | `--hm-sem-palette-green-dark-1` | `#11372d` | 선택적 Theme 팔레트: green-dark-1 | Yes | calendar, pagination, badge, table, input, select, button, gnb |
| `color.palette.green-dark-1` | `--hm-sem-palette-green-dark-1` | `#11372d` | 선택적 Theme 팔레트: green-dark-1 | Yes | brand gradient stop, button border, tabs arrow (2026-11-11부터 텍스트 기본값 아님) |
| `color.palette.green-dark-2` | `--hm-sem-palette-green-dark-2` | `#0b2b23` | 선택적 Theme 팔레트: green-dark-2 | Yes | Theme palette / adapter |
| `color.palette.brown-light-2` | `--hm-sem-palette-brown-light-2` | `#897445` | 선택적 Theme 팔레트: brown-light-2 | Yes | button |
| `color.palette.brown-light-1` | `--hm-sem-palette-brown-light-1` | `#604f32` | 선택적 Theme 팔레트: brown-light-1 | Yes | button |
@@ -62,12 +62,12 @@
| `color.palette.orange-default` | `--hm-sem-palette-orange-default` | `#cc5200` | 선택적 Theme 팔레트: orange-default | Yes | button |
| `color.palette.warm-neutral-light` | `--hm-sem-palette-warm-neutral-light` | `#e0dace` | 선택적 Theme 팔레트: warm-neutral-light | Yes | slider, progress |
| `color.palette.warm-neutral-mid` | `--hm-sem-palette-warm-neutral-mid` | `#9a9284` | 선택적 Theme 팔레트: warm-neutral-mid | Yes | checkbox, radio, switch, badge |
| `color.palette.warm-neutral-dark` | `--hm-sem-palette-warm-neutral-dark` | `#6e6759` | 선택적 Theme 팔레트: warm-neutral-dark | Yes | calendar, pagination, badge, table, gnb |
| `color.palette.warm-neutral-dark` | `--hm-sem-palette-warm-neutral-dark` | `#6e6759` | 선택적 Theme 팔레트: warm-neutral-dark | Yes | action cancel, chart series side (2026-11-11부터 텍스트 기본값 아님) |
| `color.palette.beige-light` | `--hm-sem-palette-beige-light` | `#f5f0e5` | 선택적 Theme 팔레트: beige-light | Yes | gnb, lnb |
| `color.palette.red-danger` | `--hm-sem-palette-red-danger` | `#d32f2f` | 선택적 Theme 팔레트: red-danger | Yes | checkbox, radio, badge, input, button |
| `color.palette.white` | `--hm-sem-palette-white` | `#ffffff` | 선택적 Theme 팔레트: white | Yes | checkbox, radio, switch, slider, calendar, pagination, badge, table, input, select, button, gnb, lnb |
| `color.palette.black` | `--hm-sem-palette-black` | `#000000` | 선택적 Theme 팔레트: black | Yes | checkbox, switch, select, button, gnb, lnb |
| `color.palette.neutral-gray-500` | `--hm-sem-palette-neutral-gray-500` | `#999999` | 선택적 Theme 팔레트: neutral-gray-500 | Yes | input, select |
| `color.palette.neutral-gray-500` | `--hm-sem-palette-neutral-gray-500` | `#999999` | 선택적 Theme 팔레트: neutral-gray-500 | Yes | 호환 유지(2026-11-11부터 Placeholder 기본 연결 없음) |
| `color.palette.green-tone-1` | `--hm-sem-palette-green-tone-1` | `#1f8265` | 선택적 Theme 팔레트: green-tone-1 | Yes | button, gnb |
| `color.palette.green-tone-2` | `--hm-sem-palette-green-tone-2` | `#165c47` | 선택적 Theme 팔레트: green-tone-2 | Yes | button, gnb |
| `color.palette.green-tone-3` | `--hm-sem-palette-green-tone-3` | `#114838` | 선택적 Theme 팔레트: green-tone-3 | Yes | button, gnb |
@@ -99,8 +99,13 @@
| `color.palette.orange-dark-1` | `--hm-sem-palette-orange-dark-1` | `#bc4c00` | 2026-10-11 사용자 확정 브랜드 단계 | Yes | Color Reference / 선택적 Theme palette |
| `color.palette.orange-dark-2` | `--hm-sem-palette-orange-dark-2` | `#883700` | 2026-10-11 사용자 확정 브랜드 단계 | Yes | Color Reference / 선택적 Theme palette |
| `color.palette.orange-dark-3` | `--hm-sem-palette-orange-dark-3` | `#4f2000` | 2026-10-11 사용자 재확정 브랜드 단계 | Yes | Color Reference / 선택적 Theme palette |
| `color.palette.gray-900` | `--hm-sem-palette-gray-900` | `#212121` | Foundation Gray 텍스트 단계 (2026-11-11) | Yes | fg-primary 기본 |
| `color.palette.gray-800` | `--hm-sem-palette-gray-800` | `#424242` | Foundation Gray 텍스트 단계 (2026-11-11) | Yes | 기본 연결 없음(Strong Secondary 예약) |
| `color.palette.gray-700` | `--hm-sem-palette-gray-700` | `#616161` | Foundation Gray 텍스트 단계 (2026-11-11) | Yes | fg-secondary 기본 |
| `color.palette.gray-600` | `--hm-sem-palette-gray-600` | `#757575` | Foundation Gray 텍스트 단계 (2026-11-11) | Yes | fg-placeholder 기본 |
| `color.palette.gray-500` | `--hm-sem-palette-gray-500` | `#9e9e9e` | Foundation Gray 텍스트 단계 (2026-11-11) | Yes | 기본 연결 없음(Disabled는 opacity 정책 유지) |
총 94개. 기존 25개 + 핵심 역할 6개 + 선택적 팔레트 52개(2026-10-11 ui_viz 확정 단계 8개 및 사용자 확정 Orange Dark 1·2 추가) + Provisional Generic Status Error 1개 + Brown·Orange Background Stop 10개. 팔레트는 컴포넌트별 계약이 아니며 Primary / Active / Focus를 개별 지정하면 팔레트 alias보다 우선한다. Focus와 Active, Primary와 On Accent는 각각 sibling이며 서로 alias하지 않는다.
총 99개(2026-11-11 Foundation Gray 텍스트 단계 5개 추가 전 94개). 기존 25개 + 핵심 역할 6개 + 선택적 팔레트 52개(2026-10-11 ui_viz 확정 단계 8개 및 사용자 확정 Orange Dark 1·2 추가) + Provisional Generic Status Error 1개 + Brown·Orange Background Stop 10개. 팔레트는 컴포넌트별 계약이 아니며 Primary / Active / Focus를 개별 지정하면 팔레트 alias보다 우선한다. Focus와 Active, Primary와 On Accent는 각각 sibling이며 서로 alias하지 않는다.
## Generic Status Error — Provisional · 2026-10-11
@@ -113,7 +118,7 @@ Input Error와 Generic Status Error는 별도 역할이다. Input / Alert destru
기존 v1 입력 73개와 이전 팔레트 보강 이후 81개의 Key·CSS property·type·Default를 유지한다. Orange Dark 1·2는 최신 사용자 확정값으로 공개 입력에 추가하며 Dark 3는 기존 값을 유지한다. 과거 Needs Review 기록은 이력으로 보존하고 현재 기준은 [브랜드 컬러 단계](brand-color-steps.md)를 따른다. 공개 API `isRuntimeTheme(unknown): value is RuntimeTheme`를 제공한다. 이 사전 검증은 DOM을 변경하지 않는다. 기존 `applyRuntimeTheme`의 invalid 입력 시 reset 정책은 유지한다. 편집기는 사전 검증으로 invalid Import를 차단해 마지막 유효 Theme를 보존한다.
Default 컬러의 운영 원본은 `themes/default.json`(92개 컬러)이다. `scripts/theme-defaults.mjs`가 JSON과 컬러 literal 없는 alias/geometry template에서 package `primitives.css`, `default.css`, `default-values.generated.ts`를 생성한다. `contract.ts`의 defaultValue와 `defaultRuntimeTheme`는 생성 데이터를 읽는다. 2개 radius/geometry는 template에서 유지한다. CSS fallback/현재 색을 유지하고 세 가지 최종 명령의 pre hook에서 stale 생성 데이터를 검사한다. Theme-only 산출은 `npm run build:themes`로 분리한다.
Default 컬러의 운영 원본은 `themes/default.json`(97개 컬러, 2026-11-11 Gray 5개 추가 전 92개)이다. `scripts/theme-defaults.mjs`가 JSON과 컬러 literal 없는 alias/geometry template에서 package `primitives.css`, `default.css`, `default-values.generated.ts`를 생성한다. `contract.ts`의 defaultValue와 `defaultRuntimeTheme`는 생성 데이터를 읽는다. 2개 radius/geometry는 template에서 유지한다. CSS fallback/현재 색을 유지하고 세 가지 최종 명령의 pre hook에서 stale 생성 데이터를 검사한다. Theme-only 산출은 `npm run build:themes`로 분리한다.
Storybook `Theme/Designer Playground/Editor`는 17개 상위 컬러 역할과 JSON URL/파일 Preview를 제공하는 소비자다. Global decorator에서 `resolveRuntimeTheme(theme, defaultJson)` 후 Production `applyRuntimeTheme(document.documentElement, theme)` → CSS Custom Properties → 기존 Mapping으로 적용한다. JSON Export/Import는 동일 v1 계약이다. 컬러 artifact/편집기만 radius를 거부한다. Production API의 기존 radius/gradient 계약은 유지한다.
@@ -132,3 +137,18 @@ Dashboard의 `active / hold / done / issue` 업무 상태 계약은 `packages/ui
조합 변수 `--hm-sem-bg-brown` / `--hm-sem-bg-orange`는 내부 Derived CSS이며 전체 Gradient 문자열·방향·위치를 Runtime JSON 입력으로 받지 않는다. Runtime에서 한 stop을 바꾸려면 해당 브랜드의 5개 stop을 모두 전달한다. Brown·Orange 두 그룹은 서로 독립적이며 미지정 그룹은 기존 fallback을 따른다. 부분 그룹은 atomic validation으로 거부한다. Global / Scoped 적용과 Reset은 [Runtime Theme](runtime-theme.md)의 기존 계약을 사용한다.
공통 Background는 기존 Green·Brown/Orange Button·Dashboard 배경에 자동 연결하지 않는다. 2026-10-11 최종 표시 요청으로 [Foundation Color](../../src/foundation/color.stories.tsx)의 기존 `foundation-color--all`은 [브랜드 3개 그룹·24개 컬러칩](brand-color-steps.md#호환성과-storybook)만 표시하며 모든 Gradient 미리보기와 개발용 설명을 제거한다. 실제 공통 Background·Button·Dashboard Gradient의 CSS·Theme·Token과 Runtime 계약은 유지한다. 과거 미정의 및 Gradient 추가 검증 보고서는 당시 이력으로 유지한다.
## Admin 텍스트 위계 — Foundation Gray · 2026-11-11
Web·Chart 공통 텍스트 기본값을 Foundation Gray로 바꿨다. 공개 Key·CSS property·type은 그대로이고 기본값만 바뀌었으므로, `color.fg.*`를 지정한 외부 Theme JSON은 이전과 같이 우선한다.
| 역할 | 공개 Key | 기본값 | 이전 기본값 |
|---|---|---|---|
| Primary — 제목·본문 | `color.fg.primary` | `#212121` (gray-900) | `#11372d` (green-dark-1) |
| Secondary — 설명·보조·캡션 | `color.fg.secondary` | `#616161` (gray-700) | `#6e6759` (warm-neutral-dark) |
| Placeholder | `color.fg.placeholder` | `#757575` (gray-600) | `#999999` (neutral-gray-500) |
- 브랜드 Primitive(`green-dark-1`, `warm-neutral-dark`, `neutral-gray-500`)의 값은 바꾸지 않았다. 텍스트 alias만 Gray를 가리킨다.
- Strong Secondary(`gray-800`)·Tertiary·Disabled(`gray-500`) Semantic은 만들지 않았다. Disabled는 기존 opacity 정책을 유지한다.
- 대비(흰 면 / 베이지 `#f5f0e5`): #212121 16.10 / 14.17, #616161 6.19 / 5.45, #757575 4.61 / **4.05**. Placeholder는 흰 입력 면에서만 쓰며, 투명 면인 readonly Input은 Secondary를 쓴다(`input.css`).
- SW(`--hm-sw-*`)·CENTER·OrgChart Core는 이 기본값을 참조하지 않는다. OrgChart는 자체 `--hm-orgchart-fg-*` 기본값을 같은 값으로 맞췄다([OrgChart 승인 기록 §8](../org-chart/design-approval.md#8-2026-11-11-admin-텍스트-위계-적용)).