mirror of
https://github.com/Stirling-Tools/Stirling-PDF.git
synced 2026-09-02 21:03:34 +03:00
Storybook: render off the app's real theme CSS, stop hardcoding story colours, and gate a11y in dark mode too (#7187)
## What Makes Storybook render components with the same CSS the app gives them. - The preview loaded the token primitives but **not the editor's semantic token layer** (`styles/theme.css`), so components styled on those variables rendered unthemed — three onboarding stories were importing it by hand to stop their modal surfaces rendering transparent. It's now loaded in the preview and the workarounds are gone. - **Portal stories render inside the `.portal-scope` wrapper** PortalApp mounts, so the portal's scoped reset and typography apply to them exactly as in the app — and, deliberately, to nothing else. - The folder stories invented their own hex colours, two of which aren't values the app's `FOLDER_COLOR_PALETTE` can produce. They now use the palette, so they can't drift from what a user can actually pick. Deliberately does **not** load `tailwind.css` — tailwind is on its way out of the editor, so matching the token layer alone is the target state. ## Story colours route through the tokens, enforced Stories were exempt from the `code-colors` lint, and it showed: hardcoded hexes for surfaces the tokens already name (chat bubbles, borders, demo backgrounds), `var(--x, #hex)` fallbacks that mask a renamed token by silently painting the stale colour, and mocked category accents for which real `--color-cat-*` tokens exist. - Styling literals now use tokens; the dead fallbacks are stripped. - The stories exemption is removed from `theme-lint`, so this can't regress. - Colours that are **the datum itself** — `ColorInput` values, signature ink, per-policy accents, brand-mark swatches — stay literal via `theme-allow-color`, hoisted to named consts so the exemption and its reason sit together. A practical side effect: stories styled on tokens actually respond to the dark-mode toolbar toggle, which is what makes a dark-theme a11y pass meaningful later. ## The a11y gate now runs dark as well as light Contrast is most of what axe reports and it is theme-dependent, so a light-only gate left half the surface unmeasured — and it only becomes measurable at all once the tokens above actually flip. `SCAN_THEME=dark` pins the theme for a whole scan run, every a11y task runs both themes, and each theme has its own baseline: - **light** re-recorded against the themed rendering (the old baseline measured colours the app never shows): 831 stories with violations - **dark** recorded for the first time: 798 stories with violations, 980 story-rule pairs, zero render failures across the full sweep Verified end to end: dark scans measure against dark surfaces (`#18181b` vs `#ffffff`), both baselines self-check clean, and a live scan of stories that changed on main after recording passes both gates. Nightly's timeout doubles for the second sweep. ## Testing Typecheck (all variants), ESLint and Prettier pass. Onboarding, folder, portal and control stories render in the browser scan (39/39) with the per-story CSS imports removed; every story touched by the colour sweep renders too (58/58). `task frontend:lint:colors` passes with stories included.
This commit is contained in:
@@ -211,11 +211,13 @@ tasks:
|
||||
- npx vitest run --config .storybook/vitest.config.ts {{.CLI_ARGS}}
|
||||
|
||||
storybook:a11y:
|
||||
desc: "a11y regression gate over every story: fail only on NEW axe violations"
|
||||
desc: "a11y regression gate over every story, light and dark: fail only on NEW axe violations"
|
||||
deps: [prepare, storybook:browser]
|
||||
cmds:
|
||||
- node .storybook/a11y-scan.mjs
|
||||
- node .storybook/a11y-check.mjs --in .a11y-scan --manifest .a11y-scan/manifest.txt
|
||||
- SCAN_THEME=dark node .storybook/a11y-scan.mjs
|
||||
- node .storybook/a11y-check.mjs --in .a11y-scan --manifest .a11y-scan/manifest.txt --baseline .storybook/a11y-baseline.dark.json
|
||||
|
||||
storybook:a11y:changed:
|
||||
desc: "a11y gate over the stories this branch affects (default base origin/main)"
|
||||
@@ -244,13 +246,17 @@ tasks:
|
||||
fi
|
||||
node .storybook/a11y-scan.mjs {{.CHANGED}}
|
||||
node .storybook/a11y-check.mjs --in .a11y-scan --manifest .a11y-scan/manifest.txt
|
||||
SCAN_THEME=dark node .storybook/a11y-scan.mjs {{.CHANGED}}
|
||||
node .storybook/a11y-check.mjs --in .a11y-scan --manifest .a11y-scan/manifest.txt --baseline .storybook/a11y-baseline.dark.json
|
||||
|
||||
storybook:a11y:record:
|
||||
desc: "Re-record the a11y baseline (run after intentionally fixing/adding violations)"
|
||||
desc: "Re-record both a11y baselines (run after intentionally fixing/adding violations)"
|
||||
deps: [prepare, storybook:browser]
|
||||
cmds:
|
||||
- node .storybook/a11y-scan.mjs
|
||||
- node .storybook/a11y-check.mjs --in .a11y-scan --manifest .a11y-scan/manifest.txt --record
|
||||
- SCAN_THEME=dark node .storybook/a11y-scan.mjs
|
||||
- node .storybook/a11y-check.mjs --in .a11y-scan --manifest .a11y-scan/manifest.txt --record --baseline .storybook/a11y-baseline.dark.json
|
||||
|
||||
# ============================================================
|
||||
# Code quality
|
||||
|
||||
Reference in New Issue
Block a user