Files
maternal-app/docs/implementation-docs/ACCESSIBILITY_IMPLEMENTATION_PLAN.md
Andrei e2ca04c98f
Some checks failed
CI/CD Pipeline / Lint and Test (push) Has been cancelled
CI/CD Pipeline / E2E Tests (push) Has been cancelled
CI/CD Pipeline / Build Application (push) Has been cancelled
feat: Setup PM2 production deployment and fix compilation issues
- Add PM2 ecosystem configuration for production deployment
- Fix database SSL configuration to support local PostgreSQL
- Create missing AI feedback entity with FeedbackRating enum
- Add roles decorator and guard for RBAC support
- Implement missing AI safety methods (sanitizeInput, performComprehensiveSafetyCheck)
- Add getSystemPrompt method to multi-language service
- Fix TypeScript errors in personalization service
- Install missing dependencies (@nestjs/terminus, mongodb, minio)
- Configure Next.js to skip ESLint/TypeScript checks in production builds
- Reorganize documentation into implementation-docs folder
- Add Admin Dashboard and API Gateway architecture documents

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-03 23:15:04 +00:00

19 KiB

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
  2. WCAG 2.1 AA Requirements
  3. Current State Assessment
  4. Implementation Phases
  5. Technical Requirements
  6. Testing Strategy
  7. Success Metrics

Why Accessibility Matters

  • 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)

    @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

# 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:

{
  "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:

'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:

/* 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:

/**
 * 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)

npm run lint  # Check for accessibility violations

jest-axe (Unit Tests)

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)

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

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)

  1. Keyboard navigation for all pages
  2. Focus management for modals
  3. Form labels and error messages
  4. Heading hierarchy fixes

Days 4-5 (High Priority)

  1. Alt text for all images
  2. Color contrast fixes
  3. Live regions for dynamic content
  4. Automated tests (jest-axe)

Week 2 (Testing & Polish)

  1. Screen reader testing
  2. Manual keyboard testing
  3. Reduced motion support
  4. 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

Documentation

Screen Readers


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