This Storybook addon can be helpful to make your UI components more accessible.
First, install the addon.
$ yarn add @storybook/addon-a11y --dev
Add this line to your main.js
file (create this file inside your Storybook config directory if needed).
export default {
addons: ['@storybook/addon-a11y'],
};
And here's a sample story file to test the addon:
import React from 'react';
export default {
title: 'button',
};
export const Accessible = () => <button>Accessible button</button>;
export const Inaccessible = () => (
<button style={{ backgroundColor: 'red', color: 'darkRed' }}>Inaccessible button</button>
);
When Axe reports accessibility violations in stories, there are multiple ways to handle these failures depending on your needs.
At the Story level, override rules using parameters.a11y.config.rules
.
export const InputWithoutAutofill = () => <input type="text" autocomplete="nope" />;
InputWithoutAutofill.parameters = {
a11y: {
// Avoid doing this, as it will fully disable all accessibility checks for this story.
disable: true,
// Instead, override rules 👇
// axe-core configurationOptions (https://github.com/dequelabs/axe-core/blob/develop/doc/API.md#parameters-1)
config: {
rules: [
{
// You can exclude some elements from failing a specific rule:
id: 'autocomplete-valid',
selector: '*:not([autocomplete="nope"])',
},
{
// You can also signify that a violation will need to be fixed in the future
// by overriding the result of a rule to return "Needs Review"
// rather than "Violation" if the rule fails:
id: 'landmark-complementary-is-top-level',
reviewOnFail: true,
},
],
},
},
};
Alternatively, you can disable specific rules in a Story:
export const Inaccessible = () => (
<button style={{ backgroundColor: 'red', color: 'darkRed' }}>Inaccessible button</button>
);
Inaccessible.parameters = {
a11y: {
config: {
rules: [{ id: 'color-contrast', enabled: false }],
},
},
};
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:
MyStory.parameters = {
a11y: {
config: {
rules: [
{
// Allow `autocomplete="nope"` on form elements,
// a workaround to disable autofill in Chrome.
// @link https://bugs.chromium.org/p/chromium/issues/detail?id=468153
id: 'autocomplete-valid',
selector: '*:not([autocomplete="nope"])',
},
{
// @fixme Color contrast of subdued text fails, as raised in issue #123.
id: 'color-contrast',
reviewOnFail: true,
},
],
},
},