docs(storybook): expose semantic colors and gradients
This commit is contained in:
1 parent
91c8e5e14e
commit
3ecc8c7402
3 files changed
+199
-6
No files matched your search
@@ -0,0 +1,87 @@
|
||||
# Foundation Color 현행 Token 표시 확장 — 2026-10-11
|
||||
|
||||
RESULT: PARTIAL. 요청한 표시 확장과 선택 검증은 완료했다. 현행 프로젝트에 없는 Generic Status Error와 Brown/Orange 공통 Background Gradient는 누락 상태로 표시한다. 기존 자료의 HEX·5-stop 구조를 새 Theme 정의로 만들지 않았다. Guard의 동적 값 미검증도 보존한다.
|
||||
|
||||
## 작업 기준과 범위
|
||||
|
||||
- PROJECT_PATH: `D:\디자인시스템\HMDesign-Gitea-Transfer`
|
||||
- BRANCH: `main`
|
||||
- ORIGIN: `https://gitea.hmac.kr/b25027/HMDesign.git`
|
||||
- BEFORE_SHA: `91c8e5e14ef9f162d364909df9a4b481ef3146e4`
|
||||
- 조사 시작 때 보인 Disabled Input Label의 Stage된 5개 파일은 작업 A가 Commit·Push를 완료했다. 이후 로컬/원격 일치와 깨끗한 Working Tree를 확인하고 작업 B의 기준으로 삼았다. 해당 Commit을 보존한다.
|
||||
- Scope: STORYBOOK_ONLY / React. 기존 `Foundation/Color`의 `All` export, `foundation-color--all` ID, Storybook Navigation을 유지한다. 신규 업무 화면·Navigation·Pattern·control은 없으므로 신규 화면 선택 계약과 Form 검증은 해당하지 않는다.
|
||||
- 변경: [Color Story](../../src/foundation/color.stories.tsx), [Foundation 전용 CSS](../../src/foundation/foundation.css), 이 보고서. 기존 ReferencePage / ReferenceSection / 카드·Swatch·가로 Palette 행과 [Computed Property Hook](../../src/foundation/reference.tsx)을 재사용한다. Palette의 Token 상세는 native details/summary로 제공한다.
|
||||
|
||||
## Foundation → Theme → Contract → CSS → Storybook
|
||||
|
||||
[Default JSON](../../themes/default.json) → Theme 생성 스크립트 → [생성 Default 값](../../packages/ui/src/theme/default-values.generated.ts) / [공개 Runtime 계약](../../packages/ui/src/theme/contract.ts) 및 [default.css](../../packages/ui/src/theme/default.css) → Component mapping → [Storybook preview](../../.storybook/preview.tsx)의 index.css / hm-theme.css → Color Story.
|
||||
|
||||
Story는 `@hm-design/ui/theme` 공개 export를 사용한다. Swatch는 현재 CSS 변수를 직접 소비하고 표시 HEX는 documentElement의 computed custom property를 읽는다. Root style/class/data-hm-theme 변경과 resize를 기존 Hook이 관찰한다. Gradient 방향·Stop 위치·색상은 현재 변수의 해석된 linear-gradient에서 추출한다. 과거 자료 HEX나 Stop 위치를 Story에 하드코딩하지 않는다. 해석되지 않는 형식은 NOT VERIFIED로 표시한다.
|
||||
|
||||
상태는 현행 [브랜드 단계 기준](../guidelines/brand-color-steps.md), [Focus 시험 적용 기록](../guidelines/테마-토큰-가이드.md), Component CSS의 Confirmed 근거와 읽기 전용 ui_viz token-inventory의 해당 역할을 대조했다. 값·이름은 현재 HMDesign 구현이 우선하며 ui_viz는 수정하지 않았다.
|
||||
|
||||
## STORYBOOK / TOKEN_CONSISTENCY
|
||||
|
||||
FOUNDATION_COLOR: 렌더 PASS. EXISTING_PALETTE: Green/Brown/Orange 각 8개 및 기존 Button 전용 5개 보존. 모두 현재 CSS 배경색과 표시 HEX가 일치한다. 단계 순서·HEX·기존 Orange Dark 1/2/3의 확정 상태를 보존한다. Orange Default의 border 2px / font-weight 700을 브라우저에서 확인했다.
|
||||
|
||||
| 표시 항목 | 실제 Canonical Token | 실제 CSS Variable | Default Theme HEX | 상태 / 차이 |
|
||||
|---|---|---|---|---|
|
||||
| ACCENT_YELLOW | color.palette.yellow-accent | --hm-sem-palette-yellow-accent | #FFC600 | Confirmed. 이전 hm-accent-yellow / --hm-accent-yellow → 현행 --hm-yellow-accent Primitive. color.accent(#BDDFD4 Green Tint)와 별도 |
|
||||
| INPUT_OUTLINE_DEFAULT | color.stroke.input.default | --hm-sem-stroke-input-default | #DEDBD2 | Confirmed. 동일 색의 다른 역할과 통합하지 않음 |
|
||||
| INPUT_OUTLINE_FOCUS | color.stroke.input.focus | --hm-sem-stroke-input-focus | #266651 | Provisional · 현재 시험 적용. 참고 #123328로 되돌리지 않음 |
|
||||
| INPUT_OUTLINE_ERROR | color.action.destructive | --hm-input-error-border-color → --hm-sem-action-destructive | #D32F2F | Confirmed 현행 mapping. 참고 color.stroke.input.error는 현재 공개 계약에 없음을 표시 |
|
||||
| GENERIC_STATUS_ERROR | 미정의 | 미정의 | 미정의 | 참고 color.status.error는 Provisional. Alert destructive의 Action Token으로 대체하지 않음 |
|
||||
| PRIMARY_ACTION | color.action.primary | --hm-sem-action-primary | #123328 | Confirmed |
|
||||
| CONTENT_BACKGROUND | color.bg.content | --hm-sem-bg-content | #F5F0E5 | Application Context Confirmed / Marketing TBD |
|
||||
| SURFACE_BACKGROUND | color.bg.surface | --hm-sem-bg-surface | #FFFFFF | Confirmed |
|
||||
| PRIMARY_FOREGROUND | color.fg.primary | --hm-sem-fg-primary | #0A221D | Confirmed. White 배경 텍스트 예시 제공 |
|
||||
|
||||
Input/Textarea의 error-border-color 및 Select invalid border는 현재 Action Destructive에 연결된다. Generic Status Error의 독립 역할과 구분하여 설명했으며 mapping을 변경하지 않았다. Yellow의 실제 LNB 소비는 그룹 선택 텍스트다.
|
||||
|
||||
MATCHED: 위 정의된 8개 컬러와 Palette 29개의 HEX / computed backgroundColor 일치. PRIMARY_FOREGROUND의 computed color는 rgb(10, 34, 29), 예시 backgroundColor는 rgb(255, 255, 255).
|
||||
|
||||
MISSING: color.status.error, 독립 color.stroke.input.error 공개 입력, Brown/Orange 공통 Background 역할. LEGACY_NAME_DIFFERENCES와 PROVISIONAL_ITEMS는 위 표에 기록했다.
|
||||
|
||||
## GRADIENTS
|
||||
|
||||
| 구분 | 현재 CSS 변수 | 방향 | STOP_VALUES: 위치 / 현재 HEX |
|
||||
|---|---|---|---|
|
||||
| GREEN: 공통 HM Green Background | --hm-sem-bg-brand | to bottom | 0% #0A221D / 12% #071E18 / 42% #123328 / 78% #266651 / 100% #205241 |
|
||||
| BROWN: 공통 Background 미정의. 별도 기존 Button Background 표시 | --hm-button-brand-brown-background | 180deg | 0% #897445 / 30% #604F32 / 65% #352D1D / 100% #221D13 |
|
||||
| ORANGE: 공통 Background 미정의. 별도 기존 Button Background 표시 | --hm-button-brand-orange-background | 180deg | 0% #D35A00 / 30% #CE5600 / 65% #B44B00 / 100% #783402 |
|
||||
|
||||
참고 명칭 gradient.green.background는 현재 공통 derived CSS와 color.bg.brand.stop.* 공개 입력으로 연결된다. 전체 Gradient 자체의 Runtime 입력은 없다. gradient.brown.background / gradient.orange.background의 공통 5-stop 계약은 현재 HMDesign에 없으므로 재구성하지 않았다. 현행 Button 전용 4-stop은 [button.css](../../packages/ui/src/theme/button.css)의 정의를 그대로 소비하며 공통 배경으로 승격하지 않는다.
|
||||
|
||||
COMPUTED_STYLE: 실제 3개 preview의 backgroundImage가 모두 linear-gradient이고 위 모든 색상·Stop 위치와 일치했다. 각 Stop Swatch도 실제 적용값에서 생성한다. 전체 opacity나 Solid 색으로 Gradient를 대체하지 않았다.
|
||||
|
||||
[Dashboard CSS](../../packages/ui/src/theme/dashboard-layout.css)의 Header는 별도 Action Surface 4-stop이며 Compact는 독립적인 2-layer Gradient다. 이번 공통 Green 미리보기를 Dashboard Compact와 동일한 Gradient라고 주장하지 않으며 Dashboard 원본을 변경하지 않았다.
|
||||
|
||||
## VALIDATION
|
||||
|
||||
| 항목 | 결과 |
|
||||
|---|---|
|
||||
| STORYBOOK_RENDER | Default Theme 실제 React 렌더 PASS. Accent/Semantic/Gradient 및 텍스트 예시 확인. 브라우저 error 로그 0건 |
|
||||
| TYPECHECK | npm run typecheck PASS(root/UI/CENTER, 패키지 생성 및 Theme defaults 검사 포함). 표시 문구·details 변경 후 영향받는 root tsc -b PASS |
|
||||
| BUILD | Storybook build PASS: `_local/foundation-color-storybook-20261011`. 최초 기존 storybook-static의 폰트 쓰기가 Access Denied로 실패하여 별도 출력으로 해결. 500kB chunk·plugin timing 경고는 남음 |
|
||||
| STORY_ID | build index에 foundation-color--all / Foundation/Color / Color / All 유지. 다른 Story export와 Navigation 구성 변경 없음 |
|
||||
| DOC_LINKS | 내부 링크 검사 PASS. 관련 문서 및 Source 연결 유효 |
|
||||
| RESPONSIVE | 390/768/1280/1440px 실제 브라우저에서 document scrollWidth = clientWidth(375/753/1265/1425). Palette 행만 좁은 폭에서 overflow-x:auto. 카드 외부 넘침 0, Stop wrap 후 내부 넘침 0 |
|
||||
| KEYBOARD | Palette Token details를 Enter로 열기·닫기 PASS, SUMMARY focus 유지. 읽기 전용 참조 화면이며 Form ID / disabled / readOnly / popup focus 복귀는 해당 없음. 실제 SR 발화는 NOT VERIFIED |
|
||||
| GUARD | PARTIAL / STORYBOOK 1회. FAIL 0, 원본 status 및 staticStatus NOT VERIFIED. 동적 Token template/스타일·기존 reference/story-page의 해석 한계 보존 |
|
||||
|
||||
Guard 원본은 `_local/foundation-color-guard-20261011.json`에 보존한다. styleEvidence: STATIC PASS / RUNTIME NOT VERIFIED / DESIGN_INTENT PASS / FINAL NOT VERIFIED. Guard 판정을 computed 결과로 덮어쓰지 않는다. 별도 Runtime 근거는 위 Swatch backgroundColor, Foreground color, Gradient backgroundImage와 네 폭 측정이다. 동적 ColorChip 후보 29개, SemanticColor 후보 8개, GradientPreview 후보 3개, Stop 후보 13개는 모두 실제 소스의 유한 집합을 소비한다. CSS 추가 4개 규칙은 Foundation 콘텐츠에만 적용하며 HM Component override는 없다. Storybook 밖 production UI의 전체 검증과 전체 Component 반복 검증은 실행하지 않았다.
|
||||
|
||||
## PRESERVED / GIT
|
||||
|
||||
PALETTE / THEME / COMPONENT_API / EXISTING_STORIES / DASHBOARD_GRADIENTS: 값·정의·소비처 변경 없음. 기존 Story의 레이아웃 기준과 Swatch·Palette 행을 유지하면서 Token 상세와 요청한 섹션만 확장했다. 다른 Foundation 화면에 새 CSS selector가 적용되지 않는다.
|
||||
|
||||
CHANGED_FILES: 위 Story, 전용 CSS, 이 보고서의 3개만 Stage/검토한다. Commit 메시지는 `docs(storybook): expose semantic colors and gradients`. Commit·Push 전 최신 원격 main과 작업 브랜치/기준 SHA 및 Working Tree를 비교하며 일반 Push만 수행한다. Commit SHA / Push / 최종 Local-Remote 일치 / Working Tree 결과는 최종 응답에 기록한다.
|
||||
|
||||
## FOLLOW_UP
|
||||
|
||||
- Generic Status Error의 Provisional 역할·값과 공개 계약 추가 여부는 후속 승인 작업이다.
|
||||
- Input Error의 독립 canonical이 필요한지 판단한다. 이번에는 기존 Action Destructive mapping을 유지했다.
|
||||
- Focus #266651 시험 적용값의 최종 확정이 필요하다.
|
||||
- Brown/Orange 공통 Background Gradient를 도입할지, 현행 Button 전용 Gradient를 계속 별도로 유지할지 판단한다. 이번에는 공통 Token을 만들지 않았다.
|
||||
|
||||
Estimated Duration: 최초 약 35분. 실제 시작·완료 시각과 소요 시간은 Commit·Push 및 최종 상태 확인을 마친 응답에 KST로 기록한다.
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { Meta, StoryObj } from "@storybook/react-vite"
|
||||
import { runtimeThemeContract, type RuntimeThemeToken } from "@hm-design/ui/theme"
|
||||
import { ReferencePage, ReferenceSection } from "./reference"
|
||||
import { ReferencePage, ReferenceSection, useResolvedProperties } from "./reference"
|
||||
|
||||
// Orange Dark 1/2/3 use the latest user-confirmed values (2026-10-11).
|
||||
const stages = ["light-4", "light-3", "light-2", "light-1", "default", "dark-1", "dark-2", "dark-3"] as const
|
||||
@@ -10,23 +10,123 @@ const palettes = [
|
||||
{ name: "한맥오렌지", prefix: "orange", confirmed: [...stages], legacy: ["light", "mid", "dark", "deep"] },
|
||||
]
|
||||
const stageLabel = (stage: string) => stage === "default" ? "Default · 기본색" : stage.replaceAll("-", " ").replace(/^./, letter => letter.toUpperCase())
|
||||
function ColorChip({ prefix, stage, confirmed = true }: { prefix: string; stage: string; confirmed?: boolean }) {
|
||||
const semanticGroups = [
|
||||
{ name: "Input-family Outline", colors: [
|
||||
{ name: "Input Default Outline", token: "color.stroke.input.default", status: "Confirmed", note: "Input / Textarea / Select / Search Form 기본·Disabled 윤곽. 다른 역할의 동일 HEX와 통합하지 않습니다." },
|
||||
{ name: "Input Focus / Open Outline", token: "color.stroke.input.focus", status: "Provisional · 시험 적용", note: "현재 Light 2 시험 적용값. 과거 Green Default로 되돌리지 않으며 사용자 최종 확정 전입니다." },
|
||||
{ name: "Input Error Outline", token: "color.action.destructive", property: "--hm-input-error-border-color", status: "Confirmed · 현행 mapping", legacy: "color.stroke.input.error", note: "현행 Input / Textarea / Select 오류 윤곽은 Action Destructive를 소비합니다. 독립 Input Error canonical은 공개 계약에 없습니다. Generic Status Error와 별도 역할입니다." },
|
||||
] },
|
||||
{ name: "Status", colors: [
|
||||
{ name: "Generic Status Error", status: "Provisional · 미정의", legacy: "color.status.error", note: "현재 계약·Theme에 해당 역할이 없습니다. Alert destructive는 color.action.destructive를 소비하지만 Generic Status Error로 대체하지 않습니다." },
|
||||
] },
|
||||
{ name: "Action", colors: [
|
||||
{ name: "Primary Action", token: "color.action.primary", status: "Confirmed", note: "확인·저장 등 주요 행동. Gradient 배경과는 별도 역할입니다." },
|
||||
] },
|
||||
{ name: "Background", colors: [
|
||||
{ name: "Content Background", token: "color.bg.content", status: "Confirmed · Application Context", note: "업무 콘텐츠 배경. Marketing Context는 TBD입니다." },
|
||||
{ name: "Surface Background", token: "color.bg.surface", status: "Confirmed", note: "Card / Panel / Input / Select / Textarea / Table 표면." },
|
||||
] },
|
||||
{ name: "Foreground", colors: [
|
||||
{ name: "Primary Foreground", token: "color.fg.primary", status: "Confirmed", foreground: true, note: "본문·제목·입력값에 사용하는 주요 텍스트." },
|
||||
] },
|
||||
] satisfies { name: string; colors: ColorReference[] }[]
|
||||
type ColorReference = { name: string; token?: RuntimeThemeToken; property?: string; status: string; note: string; legacy?: string; foreground?: boolean }
|
||||
const gradients = [
|
||||
{ name: "HM Green Background", property: "--hm-sem-bg-brand", legacy: "gradient.green.background", note: "현행 공통 브랜드 배경 · Confirmed. 공개 stop 계약은 color.bg.brand.stop.*이며 방향·위치는 현행 CSS에서 읽습니다. Dashboard의 Header / Compact 배경은 별도 정의입니다." },
|
||||
{ name: "HM Brown Background", legacy: "gradient.brown.background", note: "공통 Brown Background Token / CSS 변수 미정의. 참고 자료의 5-stop 배경을 재구성하지 않습니다.", componentProperty: "--hm-button-brand-brown-background" },
|
||||
{ name: "Orange Background", legacy: "gradient.orange.background", note: "공통 Orange Background Token / CSS 변수 미정의. 참고 자료의 5-stop 배경을 재구성하지 않습니다.", componentProperty: "--hm-button-brand-orange-background" },
|
||||
]
|
||||
const colorProperties = [...new Set([
|
||||
...Object.values(runtimeThemeContract).filter(definition => definition.type === "color").map(definition => definition.property),
|
||||
"--hm-input-error-border-color",
|
||||
...gradients.flatMap(gradient => [gradient.property, gradient.componentProperty].filter((property): property is string => !!property)),
|
||||
])]
|
||||
|
||||
// Read the current CSS value, never the legacy document HEX. Keep unsupported values visible.
|
||||
function colorHex(value: string | undefined) {
|
||||
if (value === undefined) return "확인 중"
|
||||
if (!value) return "미정의"
|
||||
if (/^#[\da-f]{6}$/i.test(value)) return value.toUpperCase()
|
||||
const rgb = value.match(/^rgb\(\s*(\d+)[,\s]+(\d+)[,\s]+(\d+)\s*\)$/)
|
||||
return rgb ? `#${rgb.slice(1).map(channel => Number(channel).toString(16).padStart(2, "0")).join("").toUpperCase()}` : value
|
||||
}
|
||||
function gradientParts(value: string | undefined) {
|
||||
// Split only top-level commas: rgb()/color() channels must stay together.
|
||||
if (!value?.startsWith("linear-gradient(") || !value.endsWith(")")) return undefined
|
||||
let depth = 0
|
||||
const parts = value.slice("linear-gradient(".length, -1).split("").reduce<string[]>((result, char) => {
|
||||
if (char === "(") depth++
|
||||
if (char === ")") depth--
|
||||
if (char === "," && depth === 0) result.push("")
|
||||
else result[result.length - 1] += char
|
||||
return result
|
||||
}, [""]).map(part => part.trim())
|
||||
const [direction, ...stops] = parts
|
||||
const parsed = stops.map(stop => stop.match(/^(.*)\s+(-?[\d.]+%)$/))
|
||||
if (!parsed.length || parsed.some(stop => !stop)) return undefined
|
||||
return { direction, stops: parsed.map(stop => ({ color: stop![1], position: stop![2] })) }
|
||||
}
|
||||
|
||||
function ColorChip({ prefix, stage, confirmed = true, values }: { prefix: string; stage: string; confirmed?: boolean; values: Record<string, string> }) {
|
||||
const token = `color.palette.${prefix}-${stage}` as RuntimeThemeToken
|
||||
const definition = confirmed ? runtimeThemeContract[token] : undefined
|
||||
return <article className="hm-brand-color-chip" data-color-stage={stage} data-color-token={definition ? token : undefined} data-base={stage === "default" ? "" : undefined}>
|
||||
<div className="hm-foundation-swatch" style={definition ? { background: `var(${definition.property})` } : undefined} />
|
||||
<h3>{stageLabel(stage)}</h3><p>{definition ? definition.defaultValue.toUpperCase() : "미확정"}</p>
|
||||
<h3>{stageLabel(stage)}</h3><p data-color-value>{definition ? colorHex(values[definition.property]) : "미확정"}</p>
|
||||
{definition && <details><summary>{paletteStatus(stage)} · Token</summary><dl><dt>Canonical Token</dt><dd><code>{token}</code></dd><dt>CSS Variable</dt><dd><code>{definition.property}</code></dd></dl></details>}
|
||||
</article>
|
||||
}
|
||||
const paletteStatus = (stage: string) => stages.includes(stage as typeof stages[number]) ? "Confirmed" : "Confirmed · 기존 Button 전용"
|
||||
|
||||
function SemanticColor({ item, values }: { item: ColorReference; values: Record<string, string> }) {
|
||||
const definition = item.token ? runtimeThemeContract[item.token] : undefined
|
||||
const property = item.property ?? definition?.property
|
||||
return <article className="hm-foundation-card" data-color-name={item.name} data-color-token={item.token}>
|
||||
{property && <div className="hm-foundation-swatch" data-color-property={property} style={{ background: `var(${property})` }} />}
|
||||
<h3>{item.name}</h3><p data-color-value>{property ? colorHex(values[property]) : "미정의 · HEX 없음"}</p>
|
||||
<p>{item.status}</p><p className="hm-foundation-note">{item.note}</p>
|
||||
{item.foreground && property && <p className="hm-color-foreground-sample" style={{ color: `var(${property})` }}>한맥 프로젝트 · Hanmac Project · 0123456789</p>}
|
||||
<dl><dt>Canonical Token</dt><dd><code>{item.token ?? "미정의"}</code></dd><dt>CSS Variable</dt><dd><code>{property ?? "미정의"}</code></dd>
|
||||
{item.property && definition && <><dt>현재 Semantic 연결</dt><dd><code>{definition.property}</code></dd></>}
|
||||
{item.legacy && <><dt>기존 참고 명칭</dt><dd><code>{item.legacy}</code></dd></>}
|
||||
</dl>
|
||||
</article>
|
||||
}
|
||||
function GradientPreview({ name, property, values }: { name: string; property: string; values: Record<string, string> }) {
|
||||
const value = values[property]
|
||||
const parts = gradientParts(value)
|
||||
return <>
|
||||
<div className="hm-foundation-swatch hm-color-gradient-preview" data-gradient-property={property} style={{ backgroundImage: `var(${property})` }} aria-label={`${name} Gradient 미리보기`} />
|
||||
<dl><dt>현재 CSS Variable</dt><dd><code>{property}</code></dd><dt>현재 Theme 적용 결과 · Computed CSS</dt><dd><code data-gradient-value>{value ?? "확인 중"}</code></dd><dt>방향</dt><dd>{parts?.direction ?? "NOT VERIFIED"}</dd></dl>
|
||||
{parts ? <div className="hm-color-gradient-stops">{parts.stops.map((stop, index) => <article className="hm-brand-color-chip" key={index} data-gradient-stop={stop.position}>
|
||||
<div className="hm-foundation-swatch" style={{ background: stop.color }} /><h3>{stop.position}</h3><p data-stop-value>{colorHex(stop.color)}</p>
|
||||
</article>)}</div> : <p>{value === undefined ? "Stop 확인 중" : "Stop 미정의 또는 해석 불가 · NOT VERIFIED"}</p>}
|
||||
</>
|
||||
}
|
||||
function ColorReferencePage() {
|
||||
return <ReferencePage title="Color" intro="한맥 브랜드 컬러의 확정된 8단계를 비교합니다. 한맥오렌지 Dark 1·2·3은 최신 사용자 확정값을 반영하며 기본색을 강조합니다.">
|
||||
const values = useResolvedProperties(colorProperties)
|
||||
return <ReferencePage title="Color" intro="브랜드 8단계와 Accent · Semantic · Gradient의 현재 CSS 값을 비교합니다. Default Theme를 기본으로 실제 적용값을 읽으며 미정의·잠정 항목은 확정하거나 대체하지 않습니다.">
|
||||
{palettes.map(palette => <ReferenceSection key={palette.name} title={palette.name} note="Light 4 → Light 3 → Light 2 → Light 1 → Default → Dark 1 → Dark 2 → Dark 3.">
|
||||
<div className="hm-brand-color-row">{stages.map(stage => <ColorChip key={stage} prefix={palette.prefix} stage={stage} confirmed={palette.confirmed.includes(stage)} />)}</div>
|
||||
<div className="hm-brand-color-row">{stages.map(stage => <ColorChip key={stage} prefix={palette.prefix} stage={stage} confirmed={palette.confirmed.includes(stage)} values={values} />)}</div>
|
||||
{palette.legacy.length > 0 && <>
|
||||
<p>기존 버튼 그라데이션 색상 · 브랜드 단계와 별도 유지</p>
|
||||
<div className="hm-brand-color-row">{palette.legacy.map(stage => <ColorChip key={stage} prefix={palette.prefix} stage={stage} />)}</div>
|
||||
<div className="hm-brand-color-row">{palette.legacy.map(stage => <ColorChip key={stage} prefix={palette.prefix} stage={stage} values={values} />)}</div>
|
||||
</>}
|
||||
</ReferenceSection>)}
|
||||
<ReferenceSection title="Accent Colors" note="Yellow는 color.palette.yellow-accent입니다. color.accent(Green Tint)와 별도 Token으로 유지합니다.">
|
||||
<div className="hm-foundation-grid"><SemanticColor values={values} item={{ name: "Yellow", token: "color.palette.yellow-accent", status: "Confirmed", legacy: "hm-accent-yellow / --hm-accent-yellow", note: "현재 --hm-yellow-accent Primitive에 연결된 Yellow. Green 맥락 강조 및 LNB 그룹 선택 텍스트에 사용합니다." }} /></div>
|
||||
</ReferenceSection>
|
||||
<ReferenceSection title="Semantic Colors" note="역할별 현행 공개 계약·Component mapping을 표시합니다. 같은 HEX라도 별도 역할을 임의로 합치지 않습니다.">
|
||||
{semanticGroups.map(group => <div className="hm-foundation-specimen" key={group.name}><h3>{group.name}</h3><div className="hm-foundation-grid">{group.colors.map(item => <SemanticColor key={item.name} item={item} values={values} />)}</div></div>)}
|
||||
</ReferenceSection>
|
||||
<ReferenceSection title="Gradients" note="실제 CSS Gradient를 가로형 카드에서 비교합니다. Stop과 방향은 현재 선언의 적용값에서 읽습니다. 공통 배경과 Button 전용 배경은 별도 역할입니다.">
|
||||
<div className="hm-foundation-specimens">{gradients.map(gradient => <article className="hm-foundation-panel" key={gradient.name}>
|
||||
<h3>{gradient.name}</h3><p className="hm-foundation-note">{gradient.note}</p><p>기존 참고 명칭: <code>{gradient.legacy}</code></p>
|
||||
{gradient.property ? <GradientPreview name={gradient.name} property={gradient.property} values={values} /> : <><p>공통 Background: 미정의 · Canonical Token / CSS Variable 없음</p>
|
||||
{gradient.componentProperty && <div className="hm-foundation-specimen"><h3>기존 Button 전용 Background · Confirmed</h3><p>현행 Component CSS만 표시합니다. 공통 5-stop 배경의 대체 또는 확정이 아닙니다. 전체 Gradient canonical은 없으며 stop 색상은 공개 Palette를 소비합니다.</p><GradientPreview name={`${gradient.name} Button`} property={gradient.componentProperty} values={values} /></div>}
|
||||
</>}
|
||||
</article>)}</div>
|
||||
</ReferenceSection>
|
||||
</ReferencePage>
|
||||
}
|
||||
const meta = { title: "Foundation/Color", parameters: { layout: "fullscreen" } } satisfies Meta
|
||||
|
||||
Vendored
+6
@@ -30,3 +30,9 @@
|
||||
.hm-brand-color-chip { flex: 1 0 110px; min-width: 0; padding: 8px; border: 1px solid var(--hm-sem-stroke-default); }
|
||||
.hm-brand-color-chip[data-base] { border: 2px solid var(--hm-sem-fg-primary); font-weight: var(--hm-font-weight-bold); }
|
||||
.hm-brand-color-chip h3, .hm-brand-color-chip p { margin: 8px 0 0; font-size: 13px; }
|
||||
|
||||
/* Color reference additions only; preserve the existing palette row and Default emphasis. */
|
||||
.hm-foundation .hm-color-gradient-preview { height: 112px; }
|
||||
.hm-foundation .hm-color-gradient-stops { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 16px; }
|
||||
.hm-foundation .hm-color-gradient-stops .hm-brand-color-chip { flex: 1 1 110px; }
|
||||
.hm-foundation .hm-color-foreground-sample { padding: 16px; background: var(--hm-sem-bg-surface); }
|
||||
Reference in new issue
Block a user