Storybook a11y addon violations gating the test-runner in CI
When the test-runner is wired to run axe via @storybook/addon-a11y, accessibility violations become test failures. The job fails with the axe rule id and the element that violated it, gating the merge on a11y.
What this error means
The runner fails a story with an axe result like "Expected 0 accessibility violations but found N", naming rules such as color-contrast or button-name.
Expected the page to have no accessibility violations but found 1:
color-contrast: Elements must meet minimum color contrast ratio thresholds
Element: <button class="btn-ghost">Save</button>Common causes
A real accessibility violation in the component
axe found a genuine issue (low contrast, missing accessible name) that the runner is set to fail on.
A rule that needs configuration for your design system
A rule flags an intended pattern; it should be tuned in the a11y config rather than left as a spurious failure.
How to fix it
Fix the violation in the component
- Read the axe rule id and the offending element.
- Fix the markup (contrast, label, role) so the rule passes.
- Re-run the runner to confirm zero violations.
Tune axe rules in the test-runner hook
Configure which rules run per story via the a11y parameters and the runner's postVisit hook, disabling only rules that do not apply.
// .storybook/test-runner.ts
import { injectAxe, checkA11y } from 'axe-playwright';
export default {
async postVisit(page) {
await injectAxe(page);
await checkA11y(page, '#storybook-root');
},
};How to prevent it
- Fix real a11y violations rather than globally disabling axe.
- Configure rule exceptions narrowly in a11y parameters.
- Run the a11y checks locally before pushing.