Skip to content

[A11Y] [Medium] Dynamic content updates not announced to screen readers #7

@continue

Description

@continue

Accessibility Issue: Dynamic Content Without ARIA Live Regions

WCAG Level: A
Severity: Medium
Category: Dynamic Content (WCAG 4.1.3)

Issue Description

Several areas of the application update dynamically (sync status, loading states, success/error messages, recommendations) without using ARIA live regions to announce changes to screen reader users.

User Impact

  • Affected Users: Screen reader users
  • Severity: Medium - users miss important status updates and feedback

Violations Found

File: src/pages/Settings.tsx

Lines: 145-156

<!-- Current Code -->
{message && (
  <div className="card" style={{ background: 'var(--color-success-dim)', ... }}>
    <span style={{ color: 'var(--color-success)', fontWeight: 600 }}>{message}</span>
  </div>
)}
{error && (
  <div className="card" style={{ background: 'var(--color-error-dim)', ... }}>
    <span style={{ color: 'var(--color-error)', fontWeight: 600 }}>Error:</span> {error}
  </div>
)}

Issue: Success and error messages appear but are not announced to screen readers.

File: src/pages/Activities.tsx

Lines: 92-97

<!-- Current Code (loading state) -->
{loading ? (
  <div className="card" style={{ textAlign: 'center', padding: '2rem' }}>
    <div></div>
    <p style={{ color: 'var(--text-muted)', margin: 0 }}>Loading your victories…</p>
  </div>
) : ( ... )}

Issue: Loading state not announced; completion not announced.

File: src/components/AdaptiveRecommendations.tsx

Lines: 254-274

<!-- Current Code -->
{analyzing && (
  <span style={{ fontSize: '0.78rem', color: 'var(--text-muted)' }}>Analyzing…</span>
)}

Issue: Analysis status not announced.


Recommended Fix

<!-- Fixed Code - Settings.tsx -->
{message && (
  <div 
    className="card" 
    role="status" 
    aria-live="polite"
    style={{ background: 'var(--color-success-dim)', ... }}
  >
    <span style={{ color: 'var(--color-success)', fontWeight: 600 }}>{message}</span>
  </div>
)}
{error && (
  <div 
    className="card" 
    role="alert" 
    aria-live="assertive"
    style={{ background: 'var(--color-error-dim)', ... }}
  >
    <span style={{ color: 'var(--color-error)', fontWeight: 600 }}>Error:</span> {error}
  </div>
)}

<!-- Fixed Code - Loading states -->
<div 
  className="card" 
  role="status" 
  aria-live="polite"
  aria-busy={loading}
  style={{ textAlign: 'center', padding: '2rem' }}
>
  {loading ? (
    <>
      <div aria-hidden="true"></div>
      <p style={{ color: 'var(--text-muted)', margin: 0 }}>Loading your activities…</p>
    </>
  ) : (
    <p style={{ color: 'var(--text-muted)', margin: 0 }}>
      {activities.length} activities loaded
    </p>
  )}
</div>

Changes Made:

  1. Add role="status" and aria-live="polite" for non-critical updates
  2. Add role="alert" and aria-live="assertive" for errors
  3. Add aria-busy attribute for loading states
  4. Announce completion states, not just loading

Additional Instances

  • src/pages/Dashboard.tsx - Sync results, daily recap appearance
  • src/pages/Training.tsx - Sync status messages
  • src/components/LoadingScreen.tsx - Loading spinner
  • src/pages/Analytics.tsx - Data loading states
  • src/pages/Insights.tsx - Score updates

Testing Instructions

  1. Use screen reader to navigate application
  2. Trigger actions that show messages (save settings, sync)
  3. Verify success/error messages are announced
  4. Verify loading states announce start and completion
  5. Test with NVDA/VoiceOver in different modes

Resources

Acceptance Criteria

  • Success messages use role="status" with aria-live="polite"
  • Error messages use role="alert" with aria-live="assertive"
  • Loading states use aria-busy attribute
  • Screen reader announces message content when it appears
  • Tested with NVDA and VoiceOver

Metadata

Metadata

Assignees

No one assigned

    Labels

    accessibilityAccessibility improvementsseverity-mediumMedium severity - notable impactwcag-aWCAG Level A compliance

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions