# 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!** 🌟
