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

+2
View File
@@ -125,5 +125,7 @@ npm run storybook # Chart 그룹: Bar / Line / Donut / P
## 제한
- 차트 전용 HM 디자인 규격은 아직 없습니다. 색은 기존 HM 팔레트 Semantic 토큰의 별칭이며(`src/chart.css`), 차트 Token은 이 패키지 안에서만 정의합니다.
- 글자색은 Admin 텍스트 위계를 따릅니다: 툴팁 값·중앙값·막대 이름/값은 `--hm-sem-fg-primary`(#212121), 축 눈금(Cartesian·Radar 기본 축 이름)·범례·툴팁 이름·중앙 캡션은 `--hm-chart-axis-text` → `--hm-sem-fg-secondary`(#616161)입니다.
- 접근성 후속 항목(2026-11-11 기록, 미수정): Line·Area 포인트 값 Label은 시리즈 색을 그대로 씁니다. 기본 시리즈 4 `#ECD4A2`(흰색 대비 1.45:1)·5 `#9A9284`(3.08:1)는 4.5:1 미만입니다. 시리즈 색은 유지하며 Label 색 정책은 별도 결정입니다.
- `@hm-design/chart/examples`의 `ExampleCard`는 공개 Export가 아닙니다(예제 카드를 통해서만 사용).
- Dark 테마 없음. Runtime Theme(`@hm-design/ui/theme`)의 팔레트 override는 차트 별칭을 통해 반영됩니다.
+5 -1
View File
@@ -42,7 +42,11 @@
min-width: 0;
max-width: 100%;
}
[data-slot="chart"] .recharts-cartesian-axis-tick text {
[data-slot="chart"] .recharts-cartesian-axis-tick text,
/* Recharts 3.8 renders tick text as .recharts-cartesian-axis-tick-value outside the tick group, so the rule above no longer matched. */
[data-slot="chart"] .recharts-cartesian-axis-tick-value,
/* Radar default axis names: Recharts would otherwise fill them with its own #808080. */
[data-slot="chart"] .recharts-polar-angle-axis-tick-value {
fill: var(--hm-chart-axis-text);
}
[data-slot="chart"] .recharts-cartesian-grid line {
+2
View File
@@ -18,6 +18,8 @@
| Fixed readOnly / Full Composition 배경 | `#F5F8FB`(`bg-content` 기본) |
| 회사 메인 컬러(Auto 그룹 제목·카드 강조) | `hanmac` 한맥기술 `#CB2E28`, `saman` 삼안 `#F08300`, `jangheon-industry` 장헌산업 `#4580A6`, `jangheon` (주)장헌 `#1D418D`, `ptc` 피티씨 `#84338E`, `halla` 한라산업개발 `#0068B7`, `baron` 바론컨설턴트 `#0C367F` |
| 그룹 제목 글자 | 흰색 |
| 기본 글자 / 보조 글자 | `#212121` / `#616161`(`fg-primary` / `fg-secondary` 기본, 2026-11-11 Admin 텍스트 위계) |
| 카드 직위 / 대표자 직위 | `#616161`(`fg-secondary`) / `#224387`(브랜드 블루) |
| Auto 연결선 | `#738399`(`expanded-line-color` 기본) |
| Fixed 부서 Gradient | 6종(`business-management`, `business-planning`, `talent-growth`, `integrated-system`, `design-planning`, `solution-sales`). 회사색과 별개 — 서로 대체하지 않음 |
| 글꼴 | Noto Sans KR(`--hm-orgchart-font-family`로 override 가능). 호스트가 font-face 등록 |
@@ -9,8 +9,9 @@
--hm-orgchart-resolved-bg-content: var(--hm-orgchart-bg-content, #f4f7fb);
--hm-orgchart-resolved-bg-subtle: var(--hm-orgchart-bg-subtle, #e9edf3);
--hm-orgchart-resolved-bg-brand: var(--hm-orgchart-bg-brand, linear-gradient(180deg, #45639f 0%, #809dd7 100%));
--hm-orgchart-resolved-fg-primary: var(--hm-orgchart-fg-primary, #10243b);
--hm-orgchart-resolved-fg-secondary: var(--hm-orgchart-fg-secondary, #596575);
/* Text defaults follow the Admin Foundation Gray hierarchy (2026-11-11): Gray 900 / Gray 700. Was #10243b / #596575. */
--hm-orgchart-resolved-fg-primary: var(--hm-orgchart-fg-primary, #212121);
--hm-orgchart-resolved-fg-secondary: var(--hm-orgchart-fg-secondary, #616161);
--hm-orgchart-resolved-stroke-default: var(--hm-orgchart-stroke-default, #bac7d7);
--hm-orgchart-resolved-stroke-input-default: var(--hm-orgchart-stroke-input-default, #d3dce8);
--hm-orgchart-resolved-stroke-input-focus: var(--hm-orgchart-stroke-input-focus, #45639f);
@@ -203,7 +203,8 @@
.hm-orgchart-employee:is([data-card-asset], [data-card-layout="compact"])[data-card-asset-size="leader"] .hm-orgchart-avatar { flex-basis: 32px; width: 32px; height: 32px; }
.hm-orgchart-employee:is([data-card-asset], [data-card-layout="compact"])[data-card-asset-size="representative"] .hm-orgchart-avatar { flex-basis: 36px; width: 36px; height: 36px; }
.hm-orgchart-employee:is([data-card-asset], [data-card-layout="compact"]) {
--hm-orgchart-person-position-color: #797979;
/* Secondary text on the light card artwork; #797979 was 3.48:1 on #E0E6F4. */
--hm-orgchart-person-position-color: var(--hm-orgchart-resolved-fg-secondary);
--hm-orgchart-person-position-size: 15px;
--hm-orgchart-person-position-line-height: 18px;
--hm-orgchart-person-position-letter-spacing: -0.6px;
@@ -246,7 +247,7 @@
letter-spacing: var(--hm-orgchart-person-position-letter-spacing);
}
.hm-orgchart-employee:is([data-card-asset], [data-card-layout="compact"]) .hm-orgchart-person-name {
color: var(--hm-orgchart-card-color, #071D3A);
color: var(--hm-orgchart-card-color, var(--hm-orgchart-resolved-fg-primary));
font-size: var(--hm-orgchart-person-name-size);
font-weight: 700;
line-height: var(--hm-orgchart-person-name-line-height);
@@ -255,7 +256,7 @@
text-overflow: clip;
}
.hm-orgchart-employee:is([data-card-asset], [data-card-layout="compact"]) .hm-orgchart-person-name[data-name-overflow="true"] { text-overflow: ellipsis; }
.hm-orgchart-employee:is([data-card-asset], [data-card-layout="compact"]):is([data-card-asset-size="employee"], [data-card-layout="compact"]) .hm-orgchart-person-name { color: var(--hm-orgchart-card-color, #323232); }
.hm-orgchart-employee:is([data-card-asset], [data-card-layout="compact"]):is([data-card-asset-size="employee"], [data-card-layout="compact"]) .hm-orgchart-person-name { color: var(--hm-orgchart-card-color, var(--hm-orgchart-resolved-fg-primary)); }
.hm-orgchart-employee:is([data-card-asset], [data-card-layout="compact"]) .hm-orgchart-person-name:focus-visible { outline: 2px solid var(--hm-orgchart-resolved-stroke-input-focus); outline-offset: 1px; }
.hm-orgchart-employee[data-card-asset-size="employee"] .hm-orgchart-affiliation-mark { top: 2px; right: 1px; width: 20px; height: 20px; min-height: 20px; }
.hm-orgchart-employee:is([data-card-asset], [data-card-layout="compact"]):is([data-card-asset-size="employee"], [data-card-layout="compact"]) .hm-orgchart-affiliation-fallback { font-size: 6px; white-space: nowrap; }
@@ -331,5 +332,5 @@
/* Status is retained for assistive reading; the specified two-line card
composition has no third status row. Supplementary status cards are intact. */
.hm-orgchart-employee:is([data-card-asset], [data-card-layout="compact"]) .hm-orgchart-status-label { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
.hm-orgchart-person-name-tooltip { position: fixed; z-index: 10; box-sizing: border-box; max-width: min(320px, calc(100vw - 16px)); padding: 6px 8px; border: 1px solid #224387; border-radius: 4px; background: #ffffff; color: #071D3A; font-family: var(--hm-orgchart-resolved-font-family); font-size: 14px; line-height: 20px; overflow-wrap: anywhere; pointer-events: auto; }
.hm-orgchart-person-name-tooltip { position: fixed; z-index: 10; box-sizing: border-box; max-width: min(320px, calc(100vw - 16px)); padding: 6px 8px; border: 1px solid #224387; border-radius: 4px; background: #ffffff; color: var(--hm-orgchart-resolved-fg-primary); font-family: var(--hm-orgchart-resolved-font-family); font-size: 14px; line-height: 20px; overflow-wrap: anywhere; pointer-events: auto; }
.hm-orgchart-person-name-tooltip[hidden] { display: none; }
@@ -35,7 +35,7 @@
.hm-orgchart-employee-dialog-close {
/* Match HM Dialog's ghost / icon-sm Button without a React or theme dependency.
Fallbacks are the declared HM defaults (theme/default.css and primitives.css). */
--hm-orgchart-dialog-close-ink: var(--hm-orgchart-dialog-close-color, var(--foreground, var(--hm-sem-fg-primary, #0a221d)));
--hm-orgchart-dialog-close-ink: var(--hm-orgchart-dialog-close-color, var(--foreground, var(--hm-sem-fg-primary, #212121)));
--hm-orgchart-dialog-close-hover: var(--hm-orgchart-dialog-close-hover-background, var(--muted, var(--hm-sem-bg-subtle, #f4f1ea)));
--hm-orgchart-dialog-close-ring: var(--hm-orgchart-dialog-focus-color, var(--ring, var(--hm-sem-stroke-input-focus, #266651)));
position: absolute;
@@ -10,7 +10,7 @@
border: 0;
border-radius: 0;
background: none;
color: #18253a;
color: var(--hm-orgchart-resolved-fg-primary);
font-size: 14px;
}
:is(.hm-orgchart-composition[data-display-mode="readOnly"], .hm-orgchart-summary-preview) .hm-orgchart-organization-totals-title {
@@ -38,7 +38,7 @@
table-layout: fixed;
border-collapse: separate;
border-spacing: 0;
color: #18253a;
color: var(--hm-orgchart-resolved-fg-primary);
font-size: 14px;
line-height: 1.15;
text-align: center;
@@ -61,7 +61,7 @@
}
.hm-orgchart-workdesk-position-table th:first-child { padding: 0 7px; }
.hm-orgchart-workdesk-position-table :is(th, td) + :is(th, td) { border-left: 0.8px solid #d7e1ea; }
.hm-orgchart-workdesk-position-table thead { color: #223149; }
.hm-orgchart-workdesk-position-table thead { color: var(--hm-orgchart-resolved-fg-primary); }
.hm-orgchart-workdesk-position-table thead th,
.hm-orgchart-workdesk-position-table tfoot :is(th, td) { background: #f2f6fa; }
.hm-orgchart-workdesk-position-table tfoot :is(th, td) { height: 20px; }
@@ -79,7 +79,7 @@
border-radius: 10.7px;
background: rgba(255, 255, 255, 0.82);
box-shadow: 0 5.4px 14.3px rgba(44, 68, 96, 0.08);
color: #1c2534;
color: var(--hm-orgchart-resolved-fg-primary);
}
:is(.hm-orgchart-composition[data-display-mode="readOnly"], .hm-orgchart-summary-preview) .hm-orgchart-affiliation-bar-list {
flex-wrap: nowrap;
@@ -114,7 +114,7 @@
}
:is(.hm-orgchart-composition[data-display-mode="readOnly"], .hm-orgchart-summary-preview) .hm-orgchart-affiliation-bar .hm-orgchart-affiliation-mark img { object-fit: cover; }
:is(.hm-orgchart-composition[data-display-mode="readOnly"], .hm-orgchart-summary-preview) .hm-orgchart-affiliation-bar-total {
color: #071d3a;
color: var(--hm-orgchart-resolved-fg-primary);
font-weight: 700;
}
+6 -5
View File
@@ -12,13 +12,14 @@
| 역할 | 값 | 변수 |
|---|---|---|
| Green(주색) | `#164434` | `--hm-sem-palette-green-default` |
| Green 진한 글자 | `#11372D` | `--hm-sem-palette-green-dark-1` |
| Green Dark 1 | `#11372D` | `--hm-sem-palette-green-dark-1` (브랜드 gradient·테두리. 글자 기본값 아님) |
| 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` |
| Foundation Gray(글자) | 900 `#212121`, 800 `#424242`, 700 `#616161`, 600 `#757575`, 500 `#9E9E9E` | `--hm-sem-palette-gray-900` / `-800` / `-700` / `-600` / `-500` |
| Neutral gray(호환) | `#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 변수를 우선합니다.
@@ -31,9 +32,9 @@ Brown·Orange 계열 팔레트(`--hm-sem-palette-brown-*`, `--hm-sem-palette-ora
| 카드·팝업 표면 | `--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·Button·Dashboard)에는 자동 연결되지 않음 — GNB 면은 `--hm-gnb-background`(저장소 `docs/guidelines/runtime-theme-contract.md` "Brown·Orange 공통 Background") |
| 기본 글자 | `--hm-sem-fg-primary` | green-dark-1 |
| 보조 글자 | `--hm-sem-fg-secondary` | warm-neutral-dark |
| placeholder | `--hm-sem-fg-placeholder` | gray-500 |
| 기본 글자(제목·본문) | `--hm-sem-fg-primary` | gray-900 `#212121` |
| 보조 글자(설명·Label·캡션) | `--hm-sem-fg-secondary` | gray-700 `#616161` |
| placeholder | `--hm-sem-fg-placeholder` | gray-600 `#757575`(흰 면 전용, 베이지 면에서는 보조 글자) |
| 일반 테두리 | `--hm-sem-stroke-default` | warm-neutral-mid |
| 입력 테두리 | `--hm-sem-stroke-input-default` | warm-neutral-pale |
| Focus 테두리 | `--hm-sem-stroke-input-focus` | green-light-2 |
+2 -2
View File
@@ -19,8 +19,8 @@
--hm-combobox-background: var(--hm-sem-bg-surface);
--hm-combobox-text: var(--hm-sem-fg-primary);
/* Readable empty-value guidance on the white trigger; preserve shared tokens. */
--hm-combobox-placeholder: var(--hm-sem-fg-secondary);
/* Shared placeholder (Gray 600, 4.61:1 on the white trigger) since 2026-11-11; was fg-secondary for contrast. */
--hm-combobox-placeholder: var(--hm-sem-fg-placeholder);
--hm-combobox-border-color: var(--hm-sem-stroke-input-default);
--hm-combobox-focus-border-color: var(--hm-sem-stroke-input-focus);
--hm-combobox-seam-color: var(--hm-sem-stroke-input-default);
+6
View File
@@ -98,6 +98,12 @@ export const runtimeThemeContract = {
"color.palette.orange-dark-1": { property: "--hm-sem-palette-orange-dark-1", defaultValue: runtimeThemeDefaults["--hm-sem-palette-orange-dark-1"], type: "color" },
"color.palette.orange-dark-2": { property: "--hm-sem-palette-orange-dark-2", defaultValue: runtimeThemeDefaults["--hm-sem-palette-orange-dark-2"], type: "color" },
"color.palette.orange-dark-3": { property: "--hm-sem-palette-orange-dark-3", defaultValue: runtimeThemeDefaults["--hm-sem-palette-orange-dark-3"], type: "color" },
// Foundation Gray text steps (Admin Web / Chart text hierarchy, 2026-11-11). Additive; existing keys unchanged.
"color.palette.gray-900": { property: "--hm-sem-palette-gray-900", defaultValue: runtimeThemeDefaults["--hm-sem-palette-gray-900"], type: "color" },
"color.palette.gray-800": { property: "--hm-sem-palette-gray-800", defaultValue: runtimeThemeDefaults["--hm-sem-palette-gray-800"], type: "color" },
"color.palette.gray-700": { property: "--hm-sem-palette-gray-700", defaultValue: runtimeThemeDefaults["--hm-sem-palette-gray-700"], type: "color" },
"color.palette.gray-600": { property: "--hm-sem-palette-gray-600", defaultValue: runtimeThemeDefaults["--hm-sem-palette-gray-600"], type: "color" },
"color.palette.gray-500": { property: "--hm-sem-palette-gray-500", defaultValue: runtimeThemeDefaults["--hm-sem-palette-gray-500"], type: "color" },
} as const
export type RuntimeThemeToken = keyof typeof runtimeThemeContract
+2 -2
View File
@@ -19,8 +19,8 @@
--hm-date-picker-background: var(--hm-sem-bg-surface);
--hm-date-picker-text: var(--hm-sem-fg-primary);
/* Readable empty-value guidance on the white trigger; preserve shared tokens. */
--hm-date-picker-placeholder: var(--hm-sem-fg-secondary);
/* Shared placeholder (Gray 600, 4.61:1 on the white trigger) since 2026-11-11; was fg-secondary for contrast. */
--hm-date-picker-placeholder: var(--hm-sem-fg-placeholder);
--hm-date-picker-border-color: var(--hm-sem-stroke-input-default);
--hm-date-picker-focus-border-color: var(--hm-sem-stroke-input-focus);
--hm-date-picker-icon-size: 18px;
@@ -3,9 +3,9 @@
export const runtimeThemeDefaults = {
"--hm-sem-bg-content": "#f5f0e5",
"--hm-sem-bg-surface": "#ffffff",
"--hm-sem-fg-primary": "#11372d",
"--hm-sem-fg-secondary": "#6e6759",
"--hm-sem-fg-placeholder": "#999999",
"--hm-sem-fg-primary": "#212121",
"--hm-sem-fg-secondary": "#616161",
"--hm-sem-fg-placeholder": "#757575",
"--hm-sem-action-primary": "#164434",
"--hm-sem-action-cancel": "#6e6759",
"--hm-sem-action-destructive": "#d32f2f",
@@ -94,5 +94,10 @@ export const runtimeThemeDefaults = {
"--hm-sem-palette-orange-light-1": "#eb5f00",
"--hm-sem-palette-orange-dark-1": "#bc4c00",
"--hm-sem-palette-orange-dark-2": "#883700",
"--hm-sem-palette-orange-dark-3": "#4f2000"
"--hm-sem-palette-orange-dark-3": "#4f2000",
"--hm-sem-palette-gray-900": "#212121",
"--hm-sem-palette-gray-800": "#424242",
"--hm-sem-palette-gray-700": "#616161",
"--hm-sem-palette-gray-600": "#757575",
"--hm-sem-palette-gray-500": "#9e9e9e"
} as const
+13 -3
View File
@@ -9,10 +9,11 @@
--hm-color-surface-default: var(--hm-sem-palette-white);
--hm-color-surface-content: var(--hm-sem-palette-beige-light);
--hm-color-surface-subtle: var(--hm-sem-palette-warm-neutral-muted);
--hm-color-text-primary: var(--hm-sem-palette-green-dark-1);
--hm-color-text-secondary: var(--hm-sem-palette-warm-neutral-dark);
/* Admin text hierarchy (2026-11-11): Primary Gray 900, Secondary Gray 700, Placeholder Gray 600. Brand primitives keep their values. */
--hm-color-text-primary: var(--hm-sem-palette-gray-900);
--hm-color-text-secondary: var(--hm-sem-palette-gray-700);
--hm-color-text-inverse: var(--hm-sem-palette-white);
--hm-color-text-placeholder: var(--hm-sem-palette-neutral-gray-500);
--hm-color-text-placeholder: var(--hm-sem-palette-gray-600);
--hm-color-border-default: var(--hm-sem-palette-warm-neutral-mid);
--hm-color-border-control: var(--hm-sem-palette-warm-neutral-pale);
/* Common Focus color. Trial value: Light 2 (#266651), pending user confirmation. Was --hm-color-primary. */
@@ -237,3 +238,12 @@
--hm-sem-palette-orange-dark-2: var(--hm-orange-dark-2);
--hm-sem-palette-orange-dark-3: var(--hm-orange-dark-3);
}
/* Foundation Gray text steps; only the text aliases above reference them. */
:root, [data-hm-theme] {
--hm-sem-palette-gray-900: var(--hm-gray-900);
--hm-sem-palette-gray-800: var(--hm-gray-800);
--hm-sem-palette-gray-700: var(--hm-gray-700);
--hm-sem-palette-gray-600: var(--hm-gray-600);
--hm-sem-palette-gray-500: var(--hm-gray-500);
}
+2
View File
@@ -99,6 +99,8 @@
border-width: 0;
padding-inline: 0;
background: transparent;
/* Transparent face can sit on the beige content surface, where Gray 600 is below 4.5:1. */
--hm-input-placeholder: var(--hm-sem-fg-secondary);
}
[data-slot="input"][readonly]:focus-visible {
border-width: 0;
+9
View File
@@ -58,3 +58,12 @@
--hm-orange-dark-2: #883700;
--hm-orange-dark-3: #4f2000;
}
/* Foundation Gray text steps (2026-11-11). Admin text hierarchy only; SW keeps its own tokens. */
:root {
--hm-gray-900: #212121;
--hm-gray-800: #424242;
--hm-gray-700: #616161;
--hm-gray-600: #757575;
--hm-gray-500: #9e9e9e;
}