DEV Community

Cover image for The 5 Best Addons for Building Accessible React Components in Storybook
Kathryn Grayson Nanz
Kathryn Grayson Nanz

Posted on

The 5 Best Addons for Building Accessible React Components in Storybook

If you've ever created a component library (or even thought about creating your own), you already know that one of the biggest considerations is accessibility. For those devs who haven't specialized in accessible development and may only know the basics – or not even that! – building accessible components from scratch is a daunting prospect.

This is one of those benefits of using a pre-made component library – not having to worry about doing this yourself, knowing that someone else has put in the time and research to guarantee an accessible experience for your users. There are lots of great, existing libraries out there if that's the path you want to take (KendoReact being one of my favorites), but there are also lots of valid reasons why an out-of-the-box library wouldn't work and you'll need to create your own.

No matter the reason, if you're going to be rolling your own components, it's important to prioritize accessibility during your development process. Thankfully, Storybook (one of the most popular component library managers) has a ton of great addons that will make accessibility a natural part of your component creation. I've created a demo, which you can clone and use as the base for your own, or just poke around and use to try out the addons I'm suggesting before adding them to your existing setup. That being said, let's get into it!

If you already know how to install Storybook and add addons, you can skip right to the list.

Creating your Storybook instance

If you're starting completely from scratch, let's go ahead and set up your project. You can do this quickly and easily by using npx create-react-appto get your React app up and running, and then npx sb init to install Storybook. Use npm run storybook to check that everything is working as intended, and now we're ready to start customizing your setup for accessibility!

Note that any time you add a new addon, you'll need to rebuild your Storybook before you see the changes!

Installing Storybook addons

For all of the addons in this list, you'll need to take the following steps to install and add them to your Storybook instance:

  1. Install the addon with npm install [addon-name-here]
  2. Add the addon to the addons section of your module.exports in the main.js file. Storybook installs with a few addons automatically installed, so you'll just want to add your new addon to the list.

    module.exports = {
      addons: [
  3. Make any additional adjustments specific to that addon (I've detailed these in each section, when there are specific configurations that I recommend).

  4. Stop and restart your Storybook build, in order to see the changes.

1. Addon-a11y

addon-a11y is probably the most popular and beloved Storybook accessibility addon – and for good reason. It's packed with great features, and runs on the well-known Deque Systems Axe Accessibility Engine.

How does this help?

This addon does two main things:

  1. Adds a new panel to the addons drawer in Storybook, which will automatically run accessibility checks on your components as you work and alert you of violations, passes, and incomplete checks based off the WCAG accessibility guidelines.
  2. Adds a new vision adjustment tool to the header, which can simulate blurred vision as well as many different varieties of color blindness.

The accessibility panel in the addons drawer

The vision adjustment tool in the menu bar

Configuring this addon

The primary way to configure this addon centers around disabling or overriding the various rules that the addon uses to check your stories. This should only be done if you're 100% confident that the addon is throwing a false violation – otherwise, you're just ignoring the information you asked it to show you. If needed, however, you can disable individual rules or all checks at either the story or global level. More detailed information on these options can be found in the addon-a11y docs.

2. Dark Mode

storybook-dark-mode is an addon that allows you to easily toggle your Storybook UI (and the component preview pane) between light and dark mode.

How does this help?

You might be wondering why dark mode made the list of an accessibility article...and the answer is, lots of reasons! Dark mode is an important accessibility feature in and of itself, for folks that struggle with migraines, light sensitivity, eye strain, and similar. Beyond that, however, dark mode is often forgotten when developers are running their accessibility checks – can you guarantee that your color contrast is still good enough in dark mode, or that your focus highlight is still clearly visible? It's not enough to only be accessible in light mode!

Configuring this addon

This is an addon that really benefits from some advanced configuration, because it's important to make sure that your Storybook environment matches your application environment as closely as possible.

To customize this addon, you'll want to add the following parameters for darkMode to your preview.js file, as well as making sure you're importing themes at the top:

import { themes } from '@storybook/theming';
import customDarkTheme from './customDarkTheme' 

export parameters = {
  darkMode: {
    // Overrides the default dark theme
    dark: { ...customDarkTheme, appBg: 'black' },
    // Overrides the default light theme
    light: { ...themes.normal, appBg: 'white' },
        // Sets the theme Storybook starts with 
    current: 'light',
        // Sets the name of your dark mode class 
        darkClass: 'lights-out',
        // Sets the name of your light mode class 
    lightClass: 'lights-on',
        // Applies the dark / light mode classes to your preview iFrame  
    stylePreview: true
Enter fullscreen mode Exit fullscreen mode

There's a lot of adjustments we made here, so let's take them in order:

  1. Creating a custom theme

    The Storybook default dark mode will put your components over a pure black #000 background, but more often, dark modes actually use a dark grey like #121212 . Since we want to make sure we're creating components in the same environment they'll be used, that means we need to create a custom theme in order to adjust this background value. Good news, this is super easy to do!

    You can create files for your custom themes in the .storybook folder. The Storybook docs have a great rundown on all the details for theming, but for this we're only interested in changing the content background. To do so, you'll just create a custom dark theme which uses the Storybook dark theme as a base, but overwrites the appContentBg value.

    import { create } from '@storybook/theming';
    export default create({
      base: 'dark',
      appContentBg: '#121212'
  2. Defining the dark mode with dark: { ...customDarkTheme, appBg: 'black' }

    Now that we have our custom theme, we'll import that into preview.js and use it when setting the dark parameter in the darkMode addon configuration.

  3. Defining the light mode with light: { ...themes.normal, appBg: 'white' }

    In this case, we don't want to make any changes to the light mode theme, but if you wanted to you could also create a custom theme and use it here in place of themes.normal

  4. Setting the default theme with current: 'light'

    This line of code tells Storybook whether to start in light or dark mode. It's a little thing, but if you're working on your dark mode CSS, you'll quickly tire of toggling the mode in the header over and over.

  5. Setting the class names for your dark and light mode with darkClass and lightClass

    These are what allow you to match Storybook's CSS to the CSS in your application by changing the names of the dark and light mode classes that get applied to the Storybook UI. If your app uses a dark mode class called night, you'll want to change that here to make sure that Storybook is using the same class name – that way, you can easily write and test CSS that will work in both places.

  6. Copying the class name to the preview iFrame with sylePreview

    This final step is small, but important! Setting stylePreview to true tells Storybook to also apply that dark / light mode class name to the component preview window, as well as the main application body. If you don't do this, then you won't be able to use the dark or light mode class names in your component styles, since the components are rendered inside an iFrame and the application level Storybook styles won't cascade naturally.

    Example time!

    You can see in the code below that the dark mode class lights-out is being applied to the html element in my preview iFrame, thanks to the addon configurations listed above.

    Snippet of HTML in Chrome DevTools inspect element tool, showing the 'lights-out' class applied at the iFrame  raw `<html>` endraw  level

    Now, I can write CSS like:

    .lights-out h1 {
      color: white;

    And have it toggle the styles in my components automatically as I switch between dark and light mode!

    The Storybook menu bar showing dark mode activated

    The Storybook menu bar showing light mode activated

3. Built-in Storybook Screen Reader

addon-screen-reader is a super handy addon that adds a basic screen reader right to Storybook – no external software needed!

How does this help?

This allows you to test your basic keyboard nav and page structure super easily. While this basic version is not as full-featured as an actual screen reader would be, it's a great way to make sure you're checking the box on the basics while you're working – then, you can circle back with more in-depth testing later.

Configuring this addon

Good news, after that last complicated one – this addon is plug-and-play! Just install like any other addon and a panel will be added to the drawer called 'Screen Reader'. You can use that to toggle the voice and text reader options.

The addons drawer open to the Screen Reader tab, showing two switches for Voice Reader and Text Reader both switched on

4. Aria Live Addon

If you're building any kind of component that will populate new data on the screen, the aria-live-storybook-addon is here to help you do so accessibly!

How does this help?

If you're unfamiliar with aria-live, it's an attribute that you add to your HTML elements in order to let screen readers know the element is going to change dynamically, and that the screen reader should keep an eye on that element in order to tell the user about any changes. You can set two different types of aria-live announcements: polite and assertive. Polite should be used for most cases, and assertive only used when you need to interrupt a user's actions to announce critical changes.

This addon adds a new panel to the drawer called 'Aria Live Regions', which will show you when an action triggers an aria-live announcement and whether it's polite or assertive. This way, you can confirm that the announcements are triggering correctly, and with the correct type.

Configuring this addon

This addon requires no configuration – yay! Just add the aria-live attribute to the HTML element in your component and it will automatically add announcements to the panel whenever one is generated.

The drawer open to the Aria Live tab, showing 2 Polite and 3 Assertive aria-live announcements recorded

5. Pseudo States Addon

storybook-addon-psuedo-states allows you to quickly toggle through all possible element pseudo states from the Storybook menu bar.

How does this help?

This addon basically duplicates the functionality of the "Toggle Element State" tool from your Dev Tools, but without you ever having to leave Storybook. Pseudo states are incredibly important for accessible development – especially the focus and focus-within states. Any users who use a keyboard as their primary way of navigation will need a clearly visible focus in order to find their way around, so being able to easily design, develop, and test these easily within Storybook is a huge advantage.

Configuring this addon

With this addon, I highly recommend taking advantage of one useful configuration option: the ability to set your Storybook components to automatically set certain pseudo states on load. You can do this by adding a new set of parameters to your component's stories.jsx file, where you export your story variations.

export const Primary = Template.bind({});
Primary.args = {
  primary: true,
  label: 'Button',
Primary.parameters = {
  pseudo: { hover: true, focus: true }
Enter fullscreen mode Exit fullscreen mode

Just add that pseudo section to the parameters for your story variant, and set any pseudo states you want active on load to true . You'll still be able to toggle the pseudo states on and off from the menu bar, but now they'll start with whatever you listed automatically enabled. This is especially nice for when you're working on the CSS for a specific pseudo state, or if you want to test various pseudo states without enabling them manually every time.

The Storybook menu bar with the Focus States dropdown menu expanded and the  raw `:focus` endraw  option selected

Ready to get to work?

There you have it: my list of the top 5 accessibility addons for Storybook. With all of these installed, you'll never have to go out of your way to write or test accessible components again – so no more excuses! Are there any Storybook addons you use that I should add to my list? Do you have any questions about configuration or installation? Let me know in the comments below, and thanks for reading!

Top comments (4)

irreverentmike profile image
Mike Bifulco

These are all great recommendations (even at 5pm on a Friday 😉)! When I first started using Storybook, I thought this kind of thing would be the perfect target for my friends at Stark to dive in on. Thankfully an open community of plugins has made it easy by now!

kevinz69493272 profile image

Just curious. Do you build on top of existing React UI library components? I found it saves lots of work to pick a OSS lib that allows me to import individual components,a and wrap on top of them. Examples like Chakra UI. It is a bit reassuring to know you can start with the basic a11y attributes mostly right, and there is a whole community who have done the work for us. What do you think?

kathryngrayson profile image
Kathryn Grayson Nanz

I think both approaches can be worthwhile! Sometimes, you just need to build completely from scratch because you need something specific that isn't in a library. But when you can take advantage of an existing library, I definitely say go for it so that you don't have to re-invent the wheel. Just make sure you've actually tested the components yourself to confirm they meet the accessibility standards of your application – some libraries are more lenient with that definition than others!

fandredev profile image

Thanks for this!