Accessibility
Accessibility is a baseline, not a feature. Every component, pattern, and token in this system is built to meet WCAG 2.2 Level AA — so the products you ship work for the full range of people who use them.
Our commitment
Inclusive design extends what’s possible for everyone. We design and build for the full range of human ability — permanent, temporary, and situational — rather than treating accessibility as an audit at the end.
Inclusive by default
Accessibility is a baseline, not an enhancement. Every component ships keyboard-operable, screen-reader-labeled, and contrast-validated.
Designed for the spectrum
We design for permanent, temporary, and situational impairments — low vision, cognitive load, one-handed use, bright sunlight, noisy rooms.
Tokens enforce contrast
Color decisions are validated at build time. The token pipeline fails if any required pairing drops below WCAG AA.
Tested with real assistive tech
Components are verified with NVDA, VoiceOver, and keyboard-only flows — not just an automated linter.
Four principles
WCAG organizes accessibility around four ideas. Every guideline on this page maps back to one of them.
Perceivable
Information must be presentable in ways users can sense. Pair color with text or icons, provide alt text for meaningful images, and keep contrast above WCAG AA.
Operable
Every interactive element must work with keyboard alone, expose a visible focus indicator, and respect a touch target of at least 24×24 CSS pixels (44×44 preferred).
Understandable
Use plain language, predictable interaction patterns, and clear, specific error messages. Never rely on color or motion alone to convey meaning.
Robust
Use semantic HTML first; reach for ARIA only to fill gaps. Components must work across modern browsers and the assistive technology people actually use.
Standards we follow
The design system targets WCAG 2.2 Level AA as the minimum. Some criteria are enforced automatically; others require human judgment. The table below covers the criteria most often missed in product work.
| Criterion | Level | Target | Notes |
|---|---|---|---|
| 1.4.3 Contrast (Minimum) | AA | Text 4.5:1, large text 3:1 | Validated by the token build pipeline. |
| 1.4.11 Non-text Contrast | AA | 3:1 for UI components and graphics | Borders, icons, focus rings, form controls. |
| 2.1.1 Keyboard | A | All functionality available from keyboard | No mouse-only interactions. |
| 2.4.7 Focus Visible | AA | Visible focus indicator on every interactive element | 2px outline, contrast 3:1 minimum. |
| 2.4.11 Focus Not Obscured | AA (2.2) | Focused element is not fully hidden | Sticky headers must not cover focused inputs. |
| 2.5.8 Target Size (Minimum) | AA (2.2) | 24×24 CSS pixels minimum | Aim for 44×44 on touch surfaces. |
| 3.3.7 Redundant Entry | A (2.2) | Don't ask users to re-enter the same information | Persist values across multi-step flows. |
| 4.1.2 Name, Role, Value | A | Every control exposes accessible name and role | Use semantic HTML; ARIA only when needed. |
Color & contrast
Contrast is the most-failed accessibility requirement on the web. The token system handles most of this for you — but you still need to know the targets when picking a token or designing a new component.
Body copy, labels, links, anything under 24px regular or 18.66px bold.
24px regular and above, or 18.66px bold and above.
Icons, borders, form controls, focus rings, and graphical objects.
Color is never the only signal
About 1 in 12 men and 1 in 200 women have some form of color vision deficiency. Pair every colored signal with text, an icon, or a pattern. A red error border is not enough — add an error icon and a message that says what went wrong.
Pair feedback color with an icon and explicit text: color.feedback.error.bg + error icon + “Email is required.”
Communicate state with color alone — e.g. a red border on an input with no icon or message.
teal.800, #115662) for text and primary buttons, and reserves Classic Teal for decorative elements and large graphical areas where 3:1 is sufficient.npm run build:tokens to verify locally. For ad-hoc checks, use the Contrast Checker on the Color System page.Keyboard
Many people navigate without a mouse: power users, people with motor impairments, screen reader users, and anyone whose trackpad just died. Every interactive element must be fully operable from the keyboard, with a visible focus indicator.
Visible focus indicator
Press Tab to move focus through the elements below. The focus ring is 2px in the focus token color, with a 2px offset.
Standard key bindings
| Keys | Action |
|---|---|
| Tab | Move focus to the next interactive element |
| Shift+Tab | Move focus to the previous interactive element |
| Enter | Activate the focused button or link, submit a form |
| Space | Activate buttons, toggle checkboxes, open menus |
| Esc | Close a modal, popover, or menu — return focus to the trigger |
| Arrow keys | Move within composite widgets (menus, tabs, radio groups, sliders) |
| Home+End | Jump to first / last item in a composite widget |
tabindex values — they break the natural reading order. Use tabindex="0" only to make a non-interactive element focusable, and tabindex="-1" only to programmatically move focus.Screen readers & semantics
Semantic HTML carries meaning that styling alone cannot. A <button> announces as a button; a <div> with a click handler announces as nothing. Reach for ARIA only when no semantic element does the job.
Use native elements: <button>, <a href>, <label for>, <nav>, <main>.
Build interactive controls from <div> or <span> with click handlers — you lose keyboard support, focus, and the accessible role.
Give icon-only buttons an accessible name: aria-label="Close" or visually hidden text inside the button.
Ship icon-only controls with no label. Screen readers will announce them as “button” with no purpose.
Use one <h1> per page and descend through heading levels without skipping. Headings form the document outline screen readers use to navigate.
Pick heading levels for visual size. Use the right level for the structure, then style with a typography token.
Touch targets
WCAG 2.2 added a minimum target size of 24×24 CSS pixels. The design system aims for 44×44 on touch surfaces — the comfort threshold from years of mobile research.
Absolute floor — never go below this.
Apple HIG; comfortable single-tap on phones.
Android baseline; use for primary actions.
Motion & animation
Motion can disorient or trigger symptoms for users with vestibular disorders. The system honors prefers-reduced-motion across every animated component — reduce to a fade or remove the animation entirely, never just speed it up.
Always wrap motion
Wrap any non-essential transform, parallax, or auto-playing animation in the reduced motion query.
@media (prefers-reduced-motion: reduce) {
.card {
transition: none;
animation: none;
}
}Allow opacity fades
Opacity changes and short crossfades are generally safe. Keep durations short (<200ms) and avoid scaling, rotating, or large translations.
/* Safe — opacity only */
.toast {
transition: opacity 150ms ease;
}Forms & errors
Forms are where most products fail accessibility tests. Three rules cover the majority of issues: every field has a label, every error is announced, and the user can recover without losing data.
Associate label with input via <label for="email"> + id="email". Link errors and helper text with aria-describedby.
Use placeholder text as the only label. It disappears on input, fails contrast, and isn’t reliably read by assistive tech.
Write errors that describe the problem and how to fix it: “Email must include an @ symbol.”
Show generic errors like “Invalid input.” The user has to guess what went wrong.
Practical checklist
Run through this list before merging a PR or before a design review. It covers the issues that surface most often in accessibility audits.
- Keyboard: Every interactive element is reachable with Tab, activates with Enter or Space, and shows a visible focus ring.
- Order: Tab order matches visual reading order. Skip links are provided for repeated navigation.
- Labels: Every form control has a programmatically associated label. Icon-only buttons have aria-label or visually hidden text.
- Contrast: Text meets 4.5:1 (or 3:1 for large text). Icons, borders, and focus rings meet 3:1.
- Color: Information conveyed by color is also conveyed by text, icon, or pattern.
- Headings: Page has one h1. Headings descend without skipping levels.
- Landmarks: Page uses header, nav, main, and footer (or equivalent ARIA roles).
- Errors: Form errors describe the problem and how to fix it. Errors are linked to their field with aria-describedby.
- Motion: No content auto-plays for more than 5 seconds. prefers-reduced-motion is honored.
- Zoom: Layout works at 200% zoom and at a viewport of 320px CSS pixels wide.
- Screen reader: Tested at least once with VoiceOver (macOS/iOS) or NVDA (Windows).
Further reading
- WCAG 2.2 Specification →
The complete list of success criteria and conformance requirements.
- ARIA Authoring Practices Guide →
Patterns for accessible widgets — menus, dialogs, comboboxes, tabs, and more.
- WebAIM: Contrast and Color Accessibility →
A clear, in-depth explanation of contrast requirements.
- axe DevTools →
Browser extension for catching common accessibility issues during development.