v1.5.0 — fg-* text-emphasis roles
v1.5.0 — fg-* text-emphasis roles
Upstreams the foreground emphasis ladder i-willink.com grew during its dark rollout (v1.5 Outcome 3) into the Design System as official semantic roles. The DS previously shipped only fg (strongest body) and muted (weakest supporting) — with no in-between steps, consumers reached into mode-invariant text-neutral-* for emphasis, which froze light grays under a dark root. These five roles close that gap and flip in dark mode like every other semantic role.
New roles (between fg and muted)
| role | utility | light | dark | contrast contract (on bg) |
|---|---|---|---|---|
fg-strong |
text-fg-strong |
neutral-800 | neutral-100 | ≥ 7 (AAA) — headings / strong runs |
fg-emphasis |
text-fg-emphasis |
neutral-700 | neutral-200 | ≥ 7 (AAA) — labels / links |
fg-secondary |
text-fg-secondary |
neutral-600 | neutral-300 | ≥ 4.5 (AA) — secondary body |
fg-subtle |
text-fg-subtle |
neutral-400 | neutral-500 | documented baseline — captions / meta / placeholders (non-body) |
fg-faint |
text-fg-faint |
neutral-300 | neutral-600 | documented baseline — disabled text / separators (non-text) |
fg and muted are unchanged (the ladder's anchors). Each role is a neutral-step alias + a willink.dark extension, so it rides the existing ADR-0013 dark-flip + consumer-override machinery with no new mechanism.
Packages (npm lockstep 1.4.1 → 1.5.0)
@willink-labs/tokens@1.5.0— 5 new semantic roles@willink-labs/tailwind-preset@1.5.0— light decls + both dark blocks +text-fg-*safelist@willink-labs/css-tokens@1.5.0— regen (5 vars intokens.css/tokens.semantic.css, flipped intokens.dark.css)@willink-labs/react@1.5.0— lockstep marker (no component change)
No flutter-v* tag — zero Flutter changes (willink_theme stays 1.5.0 per ADR-0011).
pnpm add @willink-labs/tokens@1.5.0 @willink-labs/tailwind-preset@1.5.0 @willink-labs/react@1.5.0 @willink-labs/css-tokens@1.5.0
For consumers
Replace local fg-* definitions (or text-neutral-* used for body emphasis) with the new text-fg-* utilities — they render byte-identical in light (the DS neutral scale is the slate scale) and gain a correct dark flip. A separate task migrates i-willink.com's local fg-* block to these roles.
Contrast policy
scripts/check-contrast.mjs enforces the per-role targets in both modes: fg-strong/fg-emphasis ≥ 7 (AAA) and fg-secondary ≥ 4.5 (AA) are required; fg-subtle/fg-faint are documented report-only baselines below the body-text floor (non-body tiers — not for content text).
Out of scope (v1.7)
Pastel-chip semantic pass, naskit diagram theming, theme-toggle UX (all i-willink.com consumer-side follow-ups).