v0.2.0
The OKLCH color release (#457). Contains breaking changes — the
first since 0.1.0 — flagged below per VERSIONING.md; shipped as a
minor while the major is 0. No adopters were on the renamed surface.
- CLI
@hypermedia-components/cli@0.4.0— the email axis list
follows the accent pentagon (--color teal | lime | orange | fuchsia; the old names are rejected). Breaking for scripts passing
the old values, and older CLI versions cannot themed-eject against
core0.2.0— upgrade both together. (Independentcli-v0.4.0
tag.)
Changed
- The accent axes are now the accent pentagon —
data-color
values aredefault(blue) /teal/lime/orange/fuchsia,
replacingindigo/emerald/rose/amber. Breaking for
markup using the old values (flagged per VERSIONING.md; pre-adoption
window). The five hues sit exactly 72° apart around the hue wheel,
anchored at blue (264° / 336° / 48° / 120° / 192°), which fixes two
real defects in the old set:rosesat 9.7° from the error red, so a
rose-themed app rendered primary actions and error states in visually
identical colors, andindigosat 12.6° from the default blue —
two of five choices were nearly the same color. Every pentagon vertex
stays ≥ 21° from the error / warning / success hues, and
test/ramp.test.mjsasserts the spacing. Four new primitive ramps
(fuchsia/orange/lime/teal) back the axes; all existing
ramps are unchanged and remain available as primitives. A hexagon was
considered and rejected: anchored at blue, one vertex lands 2.9° from
the error red. For a sixth accent, the theme builder generates any
hue through the same ladder.
Fixed
-
Email templates baked
oklch()— unreadable by email clients.
The OKLCH primitive conversion leaked into the email render target:
expandEmailHtml()substituted resolved token values verbatim, so
the baked artifacts (./email-artifacts/*, the builder's Email tab,
andhc email ejectoutput) carriedoklch()colors that Outlook's
Word engine and several webmail clients cannot parse. The
transformer now converts every substituted color to its sRGB hex —
the same treatmentrem→pxalready got, for the same reason — and
email-tokens.jsoncarries the same email-safe values. New export
emailSafeValue(); a regression test asserts nooklch()or custom
property survives in any generated file. -
semantic.color.warningwas bronze. It resolved toamber.600
(#986107) — the ladder's white-text-safe step, but visibly brown as
a warning color. Every consumer is a border, fill, or checked-state
surface (never a text background — text-bearing warning chips use
status.warning's own pair), so the requirement is the 3:1
graphical-object contrast, not 4.5:1. It now resolves toamber.500
(#b8760b, 3.73:1 against white), which reads as amber. Note the
physics: a bright amber like the old#f59e0bis 2.1:1 against
white and cannot coexist with white glyphs at all.
Changed
-
Theme builder derives in OKLCH. The docs theme builder no longer
carries its own sRGB colour theory —hexToRgb/rgbToHex/
darken/luminance/hslToHexare gone, replaced by the shared
@hypermedia-components/core/oklchladder. Hover darkness is now
a lightness step holding hue and chroma (default7, the gap the
built-in ramps use between600and700) instead of an sRGB
channel multiply, which dimmed warm hues faster than cool ones. The
Auto foreground is the lightness threshold rather than a contrast
search. Exports emitoklch()andcolor-mix(in oklab, …).New In OKLCH read-out plus a Snap to ladder button that
replaces the brand colour with step600for its hue — the exact
colour a built-in axis would use, AA-safe by construction. Shuffle
now rolls a hue through the ladder, so a shuffled theme always clears
AA. The<input type="color">picker stays (it is hex-only by spec)
and converts on read. Built-in accent presets updated to the new
ramp values; amber loses its dark-foreground override. -
Chromatic ramps regularized on a shared lightness ladder. The
seven chromatic ramps (blue / red / green / amber / indigo / rose /
violet) are now generated from one hue angle per ramp plus a shared
ladder:Lfixed per step,Can absolute per-step target clamped
to the hue's sRGB gamut,Hconstant down the ramp. Colors change
visibly — mean Oklab ΔE ≈ 3.7, largest onamber, which was the
ramp furthest off the ladder. The five neutral ramps are
untouched (they were already even), so surfaces, borders, text and
dark mode do not move.The payoff is that the step number now means a lightness, so the
data-coloraxes collapse to one shape: every axis takes600
for the action surface,700for hover,500for the focus ring,
and white text.amberno longer needs dark text or an 18% soft
tint, andemerald/roseno longer reach down to700/800.
Contrast is now a property of the construction — white on600
scores 4.73–5.86:1 across all 360 hues — so a new accent hue needs no
contrast review. Measured margins narrow relative to before
(emerald5.48 → 4.76:1,indigo6.29 → 5.44:1); all clear AA, and
test/ramp.test.mjsnow asserts the whole table.Note that step
500is not a text surface: at L 0.62 the saturated
hues clear neither white nor dark text, which is why it is the
focus-ring step. Regenerate withnode scripts/build-ramp.mjs;
--checkreports drift. -
color-mix()interpolates inoklabat all 31 sites. This is
intent and future-proofing, not a visual change: 26 of the sites mix
withtransparent, which is interpolation-space-independent because
color-mix()is premultiplied, and the other 5 mix into a
near-neutral surface where the two paths differ by at most 2/255.
Changed
- Primitives expressed in OKLCH — all 139 literal colors in
src/tokens/primitive.tokens.jsonare nowoklch()instead of hex.
No visual change: every value was chosen to round-trip to the
identical 8-bit sRGB triple, verified two ways — a conversion check
on all 139 values, and all 14 Playwright VRT baselines staying
byte-identical (light/dark × LTR/RTL, plus compact and accent).
Generated--hc-*custom properties now carryoklch(…), so code
that compares the text of a resolved token against a hex string
needs updating; what the browser paints is unchanged. This is
groundwork for regularizing the ramps on a shared lightness ladder —
seeplans/hc-oklch-color-plan-en.md.
Added
@hypermedia-components/core/oklch— a dependency-free OKLCH ↔
sRGB module (parseOklch,oklchToRgb,oklchToHex,rgbToOklch,
hexToOklch,inSrgbGamut,toHex) plus the ramp ladder itself
(LADDER,maxChroma,rampStep,formatOklch,autoForeground,
FG_LIGHTNESS_PIVOT). The token generator and the docs read the same
constants, so a generated accent is built exactly like a built-in
one. Exported the same way as./token-transform.
Full details in CHANGELOG.md.