feat(theme): add brown and orange background gradients

This commit is contained in:
shkim4 committed 2026-10-11 13:30:30 +09:00
1 parent 220973cf89
commit 3220b753dd
12 files changed
+206 -20

No files matched your search

+22 -12
View File
@@ -1,4 +1,5 @@
import type { Meta, StoryObj } from "@storybook/react-vite"
import { useEffect, useRef, useState } from "react"
import { runtimeThemeContract, type RuntimeThemeToken } from "@hm-design/ui/theme"
import { ReferencePage, ReferenceSection, useResolvedProperties } from "./reference"
@@ -32,9 +33,9 @@ const semanticGroups = [
] 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" },
{ name: "HM Green Background", property: "--hm-sem-bg-brand", stopPrefix: undefined, legacy: "gradient.green.background", note: "현행 공통 브랜드 배경 · Confirmed. 공개 stop 계약은 color.bg.brand.stop.*이며 방향·위치는 현행 CSS에서 읽습니다. Dashboard의 Header / Compact 배경은 별도 정의입니다." },
{ name: "HM Brown Background", property: "--hm-sem-bg-brown", stopPrefix: "color.bg.brown.stop", legacy: "gradient.brown.background", note: "공통 Brown Background · Confirmed. 확정 Brown Palette를 참조하는 독립 5-stop 배경입니다. Runtime JSON은 5개 stop 전체를 지정하며 Button·Dashboard와 별도 역할입니다.", componentProperty: "--hm-button-brand-brown-background" },
{ name: "Orange Background", property: "--hm-sem-bg-orange", stopPrefix: "color.bg.orange.stop", legacy: "gradient.orange.background", note: "공통 Orange Background · Confirmed. 확정 Orange Palette를 참조하는 독립 5-stop 배경입니다. Runtime JSON은 5개 stop 전체를 지정하며 Button·Dashboard와 별도 역할입니다.", componentProperty: "--hm-button-brand-orange-background" },
]
const colorProperties = [...new Set([
...Object.values(runtimeThemeContract).filter(definition => definition.type === "color").map(definition => definition.property),
@@ -92,15 +93,25 @@ function SemanticColor({ item, values }: { item: ColorReference; values: Record<
</dl>
</article>
}
function GradientPreview({ name, property, values }: { name: string; property: string; values: Record<string, string> }) {
function GradientPreview({ name, property, stopPrefix, values }: { name: string; property: string; stopPrefix?: string; values: Record<string, string> }) {
const preview = useRef<HTMLDivElement>(null)
const [backgroundImage, setBackgroundImage] = useState<string>()
useEffect(() => {
if (preview.current) setBackgroundImage(getComputedStyle(preview.current).backgroundImage)
}, [property, values])
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>}
<div ref={preview} className="hm-foundation-swatch hm-color-gradient-preview" data-gradient-property={property} style={{ backgroundImage: `var(${property})` }} aria-label={`${name} Gradient 미리보기`} />
<dl><dt>현재 CSS Variable · Derived Gradient</dt><dd><code>{property}</code></dd><dt>현재 Theme 적용 결과 · Computed CSS Variable</dt><dd><code data-gradient-value>{value ?? "확인 중"}</code></dd><dt>실제 Computed background-image</dt><dd><code data-gradient-background-image>{backgroundImage ?? "확인 중"}</code></dd><dt>방향</dt><dd>{parts?.direction ?? "NOT VERIFIED"}</dd></dl>
{parts ? <div className="hm-color-gradient-stops">{parts.stops.map((stop, index) => {
const token = stopPrefix ? `${stopPrefix}.${stop.position.replace("%", "")}` as RuntimeThemeToken : undefined
const definition = token ? runtimeThemeContract[token] : undefined
return <article className="hm-brand-color-chip" key={index} data-gradient-stop={stop.position} data-gradient-stop-token={token}>
<div className="hm-foundation-swatch" style={{ background: stop.color }} /><h3>{stop.position}</h3><p data-stop-value>{colorHex(stop.color)}</p>
{definition && <dl><dt>Canonical Token</dt><dd><code>{token}</code></dd><dt>CSS Variable</dt><dd><code>{definition.property}</code></dd></dl>}
</article>
})}</div> : <p>{value === undefined ? "Stop 확인 중" : "Stop 미정의 또는 해석 불가 · NOT VERIFIED"}</p>}
</>
}
function ColorReferencePage() {
@@ -122,9 +133,8 @@ function ColorReferencePage() {
<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>}
</>}
<GradientPreview name={gradient.name} property={gradient.property} stopPrefix={gradient.stopPrefix} values={values} />
{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>
+2
View File
@@ -35,4 +35,6 @@
.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; }
/* New common background stop IDs stay on one line at the supported widths. */
.hm-foundation .hm-color-gradient-stops .hm-brand-color-chip[data-gradient-stop-token] { flex-basis: 220px; }
.hm-foundation .hm-color-foreground-sample { padding: 16px; background: var(--hm-sem-bg-surface); }