Skip to content

fix(a11y): single status announcer on activity and templates - #1862

Merged
greatest0fallt1me merged 2 commits into
Streampay-Org:mainfrom
p70436464-prog:fix/a11y-live-region-noise
Oct 24, 2026
Merged

greatest0fallt1me merged 2 commits into
Streampay-Org:mainfrom
p70436464-prog:fix/a11y-live-region-noise

Conversation

@p70436464-prog

Copy link
Copy Markdown
Contributor

Closes #1685

Summary

Resolves noisy, duplicated screen reader speech on /activity and /templates caused by marking content containers with aria-live="polite" and duplicate role="status" regions. Content containers now retain aria-busy while dropping aria-live, and both pages use a single, consolidated LiveRegion component for concise status announcements.

VoiceOver / NVDA Transcript

Before:

  • Activity page load:
    • VoiceOver: "Activity feed, region, polite. Track every event. Activity feed. Payments, stream lifecycle changes... Today... New stream created for Project Alpha... Deleted stream activity..." (re-announces entire container and timeline rows on data load).
  • Templates page search:
    • VoiceOver: "Showing 4 templates, region. Showing 3 templates. Showing 2 templates..." (announces repeatedly on every keystroke, plus duplicated role="status" announcements from both shell and panel).

After:

  • Activity page load:
    • VoiceOver: "Loaded 2 events" (single polite status message; content container does not re-read).
    • Error state: "Unable to connect to server" (assertive alert).
  • Templates page search:
    • VoiceOver: "Showing 2 templates" (single polite announcement 500ms after user finishes typing).
    • Grid region: "Template results, region" (static label constant across searches).

Changes

  • Consolidated LiveRegion: Single canonical implementation in app/components/LiveRegion.tsx (supporting deduplication and assertive role="alert" per ARIA19 / WCAG 2.1 AA) re-exported from src/components/LiveRegion.tsx.
  • Activity page (app/activity/page.tsx):
    • Removed aria-live="polite" from the <section> element while maintaining aria-busy.
    • Added single LiveRegion announcing loading start ("Loading activity…"), success with count ("Loaded N events"), empty ("No activity to display."), and assertive error announcements.
  • Templates page (app/templates/page.tsx):
    • Removed aria-live="polite" from the <section> container and removed duplicate role="status" elements.
    • Set static aria-label="Template results" on the results region.
    • Added single LiveRegion debouncing search announcements to 500ms after typing stops.
  • Testing:
    • Extended app/activity/page.test.tsx and app/templates/page.test.tsx covering all 7 issue scenarios and jest-axe audits with no violations across all states.

Test Output

@greatest0fallt1me
greatest0fallt1me merged commit 4fe8a99 into Streampay-Org:main Oct 24, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Make /activity and /templates announce state changes once instead of re-reading whole regions

2 participants