Live Region Announcer
Component Detail
Description
Provides live-region announcements for asynchronous state changes such as loading completions, form submission results, error messages, and background data refreshes. Wraps Flutter's SemanticsService.announce() with queuing and priority management so announcements do not overlap.
live-region-announcer
Summaries
Dynamic, data-driven applications constantly change state — loading indicators resolve, forms submit, errors appear — and users who rely on screen readers are completely unaware of these changes unless the app explicitly announces them. The Live Region Announcer solves this problem by ensuring every meaningful asynchronous event is communicated to the user without disrupting their current interaction. This directly improves task completion rates for screen reader users, reducing frustration and support contacts. For regulated industries, the ability to audit and demonstrate that all state changes are properly communicated to users with disabilities is a compliance asset.
The component's shared, reusable design means the investment is spread across the entire application, making it highly cost-efficient relative to the accessibility coverage it provides.
The Live Region Announcer is a shared service-layer component with a single dependency (`screen-reader-detection-service`) and medium complexity, making it one of the more straightforward accessibility components to schedule and deliver. It should be prioritized early because `accessible-bottom-navigation` and `accessible-modal-sheet` both depend on it — delays here cascade to those higher-complexity components. The core implementation (queue, priority management, locale support) can be completed within one sprint by a developer familiar with Flutter's `SemanticsService`. Testing requires real device verification with VoiceOver and TalkBack because Flutter's semantic test harness does not fully simulate announcement queueing behavior.
The main delivery risk is edge cases around rapid state transitions (e.g., multiple network calls completing simultaneously) causing announcement pile-up, which requires careful integration testing across data-heavy screens.
Live Region Announcer wraps `SemanticsService.announce(message, textDirection)` with a priority queue implemented as a `StreamController`-backed queue. Messages are typed as `AnnouncementPriority.polite` or `AnnouncementPriority.assertive`, mirroring ARIA live region semantics. `announcePolite()` enqueues at the tail; `announceAssertive()` clears the queue and inserts at the head before dispatching immediately. A `Timer`-based debounce (default 300ms) prevents overlapping announcements for polite messages.
`setLocale(locale)` propagates the locale to `SemanticsService` for correct text direction. `clearQueue()` cancels pending polite timers and is called by navigation event handlers to prevent stale messages from firing after context changes. The dependency on `screen-reader-detection-service` allows the queue to no-op entirely when no assistive technology is active, avoiding unnecessary overhead. Integration points include all async data-fetching widgets, form submission handlers, and error boundary components across the application.
Responsibilities
- Queue and dispatch polite and assertive announcements to the screen reader
- Announce async state changes (loading, success, error) without visual focus shift
- Prevent overlapping announcements with a priority queue
- Clear stale announcements when the context changes
Interfaces
announce(message, priority)
announcePolite(message)
announceAssertive(message)
clearQueue()
setLocale(locale)
Relationships
Dependencies (1)
Components this component depends on
Dependents (3)
Components that depend on this component