Repository navigation
Phase 2: consume @crashoverride/brand-tokens; versioned registry; a11y + visual CI - #5
Merged
Merged
Conversation
…ens (adopts light-border a11y fix) The design system no longer owns a token canon. brand-visual (published as @crashoverride/brand-tokens, pinned at v1.0.1 by git tag) is the single source of truth. scripts/build-theme-tokens.mjs concatenates the package token layers in the registry order (colors, spacing, typography, semantic, base) into src/registry/crashoverride/theme/tokens.css with a provenance header. Output is deterministic (LF, no timestamps) so CI can gate staleness. Wiring: - package.json: add "theme:build"; "registry:build" now runs theme:build before shadcn build. Materialized tokens.css differs from the previously committed copy on exactly two things, both expected: 1. The provenance header line. 2. Light-mode --border-default2: #9D9D9D -> #8E8E8E. This is the INTENTIONAL adoption of the brand-visual WCAG SC 1.4.11 accessibility fix. It is the only value change; verified by a comment-and-whitespace-stripped diff that isolates this single line. The tagline comment punctuation also changes (em-dash to colon) to match the package source, but the CSS values are byte-identical there; no functional change. globals.css @font-face is now self-hosted-first to match brand-visual: the primary src is the vendored OFL woff2 from the brand-visual Pages site, with the gstatic latin-subset woff2 kept as a same-declaration fallback so consumers who cannot reach Pages are not broken. Verified: npm run registry:build green; generated public/r/theme.json carries the border fix and dual font URLs; npx vitest run green (198 passed). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
After registry:build (which runs theme:build), fail CI if the materialized src/registry/crashoverride/theme/tokens.css is not byte-identical to what the build produces. This guarantees the checked-in theme canon always reflects the pinned @crashoverride/brand-tokens version and cannot drift via hand edits. Verified locally: a one-char edit makes git diff --exit-code return non-zero; reverting and re-running theme:build returns to zero (deterministic output). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The materialized registry theme (src/registry/crashoverride/theme) is now the single in-repo consumer of brand tokens; public/tokens/ and public/brand-assets/ were stale local copies. Delete them and re-source the static preview pages and the Brand Assets MDX from the live brand-visual Pages deploy. - public/styles.css: re-point the 7 token @imports at the brand-visual Pages tokens (these static pages cannot resolve a node_modules path). - src/docs/BrandAssets.mdx: point img src at brand-visual Pages assets as a minimal fix so Storybook still builds; left a TODO(Task 5) to re-source properly. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Replace all 20 public/guidelines/*.html pages with minimal meta-refresh redirect stubs pointing at the equivalent brand-visual Pages URLs (https://crashappsec.github.io/brand-visual/guidelines/<page>.html). Body link provided for clients that block meta-refresh. Cleanup tracked in #4. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…scope note - Colors.mdx, Typography.mdx: add canonical-source banner linking brand-visual guidelines (color-palette.html, type-fonts.html); existing swatch rendering unchanged. - BrandAssets.mdx: remove TODO(Task 5) comment; keep img src on brand-visual Pages assets (the correct re-source per spec); add canonical-source banner linking brand-visual guidelines/brand-logos.html. - README.md: add "Token and guideline canon" section clarifying that crashappsec/brand-visual is the source of truth and this repo is the React implementation layer consuming @crashoverride/brand-tokens. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…0 feedback) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Flip the a11y addon to `test: error` so axe violations fail story tests, add the Storybook test runner, and run it against the static build in a new CI `a11y` job (build-storybook, serve, test-storybook). Triaged the real tree (308 story tests). Fixed 42 name-gap violations by modelling accessible usage: aria-label on bare demo controls (switch, checkbox, progress, slider, input/textarea/input-group/input-otp) and component-level forwarding where the name must land on a specific element (slider thumb, combobox role=combobox trigger, scroll-area viewport made keyboard-focusable). The remaining 13 color-contrast findings are brand-palette tones (Fandango / Jazzberry / muted-foreground micro-text) materialized from the brand-tokens canon and CI-gated here, plus one upstream cmdk separator-in-listbox; those stories scope OFF only the offending rule with a justifying comment (no blanket disables) and are tracked as contrast debt in the README. Verified green (308/308) and confirmed the check catches a deliberately bad contrast color. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Snapshot a representative slice of the Storybook static build (the Foundations
pages + one story per component/block family, derived from index.json so it
never drifts) and diff it against committed baselines, so a token change cannot
silently restyle the system.
The new visual-regression workflow triggers ONLY on token-affecting paths
(package.json, package-lock.json, src/registry/crashoverride/theme/**), builds
and serves Storybook, runs the suite, and uploads diff images as an artifact on
failure. The pixel ceiling (maxDiffPixelRatio 0.005) was calibrated against a
real change: flipping the primary accent diffed affected stories by ~1% of
pixels, well above the threshold, while sub-pixel antialiasing stays under it.
Baselines carry a -{platform} suffix because chromium renders fonts differently
on macOS vs Linux. The committed -darwin set is the local reference; the -linux
set CI compares against is generated IN CI via the workflow's workflow_dispatch
update mode (which validates the target ref and commits the refreshed baselines)
-- this avoids committing macOS pixels that CI could never match. Verified: a
no-op re-run passes against the committed baselines, and a deliberate accent
change produces diffs (then reverted).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
git diff --quiet ignores untracked files, so the freshly generated -linux baselines were never committed. Stage first, then check the index with git diff --cached --quiet. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…fact The org's verified-signature rule blocks the bot from auto-committing Linux baselines (GH013). Two fixes: (1) the verify guard skips when no -linux baseline is committed yet instead of hard-failing (a snapshot guard with no baseline guards nothing), activating once seeded; (2) the update-baselines job uploads the generated baselines as an artifact so a maintainer can commit them with a signed push. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Generated by the update-baselines CI run (artifact), committed here via a signed push since the org verified-signature rule blocks the bot. This activates the visual-regression guard: token-bump PRs now diff against these 73 Linux baselines. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Collaborator
Author
Post-merge smoke: ALL PASS ✅
Harness note for anyone repeating this: the scratch project needs a Consumer refresh workflows (compass, digital-marketing) being triggered now; they'll open refresh PRs offering this update. 🤖 Generated with Claude Code |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Phase 2: consume
@crashoverride/brand-tokens— Readiness ReportUpdated 2026-06-11. Supersedes the original description; nothing material removed, everything verified against the live branch (12 commits, HEAD
9ecaa8c).Verdict: READY TO MERGE
build(tsc + vite + registry build + theme staleness gate)a11y(axe smoke-check, 308 story tests,a11y.test: error)verify(visual regression vs 73 seeded Linux baselines)What this PR does
react-design-systemstops owning the token canon and becomes the React implementation that consumes it:@crashoverride/brand-tokens(exact-pinnedgithub:crashappsec/brand-visual#v1.0.1) byscripts/build-theme-tokens.mjs; CI fails if the committed artifact is stale.public/tokens/,public/brand-assets/); 20 guideline pages are now redirect stubs to brand-visual Pages for one release cycle (Remove guideline redirect stubs after one release cycle #4 tracks removal).r/v1/<name>.jsonserved alongsider/<name>.json(latest alias); frozen-major path wired for future breaking changes; two-major support policy in the README.The only value change consumers will see
--border-default2(light mode):#9D9D9D→#8E8E8E— the WCAG 2.2 SC 1.4.11 fix (2.71:1 → 3.28:1) adopted from the canon. Fonts additionally become self-hosted-first (brand-visual Pages) with the gstatic fallback retained. Everything else in the registry output is value-identical (verified by token-level diff of all 290 declarations).Exactly what is left
To complete this rollout, in order:
r/v1/goes live, redirect stubs go live, registry serves the materialized theme.npx shadcn add @crashoverride/themeagainst both the latest andr/v1/URLs; confirmcurl r/theme.json==r/v1/theme.json; spot-check one redirect stub.design-refreshcallers weekday mornings (07:23 UTC), or trigger immediately viaworkflow_dispatch. Owners review a one-token visual diff and merge.Tracked follow-ups (none block the merge):
.storybook/stories.#v1.0.1→#v1.0.2) until either Renovate is adopted or the npm channel is enabled. The visual-regression job triggers on exactly those PRs.What users need to do
React apps consuming the shadcn registry (compass, digital-marketing, OSS sites):
design-refreshPR when it arrives, or runnpx shadcn add @crashoverride/theme --overwritemanually. The diff you will review: the one border token, the fontsrcchanges, and a provenance header.components.json:{ "registries": { "@crashoverride": "https://crashappsec.github.io/react-design-system/r/v1/{name}.json" } }Pinned consumers re-vendor within their major; unpinned consumers track latest.
Apps that want raw tokens without React/shadcn (new capability):
Anyone with links to the old guideline pages (bookmarks, Slack history, docs): old URLs redirect automatically for one release cycle; update links to
https://crashappsec.github.io/brand-visual/guidelines/<page>.html.Contributors to this repo:
src/registry/crashoverride/theme/tokens.css— it is generated and CI-gated. Token changes go to brand-visual (marketing review per CODEOWNERS), then arrive here as a dependency bump.Visual regressionworkflow'sworkflow_dispatchupdate mode; it uploads regenerated baselines as an artifact (the org's verified-signature rule blocks bot pushes), which a maintainer commits with a signed push. Documented in the README.Rollback
git revertof the merge restores everything: the registry rebuilds from committed sources on the next Pages deploy, the deleted canon is recoverable from history and independently from brand-visual, and the redirect stubs make rollback invisible to guideline readers in both directions.Reconciliation note (for the record)
This migration surfaced and fixed a real two-copy drift: commit
e4e883dhad fixed the tagline traffic-light colors only in the registry copy, never inpublic/tokens/; brand-visual inherited the stale values. Fixed upstream as brand-visual v1.0.1, consumed here. After this merge, that class of bug is structurally impossible: one canon, one materialization path, staleness-gated.🤖 Generated with Claude Code