Join us live: Agentic Design Systems with Brad Frost

A Screen Reader Storybook addon for accessibility testing

View on GithubNew to Storybook?Get started

Storybook Screen Reader Addon

NPM Version

A screen reader simulation addon for Storybook that helps developers test accessibility during component development. It uses industry-standard libraries to provide accurate accessible name computation and role announcements.

Screen Reader Demo

Features

  • 🎯 W3C AccName Spec - Uses dom-accessibility-api for accurate accessible name computation
  • 🏷️ ARIA Role Detection - Uses aria-query for proper role mapping
  • πŸ”Š Voice Reader - Uses Web Speech API to announce focused elements
  • πŸ“ Text Reader - Displays announcements in the addon panel
  • 🎯 Focus Tracking - Automatically tracks focus changes (Tab, arrow keys, clicks)
  • πŸ“’ Live Regions - Announces aria-live region updates
  • 🌐 Deep Shadow DOM Support - Traverses into shadow roots to find the actual focused element (like real screen readers)
  • 🎨 Spectrum Web Components UI - Built with Lit + SWC for the addon panel
  • πŸ”„ Story Navigation - Automatically resets when switching between stories

Comparison: This Plugin vs macOS VoiceOver

Feature This Plugin VoiceOver (macOS) Notes
Accessible Name Computation βœ… W3C AccName spec βœ… Native We use dom-accessibility-api which implements the full W3C spec
Accessible Description βœ… aria-describedby βœ… Native Full support via dom-accessibility-api
ARIA Roles βœ… 40+ roles βœ… All roles We use aria-query for accurate role detection
Focus Tracking βœ… focusin event βœ… Native Tracks Tab, Shift+Tab, clicks
Shadow DOM Traversal βœ… Deep active element βœ… Native Finds actual focused element inside shadow roots
Arrow Key Navigation βœ… aria-activedescendant βœ… Native For menus, listboxes, trees
Live Regions βœ… aria-live βœ… Native Announces dynamic content changes
Form States βœ… required, invalid, readonly βœ… Native Comprehensive form feedback
Button States βœ… pressed, expanded βœ… Native Toggle buttons, accordions
List Position βœ… "Item X of Y" βœ… Native Lists, tabs, options
Table Navigation ⚠️ Basic βœ… Full We announce row/column counts
Checkbox States βœ… checked, mixed, unchecked βœ… Native Tri-state support
Slider Values βœ… value, min, max, valuetext βœ… Native Full range announcements
Virtual Buffer Mode ❌ Not supported βœ… Native NVDA/JAWS feature, not VoiceOver
Reading All Content ❌ Focus-only βœ… Browse mode We only announce focused elements
OS Integration ❌ Browser only βœ… System-wide VoiceOver works across all apps
Braille Output ❌ Not supported βœ… Native Hardware requirement

What We Implement

Category Supported Features
Roles button, link, checkbox, radio, switch, textbox, searchbox, combobox, listbox, slider, spinbutton, heading, img, listitem, option, menuitem, tab, tabpanel, navigation, main, banner, contentinfo, complementary, region, article, form, search, dialog, alertdialog, alert, status, log, progressbar, meter, tooltip, tree, treeitem, grid, table, menu, menubar, toolbar, group, separator
States checked, pressed, expanded, selected, invalid, required, readonly, disabled
Properties aria-label, aria-labelledby, aria-describedby, aria-valuenow, aria-valuemin, aria-valuemax, aria-valuetext, aria-level, aria-activedescendant, aria-modal
Live Regions aria-live (polite/assertive), role="alert", role="status", role="log"

Accuracy & Trust Level

Use Case Reliability Recommendation
Quick dev feedback βœ… High Great for catching obvious issues
ARIA role verification βœ… High Accurate role mapping via aria-query
Accessible name testing βœ… High W3C spec via dom-accessibility-api
Focus order testing βœ… High Reliable focus tracking
Live region testing βœ… Medium Basic support, may miss edge cases
Full WCAG compliance ⚠️ Medium Use with real screen readers
Production sign-off ❌ Low Always test with VoiceOver/NVDA

Recommended Testing Workflow

1. πŸ› οΈ  Development    β†’  Use this plugin (instant feedback)
2. πŸ”  Code Review    β†’  Use axe-core / Storybook a11y addon  
3. βœ…  QA Testing     β†’  Use REAL VoiceOver / NVDA
4. πŸ‘₯  User Testing   β†’  Involve actual screen reader users

Installation

npm install storybook-screen-reader

or

yarn add storybook-screen-reader

Setup

Add the addon to your .storybook/main.js:

module.exports = {
  addons: [
    // ... other addons
    'storybook-screen-reader',
  ],
};

Usage

  1. Open Storybook and navigate to any story
  2. Click the "Screen Reader" tab in the addons panel
  3. Enable Voice Reader and/or Text Reader
  4. Navigate through your component:
    • Tab / Shift+Tab - Move between focusable elements
    • Arrow keys - Navigate within menus, listboxes, etc.
    • Click - Focus any element

The addon will announce each focused element with its role, name, and state.

Announcement Examples

Element Announcement
Button "Button, Submit. Press Space or Enter to activate."
Toggle Button "Button, Dark mode, pressed. Press Space or Enter to activate."
Link "Link, Learn more. Press Enter to follow."
Checkbox "Checkbox, Accept terms, not checked. Press Space to toggle."
Radio "Radio button, Option A, selected."
Switch "Switch, Notifications, on. Press Space to toggle."
Text Field "Text field, Email, required. Empty."
Invalid Field "Text field, Password, required, invalid entry. Contains: ****"
Slider "Slider, Volume. Value: 75. Range: 0 to 100."
Heading "Heading level 2, Welcome"
Tab "Tab, Settings, selected. 2 of 4."
List Item "Home. List item 1 of 5."
Menu Item "Menu item, Copy"
Dialog "Modal Dialog, Confirm deletion"
Alert "Alert: Your session will expire in 5 minutes"
Progress "Progress bar, Uploading. 45 percent"
Table "Table, User data. 10 rows, 4 columns."

Technical Details

Libraries Used

Library Purpose
dom-accessibility-api W3C Accessible Name and Description computation
aria-query ARIA role definitions and element-to-role mapping
lit Web component framework for addon panel
@spectrum-web-components Adobe Spectrum design system components

Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    Storybook Manager                         β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚  screen-reader-panel (Lit + SWC)                     β”‚   β”‚
β”‚  β”‚  └── Toggle switches for voice/text output          β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                              β”‚
                              β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    Storybook Preview (iframe)                β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚  ScreenReader class                                  β”‚   β”‚
β”‚  β”‚  β”œβ”€β”€ Focus tracking (focusin event)                 β”‚   β”‚
β”‚  β”‚  β”œβ”€β”€ ARIA attribute monitoring (MutationObserver)   β”‚   β”‚
β”‚  β”‚  β”œβ”€β”€ Live region monitoring (MutationObserver)      β”‚   β”‚
β”‚  β”‚  β”œβ”€β”€ Name computation (dom-accessibility-api)       β”‚   β”‚
β”‚  β”‚  β”œβ”€β”€ Role detection (aria-query)                    β”‚   β”‚
β”‚  β”‚  └── Speech synthesis (Web Speech API)              β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Limitations

This addon is a development aid, not a replacement for testing with real screen readers:

What We Can't Do Why
Access OS Accessibility Tree Browser security restrictions
Virtual/Browse mode VoiceOver reads all content, we only track focus
Braille output Hardware requirement
System-wide announcements Browser sandbox
100% VoiceOver parity Different underlying technology

Always test with actual assistive technology before shipping:

  • VoiceOver (macOS/iOS)
  • NVDA (Windows, free)
  • JAWS (Windows)
  • TalkBack (Android)

Compatibility

  • Storybook 8.x
  • React, Vue, Angular, Web Components, HTML
  • Works with Shadow DOM

Contributing

Issues and PRs welcome! GitHub Repository

Credits

Originally created by VΓ­ctor Lara. Updated and maintained by Tarun Tomar.

License

MIT