Skip to content

Accessibility Standards & Requirements

MANDATORY Accessibility Compliance

  • ALL new components MUST meet WCAG 2.1 AA accessibility standards - no exceptions.
  • Accessibility features must be implemented BEFORE code is considered complete.
  • Design components to be accessible by default, not as an afterthought.

ARIA Attributes & Semantic HTML

  • Landmark Roles: Use proper HTML5 semantic elements (header, main, nav, aside, footer) with appropriate role attributes.
  • ARIA Labels: Provide descriptive aria-label attributes for interactive elements where text content is insufficient.
  • ARIA States: Use aria-expanded, aria-current, aria-hidden, aria-live appropriately for dynamic content.
  • ARIA Relationships: Implement aria-labelledby, aria-describedby, aria-controls for element relationships.
  • Screen Reader Support: All interactive elements must have meaningful labels for screen readers.

Keyboard Navigation Requirements

  • Focus Management: Implement proper focus trapping in modals, overlays, and navigation menus.
  • Focus Indicators: ALL focusable elements must have visible focus indicators (use consistent focus:ring-2 focus:ring-blue-500 focus:ring-offset-2).
  • Tab Order: Ensure logical tab order throughout the application.
  • Arrow Keys: Implement arrow key navigation for menus, lists, and grouped controls.
  • Escape Key: Support Escape key to close modals, menus, and overlays.
  • Enter/Space: Support Enter and Space keys for button activation.

Dynamic Content & Live Regions

  • ARIA Live: Use AccessibilityAnnouncer component for dynamic content updates.
  • Status Messages: Announce navigation state changes, form submissions, and loading states.
  • Live Region Types: Use aria-live="polite" for non-urgent updates, aria-live="assertive" for urgent messages.

Images & Media

  • Alternative Text: ALL images must have descriptive alt text that conveys meaning, not just description.
  • Decorative Images: Use aria-hidden="true" or empty alt="" for purely decorative images.
  • Complex Images: Provide detailed descriptions for charts, graphs, and complex visuals.

Focus Trapping

  • Modal Focus: Use useFocusTrap hook for all modal dialogs and overlays.
  • Navigation Focus: Implement focus trapping in mobile navigation menus.
  • Focus Restoration: Always restore focus to the triggering element when closing modals/menus.

Color & Contrast

  • Color Contrast: Ensure minimum 4.5:1 contrast ratio for normal text, 3:1 for large text.
  • Color Independence: Never rely solely on color to convey information.
  • Dark Mode: Maintain accessibility standards in both light and dark themes.

Component-Specific Requirements

Interactive Components

  • All buttons, links, and form controls must have focus indicators.
  • Use consistent focus ring styling: focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2.
  • Provide descriptive labels for screen readers.
  • Implement arrow key navigation for menu items.
  • Support Home/End keys for jumping to first/last items.
  • Use proper ARIA expanded states for collapsible sections.
  • Announce navigation state changes with live regions.

Form Components

  • Associate labels with form controls using htmlFor or aria-labelledby.
  • Provide error messages with aria-describedby.
  • Use fieldsets and legends for grouped form controls.
  • Implement client-side validation with accessible error announcements.

Examples of Proper Implementation

Button with Proper Accessibility

<button
  type="button"
  aria-label="Close navigation menu"
  aria-expanded={isOpen}
  aria-controls="navigation-menu"
  className="focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 focus:outline-none"
  onClick={handleClose}
>
  <X aria-hidden="true" />
</button>
<nav role="navigation" aria-label="Course navigation">
  <ul role="menubar">
    <li role="none">
      <Link
        role="menuitem"
        href="/learn/course/intro"
        className="focus:ring-2 focus:ring-blue-500 focus:outline-none"
        aria-current={isActive ? "page" : undefined}
      >
        Introduction
      </Link>
    </li>
  </ul>
</nav>
const modalRef = useFocusTrap(isOpen);

<div
  ref={modalRef}
  role="dialog"
  aria-labelledby="modal-title"
  aria-modal="true"
  aria-hidden={!isOpen}
>
  <h2 id="modal-title">Modal Title</h2>
  {/* Modal content */}
</div>;