1 | # storybook-addon-a11y
|
2 |
|
3 | This Storybook addon can be helpful to make your UI components more accessible.
|
4 |
|
5 | [Framework Support](https://storybook.js.org/docs/react/api/frameworks-feature-support)
|
6 |
|
7 | 
|
8 |
|
9 | ## Getting started
|
10 |
|
11 | First, install the addon.
|
12 |
|
13 | ```sh
|
14 | $ yarn add @storybook/addon-a11y --dev
|
15 | ```
|
16 |
|
17 | Add this line to your `main.js` file (create this file inside your Storybook config directory if needed).
|
18 |
|
19 | ```js
|
20 | export default {
|
21 | addons: ['@storybook/addon-a11y'],
|
22 | };
|
23 | ```
|
24 |
|
25 | And here's a sample story file to test the addon:
|
26 |
|
27 | ```js
|
28 | import React from 'react';
|
29 |
|
30 | export default {
|
31 | title: 'button',
|
32 | };
|
33 |
|
34 | export const Accessible = () => <button>Accessible button</button>;
|
35 |
|
36 | export const Inaccessible = () => (
|
37 | <button style={{ backgroundColor: 'red', color: 'darkRed' }}>Inaccessible button</button>
|
38 | );
|
39 | ```
|
40 |
|
41 | ## Handling failing rules
|
42 |
|
43 | When Axe reports accessibility violations in stories, there are multiple ways to handle these failures depending on your needs.
|
44 |
|
45 | ### Story-level overrides
|
46 |
|
47 | At the Story level, override rules using `parameters.a11y.config.rules`.
|
48 |
|
49 | ```js
|
50 | export const InputWithoutAutofill = () => <input type="text" autocomplete="nope" />;
|
51 |
|
52 | InputWithoutAutofill.parameters = {
|
53 | a11y: {
|
54 | // Avoid doing this, as it will fully disable all accessibility checks for this story.
|
55 | disable: true,
|
56 |
|
57 | // Instead, override rules 👇
|
58 | // axe-core configurationOptions (https://github.com/dequelabs/axe-core/blob/develop/doc/API.md#parameters-1)
|
59 | config: {
|
60 | rules: [
|
61 | {
|
62 | // You can exclude some elements from failing a specific rule:
|
63 | id: 'autocomplete-valid',
|
64 | selector: '*:not([autocomplete="nope"])',
|
65 | },
|
66 | {
|
67 | // You can also signify that a violation will need to be fixed in the future
|
68 | // by overriding the result of a rule to return "Needs Review"
|
69 | // rather than "Violation" if the rule fails:
|
70 | id: 'landmark-complementary-is-top-level',
|
71 | reviewOnFail: true,
|
72 | },
|
73 | ],
|
74 | },
|
75 | },
|
76 | };
|
77 | ```
|
78 |
|
79 | Alternatively, you can disable specific rules in a Story:
|
80 |
|
81 | ```js
|
82 | export const Inaccessible = () => (
|
83 | <button style={{ backgroundColor: 'red', color: 'darkRed' }}>Inaccessible button</button>
|
84 | );
|
85 | Inaccessible.parameters = {
|
86 | a11y: {
|
87 | config: {
|
88 | rules: [{ id: 'color-contrast', enabled: false }],
|
89 | },
|
90 | },
|
91 | };
|
92 | ```
|
93 |
|
94 | Tip: clearly explain in a comment why a rule was overridden, it’ll help you and your team trace back why certain violations aren’t being reported or need to be addressed. For example:
|
95 |
|
96 | ```js
|
97 | MyStory.parameters = {
|
98 | a11y: {
|
99 | config: {
|
100 | rules: [
|
101 | {
|
102 | // Allow `autocomplete="nope"` on form elements,
|
103 | // a workaround to disable autofill in Chrome.
|
104 | // @link https://bugs.chromium.org/p/chromium/issues/detail?id=468153
|
105 | id: 'autocomplete-valid',
|
106 | selector: '*:not([autocomplete="nope"])',
|
107 | },
|
108 | {
|
109 | // @fixme Color contrast of subdued text fails, as raised in issue #123.
|
110 | id: 'color-contrast',
|
111 | reviewOnFail: true,
|
112 | },
|
113 | ],
|
114 | },
|
115 | },
|
116 | };
|
117 | ```
|
118 |
|
119 | ### Global overrides
|
120 |
|
121 | When you want to ignore an accessibility rule or change its settings across all stories, set `parameters.a11y.config.rules` in your Storybook’s `preview.ts` file. This can be particularly useful for ignoring false positives commonly reported by Axe.
|
122 |
|
123 | ```ts
|
124 | // .storybook/preview.ts
|
125 |
|
126 | export const parameters = {
|
127 | a11y: {
|
128 | config: {
|
129 | rules: [
|
130 | {
|
131 | // This tells Axe to run the 'autocomplete-valid' rule on selectors
|
132 | // that match '*:not([autocomplete="nope"])' (all elements except [autocomplete="nope"]).
|
133 | // This is the safest way of ignoring a violation across all stories,
|
134 | // as Axe will only ignore very specific elements and keep reporting
|
135 | // violations on other elements of this rule.
|
136 | id: 'autocomplete-valid',
|
137 | selector: '*:not([autocomplete="nope"])',
|
138 | },
|
139 | {
|
140 | // To disable a rule across all stories, set `enabled` to `false`.
|
141 | // Use with caution: all violations of this rule will be ignored!
|
142 | id: 'autocomplete-valid',
|
143 | enabled: false,
|
144 | },
|
145 | ],
|
146 | },
|
147 | },
|
148 | };
|
149 | ```
|
150 |
|
151 | ### Disabling checks
|
152 |
|
153 | If you wish to entirely disable `a11y` checks for a subset of stories, you can control this with story parameters:
|
154 |
|
155 | ```js
|
156 | export const MyNonCheckedStory = () => <SomeComponent />;
|
157 | MyNonCheckedStory.parameters = {
|
158 | // Avoid doing this, as it fully disables all accessibility checks for this story,
|
159 | // and consider the techniques described above.
|
160 | a11y: { disable: true },
|
161 | };
|
162 | ```
|
163 |
|
164 | ## Parameters
|
165 |
|
166 | For more customizability use parameters to configure [aXe options](https://github.com/dequelabs/axe-core/blob/develop/doc/API.md#api-name-axeconfigure).
|
167 | You can override these options [at story level too](https://storybook.js.org/docs/react/configure/features-and-behavior#per-story-options).
|
168 |
|
169 | ```js
|
170 | import React from 'react';
|
171 | import { storiesOf, addDecorator, addParameters } from '@storybook/react';
|
172 |
|
173 | export default {
|
174 | title: 'button',
|
175 | parameters: {
|
176 | a11y: {
|
177 | // optional selector which element to inspect
|
178 | element: '#storybook-root',
|
179 | // axe-core configurationOptions (https://github.com/dequelabs/axe-core/blob/develop/doc/API.md#parameters-1)
|
180 | config: {},
|
181 | // axe-core optionsParameter (https://github.com/dequelabs/axe-core/blob/develop/doc/API.md#options-parameter)
|
182 | options: {},
|
183 | // optional flag to prevent the automatic check
|
184 | manual: true,
|
185 | },
|
186 | },
|
187 | };
|
188 |
|
189 | export const accessible = () => <button>Accessible button</button>;
|
190 |
|
191 | export const inaccessible = () => (
|
192 | <button style={{ backgroundColor: 'red', color: 'darkRed' }}>Inaccessible button</button>
|
193 | );
|
194 | ```
|
195 |
|
196 | ## Roadmap
|
197 |
|
198 | - Make UI accessible
|
199 | - Show in story where violations are.
|
200 | - Add more example tests
|
201 | - Add tests
|
202 | - Make CI integration possible
|