docs: Create comprehensive accessibility implementation plan

Created detailed 2-week plan to achieve WCAG 2.1 AA compliance:

**Plan Overview:**
- 4 phases over 2 weeks
- Phase 1: Foundation (keyboard nav, ARIA, focus management)
- Phase 2: Content & Forms (alt text, contrast, live regions)
- Phase 3: Testing & Polish (automated tests, screen readers)
- Phase 4: Advanced Features (reduced motion, text scaling)

**Key Deliverables:**
- ESLint jsx-a11y configuration
- Axe-core integration for automated testing
- Comprehensive keyboard navigation
- Screen reader compatibility
- WCAG 2.1 AA compliance (100 Lighthouse score)

**Technical Requirements:**
- Install eslint-plugin-jsx-a11y, jest-axe, @axe-core/react
- Focus trap utilities and management
- Accessibility helper functions
- Reduced motion support

**Testing Strategy:**
- Automated: ESLint, jest-axe, Playwright, Lighthouse CI
- Manual: Keyboard nav, screen readers (NVDA, JAWS, VoiceOver)
- Browser matrix for cross-platform testing

**Success Metrics:**
- 100/100 Lighthouse accessibility score
- 0 Axe-core violations
- All user flows keyboard accessible
- Screen reader compatible

**Priority Order:**
- Day 1: ESLint setup, focus indicators, skip link
- Days 2-3: Keyboard nav, focus mgmt, forms, headings
- Days 4-5: Alt text, contrast, live regions, tests
- Week 2: Screen reader testing, documentation, polish

🎯 Goal: Make Maternal App accessible to ALL parents

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-10-02 20:50:16 +00:00
parent ba383f9335
commit 9772ed3349

View File

@@ -0,0 +1,670 @@
# Accessibility Implementation Plan - Maternal App
**Created**: October 2, 2025
**Target**: WCAG 2.1 AA Compliance
**Priority**: CRITICAL (Launch Blocker)
---
## Executive Summary
This document outlines the comprehensive accessibility implementation plan to achieve WCAG 2.1 AA compliance for the Maternal App. Accessibility is a **critical launch requirement** for legal compliance (ADA, Section 508) and to ensure the app is usable by all parents, including those with disabilities.
**Current Status**: No accessibility implementation detected
**Target**: Full WCAG 2.1 AA compliance
**Timeline**: 2 weeks (Phases 1-3)
---
## Table of Contents
1. [Why Accessibility Matters](#why-accessibility-matters)
2. [WCAG 2.1 AA Requirements](#wcag-21-aa-requirements)
3. [Current State Assessment](#current-state-assessment)
4. [Implementation Phases](#implementation-phases)
5. [Technical Requirements](#technical-requirements)
6. [Testing Strategy](#testing-strategy)
7. [Success Metrics](#success-metrics)
---
## Why Accessibility Matters
### Legal Requirements
- **ADA (Americans with Disabilities Act)**: Web accessibility is legally required
- **Section 508**: Federal compliance for government users
- **WCAG 2.1 AA**: International standard for web accessibility
### User Impact
- **15% of the population** has some form of disability
- **New parents** may have temporary disabilities (sleep deprivation, holding baby)
- **Situational disabilities**: Using app in bright sunlight, noisy environments
- **Assistive technology users**: Screen readers, keyboard-only, voice control
### Business Benefits
- Larger addressable market
- Better SEO (semantic HTML)
- Improved UX for all users
- Legal risk mitigation
- Positive brand reputation
---
## WCAG 2.1 AA Requirements
### Four Core Principles (POUR)
#### 1. **Perceivable**
- Text alternatives for non-text content
- Captions and alternatives for multimedia
- Adaptable content (can be presented in different ways)
- Distinguishable (easy to see and hear)
#### 2. **Operable**
- Keyboard accessible (all functionality available via keyboard)
- Sufficient time (users have enough time to read and use content)
- Seizures and physical reactions (nothing that causes seizures)
- Navigable (users can navigate, find content, and determine where they are)
- Input modalities (make it easier to operate functionality through various inputs)
#### 3. **Understandable**
- Readable (text content is readable and understandable)
- Predictable (web pages appear and operate in predictable ways)
- Input assistance (help users avoid and correct mistakes)
#### 4. **Robust**
- Compatible (maximize compatibility with current and future user agents)
---
## Current State Assessment
### What We Have ✅
- **Material-UI (MUI)**: Built-in accessibility features
- **React 18**: Modern framework with good accessibility support
- **Semantic HTML**: Some usage of proper HTML5 elements
- **Next.js 13**: Server-side rendering for better screen reader support
### What's Missing ❌
#### **Critical Issues**
1. ❌ No ARIA labels on interactive elements
2. ❌ No keyboard navigation support
3. ❌ No focus indicators
4. ❌ No screen reader testing
5. ❌ Missing alt text on images/icons
6. ❌ Poor color contrast (not verified)
7. ❌ No skip navigation links
8. ❌ Forms lack proper labels and error messages
9. ❌ No focus management for dialogs/modals
10. ❌ No reduced motion support
#### **High Priority Issues**
- Missing landmark regions (header, nav, main, footer)
- No heading hierarchy verification
- Missing aria-live regions for dynamic content
- No keyboard shortcuts documentation
- Touch targets not verified (44x44px minimum)
---
## Implementation Phases
### **Phase 1: Foundation (Week 1, Days 1-3)** 🏗️
#### **Goal**: Establish accessibility infrastructure and fix critical keyboard/focus issues
**Tasks:**
1. **Setup Accessibility Tools** (Day 1 Morning)
- Install `eslint-plugin-jsx-a11y` (React accessibility linting)
- Install `axe-core` and `@axe-core/react` (runtime accessibility testing)
- Configure ESLint rules for accessibility
- Install `jest-axe` for automated testing
- Add accessibility check to CI/CD
2. **Keyboard Navigation** (Day 1 Afternoon - Day 2)
- Implement focus trap for modals/dialogs
- Add visible focus indicators (outline/ring)
- Create skip navigation link
- Fix tab order across all pages
- Add keyboard shortcuts for common actions
- Document keyboard navigation patterns
3. **ARIA Labels & Semantic HTML** (Day 2 - Day 3)
- Audit all interactive elements (buttons, links, inputs)
- Add aria-label/aria-labelledby where needed
- Fix heading hierarchy (h1 → h2 → h3)
- Add landmark regions (header, nav, main, footer)
- Convert icon-only buttons to have text alternatives
- Add aria-describedby for form hints
4. **Focus Management** (Day 3)
- Implement focus management for route changes
- Focus first heading on page load
- Trap focus in modals/dialogs
- Return focus when closing modals
- Manage focus for toast notifications
**Deliverables:**
- ESLint accessibility rules configured
- Axe-core integrated into dev environment
- All pages keyboard navigable
- Focus indicators visible
- Skip navigation link added
---
### **Phase 2: Content & Forms (Week 1, Days 4-5)** 📝
#### **Goal**: Make all content accessible and improve form usability
**Tasks:**
1. **Alternative Text** (Day 4 Morning)
- Audit all images for alt text
- Add descriptive alt text to photos
- Mark decorative images as `alt=""`
- Add aria-label to icon buttons
- Document icon meanings
2. **Form Accessibility** (Day 4 Afternoon - Day 5 Morning)
- Add explicit labels to all inputs
- Associate labels with inputs (htmlFor/id)
- Add aria-required to required fields
- Improve error messages with aria-invalid
- Add aria-describedby for help text
- Group related inputs with fieldset/legend
- Add autocomplete attributes
3. **Color Contrast** (Day 5 Morning)
- Audit color contrast ratios (WCAG AA: 4.5:1 for text, 3:1 for large text)
- Fix low-contrast text
- Ensure error states don't rely on color alone
- Add patterns/icons to supplement color coding
4. **Live Regions** (Day 5 Afternoon)
- Add aria-live to toast notifications
- Add aria-live to loading states
- Add aria-live to activity feed updates
- Add status messages for async operations
**Deliverables:**
- All images have appropriate alt text
- All forms fully accessible
- Color contrast meets WCAG AA
- Live regions for dynamic content
---
### **Phase 3: Testing & Polish (Week 2, Days 1-3)** ✅
#### **Goal**: Comprehensive testing and documentation
**Tasks:**
1. **Automated Testing** (Day 1)
- Write jest-axe tests for all pages
- Add axe-core checks to E2E tests
- Run Lighthouse accessibility audits
- Fix all automated test failures
- Add accessibility tests to CI/CD
2. **Screen Reader Testing** (Day 2)
- Test with NVDA (Windows)
- Test with JAWS (Windows)
- Test with VoiceOver (macOS/iOS)
- Test with TalkBack (Android)
- Document screen reader issues
- Fix critical screen reader bugs
3. **Manual Testing** (Day 2-3)
- Test all pages with keyboard only (no mouse)
- Test with browser zoom (up to 200%)
- Test with high contrast mode
- Test with reduced motion
- Test with different viewport sizes
- Test all user flows
4. **Documentation** (Day 3)
- Create accessibility statement page
- Document keyboard shortcuts
- Add ARIA patterns guide for developers
- Create accessibility testing checklist
- Document known issues (if any)
**Deliverables:**
- Automated accessibility tests passing
- Screen reader testing complete
- Manual testing checklist complete
- Accessibility documentation published
---
### **Phase 4: Advanced Features (Week 2, Days 4-5)** 🚀
#### **Goal**: Enhanced accessibility features
**Tasks:**
1. **Reduced Motion Support** (Day 4 Morning)
```css
@media (prefers-reduced-motion: reduce) {
* {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}
```
- Detect `prefers-reduced-motion`
- Disable animations for users who prefer reduced motion
- Keep essential motion (loading indicators)
2. **Text Scaling** (Day 4 Afternoon)
- Test with browser text zoom up to 200%
- Use relative units (rem, em) instead of px
- Ensure layout doesn't break at 200% zoom
- Test with browser zoom (page zoom)
3. **Touch Target Sizes** (Day 5 Morning)
- Audit all interactive elements
- Ensure minimum 44x44px (iOS) / 48x48dp (Android)
- Add padding to small targets
- Increase spacing between adjacent targets
4. **Additional Enhancements** (Day 5 Afternoon)
- Add high contrast mode support
- Add visual focus indicators for mouse users
- Implement focus-within for nested focus
- Add aria-current for navigation
**Deliverables:**
- Reduced motion support implemented
- Text scaling verified up to 200%
- Touch targets meet minimum sizes
- Enhanced accessibility features live
---
## Technical Requirements
### **1. Dependencies to Install**
```bash
# Linting and Testing
npm install --save-dev eslint-plugin-jsx-a11y
npm install --save-dev jest-axe
npm install --save-dev @axe-core/react
# Runtime Testing
npm install --save @axe-core/react
# Focus Management
npm install react-focus-lock focus-trap-react
# Reduced Motion Hook
npm install framer-motion # Already installed, use useReducedMotion
```
### **2. ESLint Configuration**
Add to `.eslintrc.json`:
```json
{
"extends": [
"plugin:jsx-a11y/recommended"
],
"plugins": ["jsx-a11y"],
"rules": {
"jsx-a11y/anchor-is-valid": "error",
"jsx-a11y/aria-props": "error",
"jsx-a11y/aria-proptypes": "error",
"jsx-a11y/aria-unsupported-elements": "error",
"jsx-a11y/heading-has-content": "error",
"jsx-a11y/img-redundant-alt": "error",
"jsx-a11y/label-has-associated-control": "error",
"jsx-a11y/no-autofocus": "warn",
"jsx-a11y/no-static-element-interactions": "error"
}
}
```
### **3. Axe-Core Integration (Development)**
Create `components/providers/AxeProvider.tsx`:
```typescript
'use client';
import React, { useEffect } from 'react';
export function AxeProvider({ children }: { children: React.ReactNode }) {
useEffect(() => {
if (process.env.NODE_ENV === 'development') {
import('@axe-core/react').then((axe) => {
axe.default(React, require('react-dom'), 1000);
});
}
}, []);
return <>{children}</>;
}
```
### **4. Focus Visible Styles**
Add to `globals.css`:
```css
/* Focus indicators */
*:focus {
outline: 2px solid #FF8B7D; /* Coral from design system */
outline-offset: 2px;
}
/* Focus visible (keyboard only) */
*:focus:not(:focus-visible) {
outline: none;
}
*:focus-visible {
outline: 2px solid #FF8B7D;
outline-offset: 2px;
}
/* Skip link */
.skip-link {
position: absolute;
top: -40px;
left: 0;
background: #000;
color: white;
padding: 8px;
text-decoration: none;
z-index: 100;
}
.skip-link:focus {
top: 0;
}
```
### **5. Accessibility Utilities**
Create `lib/accessibility.ts`:
```typescript
/**
* Accessibility utility functions
*/
// Announce to screen readers
export function announceToScreenReader(message: string, priority: 'polite' | 'assertive' = 'polite') {
const announcement = document.createElement('div');
announcement.setAttribute('role', 'status');
announcement.setAttribute('aria-live', priority);
announcement.setAttribute('aria-atomic', 'true');
announcement.className = 'sr-only';
announcement.textContent = message;
document.body.appendChild(announcement);
setTimeout(() => {
document.body.removeChild(announcement);
}, 1000);
}
// Check if reduced motion is preferred
export function prefersReducedMotion(): boolean {
return window.matchMedia('(prefers-reduced-motion: reduce)').matches;
}
// Get contrast ratio between two colors
export function getContrastRatio(color1: string, color2: string): number {
// Implementation using relative luminance formula
// WCAG requires 4.5:1 for normal text, 3:1 for large text
}
// Trap focus within an element
export function trapFocus(element: HTMLElement) {
const focusableElements = element.querySelectorAll(
'a[href], button, textarea, input, select, [tabindex]:not([tabindex="-1"])'
);
const firstElement = focusableElements[0] as HTMLElement;
const lastElement = focusableElements[focusableElements.length - 1] as HTMLElement;
element.addEventListener('keydown', (e) => {
if (e.key === 'Tab') {
if (e.shiftKey && document.activeElement === firstElement) {
e.preventDefault();
lastElement.focus();
} else if (!e.shiftKey && document.activeElement === lastElement) {
e.preventDefault();
firstElement.focus();
}
}
});
}
```
---
## Testing Strategy
### **1. Automated Testing**
#### **ESLint (Static Analysis)**
```bash
npm run lint # Check for accessibility violations
```
#### **jest-axe (Unit Tests)**
```typescript
import { render } from '@testing-library/react';
import { axe, toHaveNoViolations } from 'jest-axe';
expect.extend(toHaveNoViolations);
test('Dashboard should be accessible', async () => {
const { container } = render(<Dashboard />);
const results = await axe(container);
expect(results).toHaveNoViolations();
});
```
#### **Playwright (E2E Tests)**
```typescript
test('should pass accessibility audit', async ({ page }) => {
await page.goto('/dashboard');
const accessibilityScanResults = await page.evaluate(async () => {
const axe = await import('axe-core');
return await axe.run();
});
expect(accessibilityScanResults.violations).toEqual([]);
});
```
#### **Lighthouse CI**
```bash
npm install --save-dev @lhci/cli
lhci autorun --collect.url=http://localhost:3000 --assert.preset=lighthouse:accessibility
```
### **2. Manual Testing Checklist**
#### **Keyboard Navigation**
- [ ] All interactive elements are keyboard accessible
- [ ] Tab order is logical
- [ ] Focus indicators are visible
- [ ] Skip navigation link works
- [ ] No keyboard traps
- [ ] Escape key closes modals
- [ ] Enter/Space activate buttons
#### **Screen Reader Testing**
- [ ] Page title is announced
- [ ] Headings are in logical order
- [ ] Form labels are announced
- [ ] Error messages are announced
- [ ] Status updates are announced
- [ ] Images have alt text
- [ ] Links have descriptive text
#### **Visual Testing**
- [ ] Color contrast meets 4.5:1 (normal text)
- [ ] Color contrast meets 3:1 (large text, 18pt+)
- [ ] Content readable at 200% zoom
- [ ] No horizontal scrolling at 320px width
- [ ] Touch targets are 44x44px minimum
#### **Assistive Technology**
- [ ] Works with NVDA (Windows)
- [ ] Works with JAWS (Windows)
- [ ] Works with VoiceOver (Mac/iOS)
- [ ] Works with TalkBack (Android)
- [ ] Works with Dragon NaturallySpeaking (voice control)
- [ ] Works with browser zoom
### **3. Browser Testing Matrix**
| Browser | Screen Reader | Platform | Status |
|---------|---------------|----------|--------|
| Chrome | NVDA | Windows | TODO |
| Firefox | NVDA | Windows | TODO |
| Edge | JAWS | Windows | TODO |
| Safari | VoiceOver | macOS | TODO |
| Safari | VoiceOver | iOS | TODO |
| Chrome | TalkBack | Android | TODO |
---
## Success Metrics
### **Quantitative Metrics**
1. **Lighthouse Accessibility Score**: 100/100 ✅
2. **Axe-core Violations**: 0 critical, 0 serious ✅
3. **ESLint jsx-a11y Errors**: 0 ✅
4. **Color Contrast**: 100% WCAG AA compliant ✅
5. **Keyboard Navigation**: 100% of features accessible ✅
### **Qualitative Metrics**
1. **Screen Reader Testing**: All critical user flows pass ✅
2. **User Testing**: Test with 3-5 users with disabilities ✅
3. **WCAG 2.1 AA Audit**: External audit (optional but recommended) ✅
### **Key User Flows to Test**
1.**Sign Up / Log In**
- Keyboard accessible
- Error messages announced
- Form labels clear
2.**Add Activity (Feeding/Sleep/Diaper)**
- Voice input accessible
- Form fully keyboard accessible
- Success message announced
3.**View Dashboard**
- Stats cards readable
- Charts have text alternatives
- Navigation clear
4.**AI Assistant Chat**
- Chat input keyboard accessible
- Responses announced to screen reader
- Conversation history navigable
5.**Settings & Account**
- All settings keyboard accessible
- Toggle buttons have clear states
- Dialogs trap focus properly
---
## Priority Order (Critical Path)
### **Day 1 (Must Have)**
1. ESLint jsx-a11y setup
2. Visible focus indicators
3. Skip navigation link
4. Basic ARIA labels on buttons/links
### **Days 2-3 (Critical)**
5. Keyboard navigation for all pages
6. Focus management for modals
7. Form labels and error messages
8. Heading hierarchy fixes
### **Days 4-5 (High Priority)**
9. Alt text for all images
10. Color contrast fixes
11. Live regions for dynamic content
12. Automated tests (jest-axe)
### **Week 2 (Testing & Polish)**
13. Screen reader testing
14. Manual keyboard testing
15. Reduced motion support
16. Documentation
---
## Risk Mitigation
### **Potential Risks**
1. **Risk**: Breaking existing functionality
- **Mitigation**: Comprehensive testing after each change
2. **Risk**: Time overrun
- **Mitigation**: Focus on critical items first (Days 1-3)
3. **Risk**: Lack of screen reader expertise
- **Mitigation**: Use automated tools, watch video tutorials, hire consultant
4. **Risk**: Design conflicts (e.g., focus indicators affect design)
- **Mitigation**: Work with design to create accessible alternatives
---
## Resources
### **Tools**
- [Axe DevTools Browser Extension](https://www.deque.com/axe/devtools/)
- [WAVE Browser Extension](https://wave.webaim.org/extension/)
- [Color Contrast Analyzer](https://www.tpgi.com/color-contrast-checker/)
- [Lighthouse](https://developers.google.com/web/tools/lighthouse)
### **Documentation**
- [WCAG 2.1 Guidelines](https://www.w3.org/WAI/WCAG21/quickref/)
- [MDN Accessibility](https://developer.mozilla.org/en-US/docs/Web/Accessibility)
- [A11y Project Checklist](https://www.a11yproject.com/checklist/)
- [ARIA Authoring Practices](https://www.w3.org/WAI/ARIA/apg/)
### **Screen Readers**
- [NVDA (Free, Windows)](https://www.nvaccess.org/)
- [JAWS (Trial, Windows)](https://www.freedomscientific.com/products/software/jaws/)
- VoiceOver (Built-in, macOS/iOS)
- TalkBack (Built-in, Android)
---
## Next Steps
1.**Review and approve this plan**
2. 🔄 **Start Phase 1, Day 1**: Install accessibility tools
3. 🔄 **Daily standups**: Review progress, adjust as needed
4. 🔄 **Test continuously**: Don't wait until the end
---
**Document Owner**: Development Team
**Stakeholders**: Product, Design, QA, Legal
**Review Cadence**: Daily during implementation, weekly post-launch
**Let's make the Maternal App accessible to ALL parents!** 🌟