Storybook addon that provides comprehensive accessibility testing for UI components using axe-core engine to ensure WCAG compliance
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Storybook Accessibility Addon provides comprehensive accessibility testing for UI components using the axe-core engine. It enables developers to automatically test their Storybook stories for WCAG compliance and web accessibility standards, offering real-time accessibility analysis with visual feedback, violation detection, color vision simulation, and detailed reporting.
npx storybook add @storybook/addon-a11yimport { PARAM_KEY, A11yTypes } from "@storybook/addon-a11y";For complete addon functionality (includes preview configuration):
import addon, {
PARAM_KEY,
A11yTypes,
A11yParameters,
run,
getTitleForAxeResult,
getFriendlySummaryForAxeResult,
getIsVitestStandaloneRun,
getIsVitestRunning
} from "@storybook/addon-a11y";For preview configuration (re-exported from main entry):
import { afterEach, initialGlobals, parameters } from "@storybook/addon-a11y/preview";For manager registration:
import "@storybook/addon-a11y/manager";For CLI postinstall (used internally by Storybook CLI):
import postinstall from "@storybook/addon-a11y/postinstall";// .storybook/main.ts
export default {
addons: ["@storybook/addon-a11y"],
};// stories/Button.stories.ts
import type { Meta, StoryObj } from '@storybook/react';
import { Button } from './Button';
const meta: Meta<typeof Button> = {
component: Button,
parameters: {
a11y: {
// Configure accessibility testing options
options: {
rules: {
'color-contrast': { enabled: true }
}
},
// Disable accessibility testing for this story
disable: false,
// Set test mode: 'off' | 'todo' | 'error'
test: 'error'
},
},
};
export default meta;
type Story = StoryObj<typeof meta>;
export const Primary: Story = {
parameters: {
a11y: {
context: {
// Include specific elements for testing
include: ['.primary-button'],
// Exclude elements from testing
exclude: ['.decorative-only']
}
}
}
};The Storybook Accessibility Addon is built around several key components:
Core configuration options for customizing accessibility testing behavior, including axe-core options, context specification, and test modes.
interface A11yParameters {
context?: ContextSpecWithoutNode;
options?: RunOptions;
config?: Spec;
disable?: boolean;
test?: 'off' | 'todo' | 'error';
}
interface A11yGlobals {
a11y?: {
manual?: boolean;
};
}Automated accessibility testing capabilities that run axe-core tests on stories through the afterEach hook, with support for different execution modes and detailed result reporting.
const afterEach: AfterEach<any> = async ({
id: storyId,
reporting,
parameters,
globals,
viewMode,
}) => Promise<void>;
interface EnhancedResults extends Omit<AxeResults, 'incomplete' | 'passes' | 'violations'> {
incomplete: EnhancedResult[];
passes: EnhancedResult[];
violations: EnhancedResult[];
}Internal React components that provide the accessibility testing interface within Storybook, automatically registered when importing the manager.
// These components are automatically registered when importing the manager
import "@storybook/addon-a11y/manager";
// Internal components (not directly importable):
// - A11YPanel: Main accessibility panel component
// - A11yContextProvider: Context provider for accessibility state
// - VisionSimulator: Vision impairment simulation toolComprehensive internal mapping system that converts axe-core rule violations into user-friendly descriptions and remediation guidance displayed in the UI.
type AxeRuleMap = {
[axeId: string]: {
title: string;
axeSummary: string;
friendlySummary: string;
};
};
const combinedRulesMap: AxeRuleMap;interface A11yTypes {
parameters: A11yParameters;
globals: A11yGlobals;
}
type A11YReport = EnhancedResults | { error: Error };
const RuleType = {
VIOLATION: 'violations',
PASS: 'passes',
INCOMPLETION: 'incomplete',
} as const;
type RuleType = (typeof RuleType)[keyof typeof RuleType];interface EnhancedNodeResult extends NodeResult {
linkPath: string;
}
interface EnhancedResult extends Omit<Result, 'nodes'> {
nodes: EnhancedNodeResult[];
}type SelectorWithoutNode = Omit<Selector, 'Node'> | Omit<SelectorList, 'NodeList'>;
type ContextObjectWithoutNode =
| {
include: SelectorWithoutNode;
exclude?: SelectorWithoutNode;
}
| {
exclude: SelectorWithoutNode;
include?: SelectorWithoutNode;
};
type ContextSpecWithoutNode = SelectorWithoutNode | ContextObjectWithoutNode;// Test runner function for executing accessibility tests
function run(input?: A11yParameters, storyId: string): Promise<EnhancedResults>;
// Rule mapping helpers for user-friendly descriptions
function getTitleForAxeResult(axeResult: EnhancedResult): string;
function getFriendlySummaryForAxeResult(axeResult: EnhancedResult): string | undefined;
// Environment detection utilities
function getIsVitestStandaloneRun(): boolean;
function getIsVitestRunning(): boolean;// Exported constant
const PARAM_KEY = 'a11y';
// Internal constants (not exported):
// const ADDON_ID = 'storybook/a11y';
// const PANEL_ID = 'storybook/a11y/panel';
// const DOCUMENTATION_LINK = 'writing-tests/accessibility-testing';
// const TEST_PROVIDER_ID = 'storybook/addon-a11y/test-provider';// CLI postinstall automation function
function postinstall(options: PostinstallOptions): Promise<void>;
interface PostinstallOptions {
yes?: boolean;
packageManager?: string;
configDir?: string;
}