Chapter 15: Accessibility as a System Requirement
Core Idea
A design system's biggest accessibility leverage is structural: fixing keyboard behavior, focus management, or ARIA semantics once in a shared component fixes it everywhere that component is used — which makes accessibility a system-level responsibility, not something each product team re-solves per feature.
Key Concepts
- WCAG as the baseline: Web Content Accessibility Guidelines (current stable version WCAG 2.2, with WCAG 3 in development) at the AA conformance level is the de facto standard most organizations target — covers perceivable/operable/understandable/robust content requirements.
- Automated testing: tools like axe-core (often via Storybook's a11y addon or CI integration) catch a meaningful subset of issues automatically — color contrast, missing labels, invalid ARIA usage — but only a subset; automated tools typically catch well under half of real-world accessibility issues.
- Manual testing is not optional: keyboard-only navigation testing and screen reader testing (VoiceOver, NVDA, JAWS) catch what automated tools structurally cannot — logical focus order, meaningful announcements, usability of complex interaction patterns.
- Accessible by default vs. accessible by discipline: a system where the base components (Dialog, Menu, Combobox) already implement correct focus trapping, ARIA roles, and keyboard interaction means consuming teams get accessibility "for free" just by using the components — this is the leverage a design system uniquely has over per-team, per-feature accessibility work.
- What already-covered libraries handle:
radix-primitives-docs and base-ui-docs both bake WAI-ARIA roles, keyboard interaction, and focus management into their primitives by default — a design system built on top of either inherits that baseline rather than reimplementing it.
Mental Models
Accessibility fixed in a shared component is accessibility fixed everywhere at once. This is the single strongest argument for building on accessible primitives instead of ad hoc markup — the leverage compounds with every consuming team.
Automated tests are a floor, not a ceiling. Passing an automated a11y scan proves the absence of certain known-bad patterns; it does not prove the component is actually usable by someone using a screen reader or keyboard-only.
Anti-patterns
- Treating a11y as a per-feature checklist item late in a project: by the time a feature ships, structural accessibility problems (wrong element choice, broken focus order) are expensive to retrofit — cheaper to inherit correctness from the base component.
- Trusting automated scans alone: shipping only what an automated tool flags as clean gives false confidence; real usability issues for assistive-technology users routinely pass automated scans.
Key Takeaways
- Bake accessibility into the base component layer — it's the one place a fix benefits every consuming team simultaneously.
- Use automated tools (axe-core) as a fast first pass, not the final word — pair with real keyboard and screen-reader testing.
- Building on accessible-by-default primitives (Radix, Base UI) is cheaper than re-implementing correct ARIA/focus/keyboard behavior per component.
- Target WCAG 2.2 AA as the practical, industry-standard baseline unless a specific context demands more.
Connects To
radix-primitives-docs, base-ui-docs: concrete primitives that already implement this chapter's "accessible by default" principle.
- Ch 12 (Component API Conventions): composable/compound-component APIs make it easier to preserve correct ARIA relationships between parts.