v0.3 Phase 4g: four-tier semantic tokens + notice usage layer
Round-5 feedback flagged the muddy result of forcing one --color-caution
to be both bright yellow (signal) and accessible text (ochre). The
single-token-per-role model collapsed the visible identity. Caution
notices ended up reading as brown/khaki surfaces because color-mix(
in oklab, var(--color-caution) 8%, transparent) over cream produced
muddy results whatever the source hex.
New architecture: four-tier per-role tokens, hand-tuned -bg surfaces,
plus usage-specific notice tokens on top.
Tier model — each semantic role publishes four tokens:
signal Brand-true colour. Left bars, large icons, dots, focus rings.
Looks like the role at a glance.
ink Accessible text variant. Used ONLY when text itself must
carry the role colour. WCAG AA 4.5:1 on its surface.
border Middle value. Visible chip/notice outline; not text-safe.
bg Hand-tuned pale tint surface. NOT a color-mix derivation.
Example, light-mode caution:
--color-caution-signal #FFCD00 (bright yellow)
--color-caution-ink #7A5D00 (ochre, for small text only)
--color-caution-border #D9A900 (mid gold)
--color-caution-bg #FFF7D6 (clean pale yellow tint)
--color-{role} retained as a backward-compat alias pointing at -signal.
v0.2 callers keep working; new code reaches for the specific tier.
Usage layer — components subscribe to usage-specific tokens, not
role-tier tokens directly:
--notice-{role}-bar left bar, signal-tier
--notice-{role}-icon signal in dark, ink in light, signal in HC
--notice-{role}-border outer border colour
--notice-{role}-bg hand-tuned pale surface
LumotiaNotice reads these via Tailwind arbitrary-value classes
(bg-[var(--notice-info-bg)] etc). v0.2 fallback values defined at
:root (outside quietware blocks) using color-mix from v0.2 --color-
{role} tokens so the Notice keeps rendering sensibly when quietware
is off.
HC contract — every -bg token forces to transparent. HC notices
render text + icon + 2-px border + left bar, no body tint. Brand
atmosphere steps fully aside.
Per Jake's round-5 spec: yellow stays yellow as the visible signal,
ochre only appears as small-text ink, and brown/khaki never
represents the caution role's primary visual identity again. Same
discipline applies to red/blue/green — each role has a clean
hand-tuned -bg pale tint per theme.
Verified — visible result.
Light caution notice: bright #FFCD00 bar + signal icon + ink-darkened
small icon + pale #FFF7D6 surface + #D9A900 border. Clean,
semantically clear, no mud.
Dark caution notice: bright #FFCD00 bar + signal icon + dark warm
#29210A surface + bright yellow border. Reads as yellow at a glance.
HC modes: no body tint, strong bordered notices, semantic colours
preserved as primary identifier alongside icon + label.
npm run check: 0 errors, 0 warnings across 5707 files.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -49,33 +49,43 @@
|
||||
classes = "",
|
||||
}: Props = $props();
|
||||
|
||||
// v0.3 Phase 4g — notice usage tokens. Each tone reads four CSS
|
||||
// variables published by v0.3-quietware-tokens.css:
|
||||
// --notice-{tone}-bar left bar (signal-tier)
|
||||
// --notice-{tone}-icon icon colour (signal in dark, ink in light)
|
||||
// --notice-{tone}-border outer border colour
|
||||
// --notice-{tone}-bg hand-tuned pale tint surface
|
||||
//
|
||||
// v0.2 fallback values are defined at :root in the same tokens file
|
||||
// via color-mix from the v0.2 --color-{role} tokens, so the Notice
|
||||
// renders sensibly with or without quietware active.
|
||||
const palette: Record<Tone, { bar: string; bg: string; border: string; iconColor: string; icon: typeof Info }> = {
|
||||
info: {
|
||||
bar: "border-l-info",
|
||||
bg: "bg-info/8",
|
||||
border: "border-info/40",
|
||||
iconColor: "text-info",
|
||||
bar: "border-l-[var(--notice-info-bar)]",
|
||||
bg: "bg-[var(--notice-info-bg)]",
|
||||
border: "border-[var(--notice-info-border)]",
|
||||
iconColor: "text-[var(--notice-info-icon)]",
|
||||
icon: Info,
|
||||
},
|
||||
caution: {
|
||||
bar: "border-l-caution",
|
||||
bg: "bg-caution/8",
|
||||
border: "border-caution/40",
|
||||
iconColor: "text-caution",
|
||||
bar: "border-l-[var(--notice-caution-bar)]",
|
||||
bg: "bg-[var(--notice-caution-bg)]",
|
||||
border: "border-[var(--notice-caution-border)]",
|
||||
iconColor: "text-[var(--notice-caution-icon)]",
|
||||
icon: AlertTriangle,
|
||||
},
|
||||
danger: {
|
||||
bar: "border-l-danger",
|
||||
bg: "bg-danger/8",
|
||||
border: "border-danger/40",
|
||||
iconColor: "text-danger",
|
||||
bar: "border-l-[var(--notice-danger-bar)]",
|
||||
bg: "bg-[var(--notice-danger-bg)]",
|
||||
border: "border-[var(--notice-danger-border)]",
|
||||
iconColor: "text-[var(--notice-danger-icon)]",
|
||||
icon: AlertOctagon,
|
||||
},
|
||||
success: {
|
||||
bar: "border-l-success",
|
||||
bg: "bg-success/8",
|
||||
border: "border-success/40",
|
||||
iconColor: "text-success",
|
||||
bar: "border-l-[var(--notice-success-bar)]",
|
||||
bg: "bg-[var(--notice-success-bg)]",
|
||||
border: "border-[var(--notice-success-border)]",
|
||||
iconColor: "text-[var(--notice-success-icon)]",
|
||||
icon: CheckCircle,
|
||||
},
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user