Skip to content

chore(storybook): drop the redundant setProjectAnnotations setup file - #1968

Open
cliffhall wants to merge 2 commits into
v2/mainfrom
v2/chore/1898-drop-setprojectannotations
Open

chore(storybook): drop the redundant setProjectAnnotations setup file#1968
cliffhall wants to merge 2 commits into
v2/mainfrom
v2/chore/1898-drop-setprojectannotations

Conversation

@cliffhall

Copy link
Copy Markdown
Member

Closes #1898

Storybook 10.3+ has @storybook/addon-vitest provision the preview annotations itself, and it skips doing so when it finds a setup file calling setProjectAnnotations — so clients/web/.storybook/vitest.setup.ts was not merely redundant, it was actively opting the project out of the automatic path. Every npm run test:storybook run printed the notice saying as much.

This removes the file and drops setupFiles: [".storybook/vitest.setup.ts"] from the storybook vitest project in clients/web/vite.config.ts.

Why this wasn't just a delete

#1898 flagged the silent-failure risk: ./preview carries the MantineProvider decorator and the App.css import, and @storybook/addon-a11y/preview drives the axe assertions. If automatic provisioning didn't pick both up, the 466 story tests would render unthemed with a11y checks inert — and would very likely still pass. A green suite proves nothing here, so both were verified directly rather than inferred.

1. Theme decorator — now guarded in-tree

New story clients/web/src/test/PreviewAnnotations.stories.tsx asserts, from a play function, that the annotations actually reached the story:

  • --mantine-primary-color-filled on :root equals the project theme's own primary shade (read from theme.colors[theme.primaryColor], not hard-coded) — proves the MantineProvider decorator ran with our theme.
  • --inspector-brand-primary resolves to the same value — that token lives in App.css, which only reaches the story through ./preview's stylesheet import, and it resolves through the Mantine variable, so it covers both layers.
  • parameters.a11y is { test: "error" } — the preview parameters merged into the story context, which is the same channel the a11y parameter arrives on.

Negative control: with decorators temporarily emptied in .storybook/preview.tsx, the story goes red. So an unthemed render now fails loudly instead of passing.

 Test Files  1 failed (1)
      Tests  1 failed (1)

2. a11y annotations — verified out-of-band

The axe runner can't be introspected from a play function, so this was checked the way the issue asked: a story with a real violation (a <button> with no accessible name) was temporarily added, and the suite went red with the setup file already removed —

Expected the HTML found at $('button[type="button"]') to have no violations:
"Buttons must have discernible text (button-name)"
https://dequeuniversity.com/rules/axe/4.12/button-name?application=axeAPI
 Test Files  1 failed (1)
      Tests  1 failed | 1 passed (2)

confirming @storybook/addon-a11y/preview is applied automatically. The temporary story was reverted; it is not part of this diff.

Verification

  • npm run test:storybook — 466 tests pass and the setProjectAnnotations notice is gone.
  • npm run validate, npm run verify:build-gate, npm run smoke, npm run ci:storybook — green.
  • npm run coverage — all 315 test files / 4881 tests pass and no file falls below the per-file 90 gate, but the step still exits 1 on the two pre-existing unhandled rejections in inspectorClient.test.ts tracked by npm run ci cannot pass: two pre-existing unhandled rejections in inspectorClient.test.ts abort the gate at coverage #1947. Confirmed pre-existing by running the integration project on unmodified origin/v2/main in the same worktree: identical two rejections, identical exit 1. Unrelated to this diff, which touches only the storybook vitest project and adds a story.

No UI change, so no screenshots.

🤖 Generated with Claude Code

https://claude.ai/code/session_0119LaPQ3v4NyBK3ZTdM9j84

Since Storybook 10.3, @storybook/addon-vitest provisions the preview
annotations itself — and *skips* doing so when it finds a setup file
calling setProjectAnnotations. So .storybook/vitest.setup.ts was not
merely redundant, it was actively opting the project out of the
automatic path, which the addon printed a notice about on every run.

Remove the file and the `setupFiles` entry from the `storybook` vitest
project.

A green suite doesn't prove the automatic provisioning works: without
the preview annotations, stories would render outside MantineProvider
and without App.css, and would very likely still pass. Add
src/test/PreviewAnnotations.stories.tsx, which asserts from a play
function that the Mantine theme variables and the App.css tokens are
actually present in the rendered document, so an unthemed render fails
loudly. Verified by emptying `decorators` in preview.tsx and confirming
the story goes red.

The a11y addon's axe runner can't be introspected from a play function,
so it was checked out-of-band: a story with a real violation turned the
suite red with the setup file already removed, confirming
@storybook/addon-a11y/preview is applied automatically.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0119LaPQ3v4NyBK3ZTdM9j84
@cliffhall cliffhall added the v2 Issues and PRs for v2 label Aug 11, 2026
@cliffhall
cliffhall requested a balanced review from Copilot August 11, 2026 03:48

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Removes obsolete manual Storybook annotation setup in favor of Storybook 10.3+ automatic provisioning.

Changes:

  • Removes the redundant setup file and configuration.
  • Adds a story guard verifying theme, CSS, and preview annotations.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
clients/web/vite.config.ts Removes the Storybook setup file reference.
clients/web/src/test/PreviewAnnotations.stories.tsx Adds annotation-provisioning checks.
clients/web/.storybook/vitest.setup.ts Deletes manual annotation setup.

💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.

Comment thread clients/web/src/test/PreviewAnnotations.stories.tsx Outdated
The guard restated `primaryShade.light` as a literal 7, so re-pinning the
theme's primary shade would have made it fail even with the preview
annotations correctly applied — a guard that has to be edited alongside a
legitimate theme change just trains people to edit it.

Derive the shade from `theme.primaryShade`, handling both of Mantine's
forms (a bare number and `{ light, dark }`) and falling back to Mantine's
own default of 6 when a theme pins none.

Verified by temporarily re-pinning the theme to `{ light: 8, dark: 8 }`:
the guard still passes, where the hard-coded 7 would have failed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0119LaPQ3v4NyBK3ZTdM9j84
@cliffhall

Copy link
Copy Markdown
Member Author

Review round 1 — responses

Mirroring the inline reply here, since inline threads go outdated and get hidden once the fix is pushed.

1. LIGHT_PRIMARY_SHADE duplicates theme.primaryShade.light (PreviewAnnotations.stories.tsx) — fixed in d1135df.

Correct, and it undercut the guard's whole purpose: the point was that every expected value is read from the theme, and I restated the shade as a literal anyway. A guard that has to be edited alongside a legitimate theme change just trains people to edit it.

lightPrimaryShade() now derives it from theme.primaryShade, handling both of Mantine's typed forms (a bare number and { light, dark }) and falling back to Mantine's own default of 6 when a theme pins none.

Verified rather than assumed — temporarily re-pinning the theme to { light: 8, dark: 8 } keeps the guard green, where the hard-coded 7 would have failed:

 Test Files  1 passed (1)
      Tests  1 passed (1)

(An intermediate attempt with { light: 4 } did go red — but on axe's color-contrast rule against the button label, not on the assertion. That's the a11y gate correctly objecting to a genuinely low-contrast primary, which is why the control uses shade 8.)

Re-validated after the change: npm run validate green, npm run ci:storybook green at 111 files / 467 tests.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated no new comments.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

v2 Issues and PRs for v2

Projects

None yet

Development

Successfully merging this pull request may close these issues.

chore(storybook): drop the now-redundant setProjectAnnotations call (Storybook >= 10.3 applies it automatically)

2 participants