Skip to main content

Overview

Accessibility is a core requirement in the User Interface Wiki. All components must follow WCAG guidelines, use semantic HTML, provide proper ARIA attributes, support keyboard navigation, and respect user motion preferences.

Semantic HTML

Use Appropriate Elements

Always use semantic HTML elements that match the component’s purpose:

Interactive Elements

Buttons vs Links:
element
Use for actions that change application state (open modal, submit form, toggle state)
element
Use for navigation to different pages or sections

Semantic Component Example

From the actual Button component:
components/button/index.tsx
Base UI components provide semantic HTML by default, which is why we use them as primitives.

ARIA Attributes

When to Use ARIA

ARIA attributes supplement semantic HTML when native elements are insufficient:
First Rule of ARIA: If you can use a native HTML element or attribute with the semantics and behavior you require already built in, do so. Only use ARIA when semantic HTML is not enough.

Common ARIA Patterns

Labels and Descriptions

Live Regions

Announce dynamic content changes to screen readers:

Tab Pattern

Dialog/Modal Pattern

Real Example: Popover Component

From the actual codebase:
components/popover/index.tsx
Base UI components handle complex ARIA patterns correctly, which is a major reason we use them.

Focus Management

Visible Focus Indicators

All interactive elements must have visible focus states:
components/button/styles.module.css
Use :focus-visible instead of :focus to show outlines only for keyboard navigation, not mouse clicks.

Focus Outline Pattern

Consistent focus styling across components:

Keyboard Navigation

Ensure all interactive features are keyboard accessible:
key
Move focus forward through interactive elements
key
Move focus backward through interactive elements
key
Activate buttons and links
key
Close dialogs, popovers, and modals
key
Navigate within composite widgets (tabs, menus, listboxes)

Focus Trap for Modals

When a modal opens, trap focus within it:
Base UI Popover, Dialog, and other overlay components handle focus management automatically. Provide skip navigation for keyboard users:
From styles.css
Layout Component

Reduced Motion

Respect User Preferences

Always respect the prefers-reduced-motion media query:

Motion Library Support

Use Motion’s built-in reduced motion support:
Motion automatically disables animations when prefers-reduced-motion: reduce is set.

Manual Reduced Motion Check

For custom animations:

CSS Transitions with Reduced Motion

Pattern from the Figure component:
components/figure/styles.module.css

Color Contrast

WCAG AA Compliance

The Radix UI Colors used in the theme meet WCAG AA contrast requirements:
Radix UI color scales are designed so that:
  • Steps 1-2: Backgrounds, subtle fills
  • Steps 3-5: UI borders and separators
  • Steps 6-8: Hovered UI backgrounds
  • Steps 9-10: Solid backgrounds, hovered text
  • Steps 11-12: Low-contrast text, high-contrast text

Testing Contrast

Always verify color combinations meet minimum contrast ratios:
  • Normal text: 4.5:1 (WCAG AA)
  • Large text: 3:1 (WCAG AA)
  • Interactive elements: 3:1 (WCAG AA)

Screen Reader Support

Descriptive Labels

Hide Decorative Elements

Announce Dynamic Changes

Alt Text for Images

Provide descriptive alt text for meaningful images:

Testing Checklist

Before shipping a component, verify:
  • All interactive elements are focusable with Tab
  • Focus order is logical and follows visual layout
  • Focus indicators are visible with :focus-visible
  • All functionality is available via keyboard
  • Escape closes modals and popovers
  • Semantic HTML elements are used correctly
  • Interactive elements have descriptive labels
  • Decorative elements are hidden with aria-hidden
  • Dynamic content changes are announced
  • Images have descriptive alt text
  • Animations respect prefers-reduced-motion
  • Motion duration doesn’t exceed 300ms for user-initiated actions
  • No auto-playing animations longer than 5 seconds
  • Users can pause, stop, or hide animations
  • Text meets WCAG AA contrast ratio (4.5:1)
  • Interactive elements meet 3:1 contrast
  • Color is not the only means of conveying information
  • Dark mode maintains proper contrast ratios

Tools for Testing

  • Keyboard: Test with keyboard only (no mouse)
  • Screen Reader: Test with VoiceOver (macOS), NVDA (Windows), or JAWS
  • Browser DevTools: Lighthouse accessibility audit
  • axe DevTools: Browser extension for automated accessibility testing
  • Contrast Checker: WebAIM Contrast Checker for color verification

Resources