# Accessibility (a11y) Best Practices Complete guide for building accessible forms. --- ## WCAG Compliance ### Required Elements 1. **Labels** - Every input must have a label 2. **Error Messages** - Must be accessible to screen readers 3. **Focus Management** - Errors should be announced 4. **Keyboard Navigation** - Full keyboard support --- ## ARIA Attributes ### Essential ARIA ```typescript We'll never share your email {errors.email && ( {errors.email.message} )} ``` ### Live Regions for Error Announcements ```typescript {Object.keys(errors).length > 0 && (
Form has {Object.keys(errors).length} errors. Please review.
)} ``` --- ## Focus Management ### Focus First Error ```typescript import { useEffect, useRef } from 'react' const firstErrorRef = useRef(null) useEffect(() => { if (Object.keys(errors).length > 0) { firstErrorRef.current?.focus() } }, [errors]) // In JSX ``` ### Using setFocus ```typescript const onSubmit = async (data) => { try { await submitData(data) } catch (error) { setFocus('email') // Focus field programmatically } } ``` --- ## Label Association ### Explicit Labels ```typescript ``` ### aria-label (When Visual Label Not Possible) ```typescript ``` ### aria-labelledby (Multiple Labels) ```typescript

Billing Address

Street ``` --- ## Required Fields ### Visual Indicator ```typescript ``` ### Legend for Required Fields ```typescript

* Required field

``` --- ## Error Messaging ### Accessible Error Pattern ```typescript
Must be at least 8 characters {errors.password && ( {errors.password.message} )}
``` --- ## Fieldsets and Legends ### Grouping Related Fields ```typescript
Contact Information
``` ### Radio Groups ```typescript
Choose your plan
``` --- ## Keyboard Navigation ### Tab Order ```typescript // Ensure logical tab order with tabindex (use sparingly) ``` ### Skip Links ```typescript Skip to form
{/* ... */}
``` --- ## Button Accessibility ### Submit Button States ```typescript ``` ### Icon Buttons ```typescript ``` --- ## Screen Reader Announcements ### Status Messages ```typescript {isSubmitSuccessful && (
Form submitted successfully!
)} ``` ### Loading States ```typescript {isSubmitting && (
Submitting form, please wait...
)} ``` --- ## Color Contrast ### WCAG AA Standards - Normal text: 4.5:1 minimum - Large text: 3:1 minimum - UI components: 3:1 minimum ```css /* Good contrast examples */ .error { color: #c41e3a; /* Red */ background: #ffffff; /* White */ /* Contrast ratio: 5.77:1 ✓ */ } .button { color: #ffffff; background: #0066cc; /* Contrast ratio: 7.33:1 ✓ */ } ``` --- ## Testing ### Automated Testing Tools - **axe DevTools** - Browser extension - **Lighthouse** - Chrome DevTools - **WAVE** - Web accessibility evaluation tool ### Manual Testing 1. **Keyboard Navigation** - Tab through entire form 2. **Screen Reader** - Test with NVDA (Windows) or VoiceOver (Mac) 3. **Zoom** - Test at 200% zoom 4. **High Contrast** - Test in high contrast mode --- ## Accessibility Checklist - [ ] All inputs have associated labels - [ ] Required fields are marked with aria-required - [ ] Error messages use role="alert" - [ ] Errors have aria-describedby linking to error text - [ ] Form has clear heading structure - [ ] Keyboard navigation works completely - [ ] Focus is managed appropriately - [ ] Color is not the only indicator of errors - [ ] Contrast ratios meet WCAG AA standards - [ ] Screen reader testing completed --- **Resources**: - WCAG Guidelines: https://www.w3.org/WAI/WCAG21/quickref/ - React Hook Form a11y: https://react-hook-form.com/advanced-usage#AccessibilityA11y