Skip to content

fix(a11y): accent-as-text meets WCAG AA + contrast ratchet#82

Merged
th3-br41n merged 1 commit into
mainfrom
feat/a11y-accent-text
Jul 3, 2026
Merged

fix(a11y): accent-as-text meets WCAG AA + contrast ratchet#82
th3-br41n merged 1 commit into
mainfrom
feat/a11y-accent-text

Conversation

@th3-br41n

Copy link
Copy Markdown
Contributor

Closes the deferred accent-text contrast tail. The prior a11y sweep fixed muted text but left accent-coloured TEXT at ~3.3–4.3:1 (under AA 4.5:1) in several light themes as a 'brand decision'. This resolves it without changing any brand fill.

⚠️ Depends on #81 (the native-embed CI hotfix). This branch is off the currently-red main, so its Verify will fail on the pre-existing @brainstorm/native-embed typecheck error until #81 merges — merge #81 first, then I'll rebase (or GitHub merges main in) and this goes green. Nothing in this diff touches that path.

The resolution (conservative — no brand-fill change)

A dedicated color.accent.onSurface token (accent tuned for text) that = the theme's existing accent.strong in the 4 failing light themes and = accent.default everywhere else — nearly free, because each theme's AA-safe text variant already existed. The brand accent (fills, borders, focus rings, button faces) is untouched.

  • New token in all 12 themes (+ the CANONICAL_TOKEN_NAMES mirror); text.link fixed in solar/mint/rose.
  • 22 accent-as-text CSS sites repointed (shell / sdk / apps) → --color-accent-on-surface; fills, borders, focus, and icon glyphs (3:1 bar) deliberately left on accent-default/strong.
  • Contrast-engine fix (token-set-contrast.ts): a translucent background token (e.g. surface.default = rgba(…,0.05)) was scored on its raw RGB — treating a 5%-white overlay as pure white (~1:1). Now composited over --color-background-primary first.
  • CI ratchet (themes-contrast.test.ts): runs lintTokenContrast over every built-in theme — the 12 themes were never linted before (the engine only ran on third-party theme-packs, which is how the translucent-surface bug hid). The deferred decision is now an enforced invariant.

Known-deferred (tracked in the ratchet, not silently skipped)

accent-text-on-accentwhite text ON the light accent fill (membership badges) fails AA in 3 light themes. This is the INVERSE concern (text on a fill, not accent as text) and needs its own per-theme accent.onFill token — a global accent.default→strong swap can't fix it (breaks nord/aurora's dark accent.text on the darker strong). The ratchet asserts the exact known-failing set, so an accidental fix trips the test and prompts removing the entry. Follow-up rung.

Verified

+13 contrast tests; 526 tokens/sdk-types tests green; full suite 14165 passed (the 10 failed files are the known worktree Electron-install collection artifact — 0 test-case failures); tsc + bun run lint (incl. the phantom-CSS-token checker) clean.

🤖 Generated with Claude Code

…xt tail)

The prior a11y sweep bumped muted text to AA but deferred accent-coloured TEXT
as a 'brand decision' — it rendered at ~3.3–4.3:1 (under 4.5:1) in several light
themes. Resolves it WITHOUT touching any brand fill: a dedicated
`color.accent.onSurface` token (accent tuned for text) that = the existing
`accent.strong` in the four failing light themes and = `accent.default`
elsewhere (nearly free — every theme's safe text variant already existed). The
brand accent (fills, borders, focus rings, button faces) is unchanged.

- **New token** `accent.onSurface` → `--color-accent-on-surface` in all 12
  themes (tokens.ts + themes.ts + the CANONICAL_TOKEN_NAMES mirror). `text.link`
  fixed in solar/mint/rose (was = the too-light accent.default).
- **22 accent-as-text CSS sites** repointed shell/sdk/apps (settings, marketplace,
  membership, help, bookmarks, theme-editor, …) → `--color-accent-on-surface`;
  fills / borders / focus / icon glyphs (3:1 bar) left on accent-default/strong.
- **Contrast engine fix** (token-set-contrast.ts): a translucent background token
  (e.g. `surface.default` = rgba(…,0.05)) was evaluated on its raw RGB — treating
  a 5%-white overlay as pure white and misreporting ~1:1. Now composited over
  `--color-background-primary` first. + two `accent-on-surface` pairs.
- **CI ratchet** (themes-contrast.test.ts): runs lintTokenContrast over every
  built-in theme so the deferred 'decision' is now an ENFORCED invariant — a
  regression fails here. The 12 themes were NEVER linted before (the engine only
  ran on third-party theme-packs); this also surfaced the translucent-surface bug.

KNOWN-DEFERRED (tracked in the ratchet): `accent-text-on-accent` — white text ON
the light accent FILL (membership badges) fails AA in 3 light themes. This is the
INVERSE concern (text on a fill, not accent as text) and needs its own per-theme
`accent.onFill` token — a global accent.default→strong swap can't fix it (breaks
nord/aurora's dark accent.text on the darker strong). Its follow-up is separate;
the ratchet asserts the exact known set so a fix trips it + the entry gets removed.

+13 contrast tests; 526 tokens/sdk-types tests green; tsc + lint (incl the
phantom-CSS-token checker) clean.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@th3-br41n th3-br41n merged commit a36f22e into main Jul 3, 2026
1 of 3 checks passed
@th3-br41n th3-br41n deleted the feat/a11y-accent-text branch July 3, 2026 10:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant