# Accessibility Guide **Build inclusive, accessible interfaces** that work for everyone. Learn WCAG AA standards, keyboard navigation, screen reader support, and testing strategies. --- ## Table of Contents 1. [Accessibility Standards](#accessibility-standards) 2. [Color Contrast](#color-contrast) 3. [Keyboard Navigation](#keyboard-navigation) 4. [Screen Reader Support](#screen-reader-support) 5. [ARIA Attributes](#aria-attributes) 6. [Focus Management](#focus-management) 7. [Testing](#testing) 8. [Accessibility Checklist](#accessibility-checklist) --- ## Accessibility Standards ### WCAG 2.1 Level AA We follow **WCAG 2.1 Level AA** as the **minimum** standard. **Why Level AA?** - ✅ Required for most legal compliance (ADA, Section 508) - ✅ Covers 95%+ of accessibility needs - ✅ Achievable without major UX compromises - ✅ Industry standard for modern web apps **WCAG Principles (POUR):** 1. **Perceivable** - Information can be perceived by users 2. **Operable** - Interface can be operated by users 3. **Understandable** - Information and operation are understandable 4. **Robust** - Content works with current and future technologies --- ### Accessibility Decision Tree ``` Creating a UI element? │ ├─ Is it interactive? │ ├─YES─> Can it be focused with Tab? │ │ ├─YES─> ✅ Good │ │ └─NO──> ❌ Add tabIndex or use button/link │ │ │ └─NO──> Is it important information? │ ├─YES─> Does it have appropriate semantic markup? │ │ ├─YES─> ✅ Good │ │ └─NO──> ❌ Use h1-h6, p, ul, etc. │ │ │ └─NO──> Is it purely decorative? │ ├─YES─> Add aria-hidden="true" │ └─NO──> Add alt text or ARIA label ``` --- ## Color Contrast ### Minimum Contrast Ratios (WCAG AA) | Content Type | Minimum Ratio | Example | | -------------------------------------- | ------------- | ---------------------------- | | **Normal text** (< 18px) | **4.5:1** | Body paragraphs, form labels | | **Large text** (≥ 18px or ≥ 14px bold) | **3:1** | Headings, subheadings | | **UI components** | **3:1** | Buttons, form borders, icons | | **Graphical objects** | **3:1** | Chart elements, infographics | **WCAG AAA (ideal, not required):** - Normal text: 7:1 - Large text: 4.5:1 --- ### Testing Color Contrast **Tools:** - [WebAIM Contrast Checker](https://webaim.org/resources/contrastchecker/) - Chrome DevTools: Inspect element → Accessibility panel - [Contrast Ratio Tool](https://contrast-ratio.com) - Browser extensions: axe DevTools, WAVE **Example:** ```tsx // ✅ GOOD - 4.7:1 contrast (WCAG AA pass)

// oklch(0.1529 0 0) on white Body text

// ❌ BAD - 2.1:1 contrast (WCAG AA fail)

// Too light Body text

// ✅ GOOD - Using semantic tokens ensures contrast

Secondary text

``` **Our design system tokens are WCAG AA compliant:** - `text-foreground` on `bg-background`: 12.6:1 ✅ - `text-primary-foreground` on `bg-primary`: 8.2:1 ✅ - `text-destructive` on `bg-background`: 5.1:1 ✅ - `text-muted-foreground` on `bg-background`: 4.6:1 ✅ --- ### Color Blindness **8% of men and 0.5% of women** have some form of color blindness. **Best practices:** - ❌ Don't rely on color alone to convey information - ✅ Use icons, text labels, or patterns in addition to color - ✅ Test with color blindness simulators **Example:** ```tsx // ❌ BAD - Color only
Success
Error
// ✅ GOOD - Color + icon + text Success Operation completed Error Something went wrong ``` --- ## Keyboard Navigation ### Core Requirements All interactive elements must be: 1. ✅ **Focusable** - Can be reached with Tab key 2. ✅ **Activatable** - Can be triggered with Enter or Space 3. ✅ **Navigable** - Can move between with arrow keys (where appropriate) 4. ✅ **Escapable** - Can be closed/exited with Escape key --- ### Tab Order **Natural tab order** follows DOM order (top to bottom, left to right). ```tsx // ✅ GOOD - Natural tab order
{/* Tab 1 */} {/* Tab 2 */} {/* Tab 3 */}
// ❌ BAD - Using tabIndex to force order
// Don't do this
``` **When to use `tabIndex`:** - `tabIndex={0}` - Make non-interactive element focusable - `tabIndex={-1}` - Remove from tab order (for programmatic focus) - `tabIndex={1+}` - ❌ **Avoid** - Breaks natural order --- ### Keyboard Shortcuts | Key | Action | Example | | --------------- | ------------------------- | ----------------------------- | | **Tab** | Move focus forward | Navigate through form fields | | **Shift + Tab** | Move focus backward | Go back to previous field | | **Enter** | Activate button/link | Submit form, follow link | | **Space** | Activate button/checkbox | Toggle checkbox, click button | | **Escape** | Close overlay | Close dialog, dropdown | | **Arrow keys** | Navigate within component | Navigate dropdown items | | **Home** | Jump to start | First item in list | | **End** | Jump to end | Last item in list | --- ### Implementing Keyboard Navigation **Button (automatic):** ```tsx // ✅ Button is keyboard accessible by default // Enter or Space triggers onClick ``` **Custom clickable div (needs work):** ```tsx // ❌ BAD - Not keyboard accessible
Click me
// ✅ GOOD - Make it accessible
{ if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); handleClick(); } }} > Click me
// ✅ BETTER - Just use a button ``` **Dropdown navigation:** ```tsx Edit {/* Arrow down */} Delete {/* Arrow down */} // shadcn/ui handles arrow key navigation automatically ``` --- ### Skip Links **Allow keyboard users to skip navigation:** ```tsx // Add to layout Skip to main content
{/* Main content */}
``` --- ## Screen Reader Support ### Screen Reader Basics **Popular screen readers:** - **NVDA** (Windows) - Free, most popular for testing - **JAWS** (Windows) - Industry standard, paid - **VoiceOver** (macOS/iOS) - Built-in to Apple devices - **TalkBack** (Android) - Built-in to Android **What screen readers announce:** - Semantic element type (button, link, heading, etc.) - Element text content - Element state (expanded, selected, disabled) - ARIA labels and descriptions --- ### Semantic HTML **Use the right HTML element for the job:** ```tsx // ✅ GOOD - Semantic HTML

Page Title

Content...

// ❌ BAD - Div soup
Home
About
Page Title
Content...
``` **Semantic elements:** - `
` - Page header - `