Repository navigation
v0.1.0-alpha.7
Pre-releaseFixed
-
Focus indicators no longer paint from the bare
--token-colorPrimary.
That token is chosen for brand, not for contrast, and measured 2.37:1
against--token-colorFillSecondaryin this package's own default palette,
under the 3:1 floor WCAG 2.2 SC 1.4.11 sets for the visual indicator of a
component state. Because the defect was in the package, every consumer
inherited it and none could fix it.Thirteen
outlinedeclarations now resolve through
var(--token-focusRingColor, var(--token-colorPrimary)). Seven of them wrote
the accent directly and bypassed the ring token entirely, so a consumer that
corrected the token still got the failing colour. Two rings drawn as the
element's ownborder-colortake
color-mix(in srgb, var(--token-colorPrimary) 70%, var(--token-colorText));
.base-card:focus-withinis the one that mattered most, since it sets
outline: noneand its border was the whole indicator on the most-used
primitive in the package. Worst case across ten measured palettes moves from
2.37:1 to 4.21:1, and no palette regresses. -
A focus indicator now carries no colour fallback literal. This is a narrow,
deliberate exception to the "always give a token a fallback" rule, recorded
in CONTRIBUTING.md and in thestyles/base.cssheader: a
fixed literal cannot clear 3:1 against a surface it cannot know, so
"renders unthemed" and "meets the contrast floor" are not both achievable
from a constant. The decorative fallback literals are untouched, per the
decision already recorded atbase.css:27-37. -
The build copies only
.cssout ofsrc/styles. It took the whole
directory, so any non-stylesheet that ever landed beside the tokens shipped
inside the tarball.
Changed
-
--token-focusRingColoris#b95b06instyles/base.cssand
styles/themes/orange-light.css, the 70% text mix of the brand accent
resolved to a literal, raising the shipped default ring from 2.37:1 to
4.18:1.orange-darkkeeps#ff9729: it already measures 7.00:1, and the
same mix would lower it to 6.42:1 for no benefit.This alters rendering, which the versioning policy would make a major
release outside the alpha series. It lands here for the same reason
0.1.0-alpha.2 and 0.1.0-alpha.6 did: the package is still an alpha with one
consumer mid-migration, and a focus ring under the WCAG floor is not a
contract worth preserving.The value is written resolved rather than as a
color-mix()call because a
custom property holds an unparsed token stream: an unsupportedcolor-mix()
substitutes successfully and only then invalidates theoutlineshorthand at
computed-value time, leavingoutline-style: noneand no ring at all, with
novar()fallback firing. In aborder-colorlonghand the failure is the
opposite and benign, which is why the mix stays inline there.
Added
src/styles/focusIndicator.test.ts, a contrast gate. Nothing in
pnpm verifyread a colour value, so a focus ring at 2.37:1 passed
typecheck, lint, format, boundary, build and pack without complaint, which
is how this shipped. The test resolves the token contract the way a browser
does, composites alpha over an opaque page base, and asserts 3:1 for every
sheet against all six surfaces a ring can land on. It also pins the two
indicator shapes, because the defect had two spellings and only one of them
contained the wordoutline.