Live Region
Announces its text to screen readers when the text changes. LiveRegion renders a persistent, visually hidden <span> live region with role="status" and aria-live="polite"; the redundant aria-live covers screen reader and browser pairs that honor only one of the two. When politeness is "assertive", it renders role="alert" alone: the role already carries assertive live-region semantics, and a redundant aria-live makes VoiceOver on iOS announce the message twice.
A live region announces reliably only when it already exists in the accessibility tree before its text changes. Keep LiveRegion mounted from first paint and swap only its children. A screen reader does not re-announce a message identical to the previous one; when the same message must repeat, clear the children first.
When to use
- Announce a completed client-side navigation: the new page name, after a route change.
- Announce an async result that moves focus nowhere: "3 results found", "Draft saved".
When not to use
- For status the user must see. Use
AlertorToast, which pair visible UI with their own announcements. - For hidden text that never changes. Use
VisuallyHidden.
- Result 1
- Result 2
- Result 3
Polymorphism
LiveRegion accepts an asChild prop. When true, it renders its single child instead of its default <span>, forwarding its class names, ARIA attributes, data-* attributes, and ref onto that child.
Ready.
The live region above is a hidden paragraph element.
Politeness
politeness defaults to "polite": the announcement waits for the screen reader's current utterance to finish. Pass "assertive" only when a delayed announcement would mislead the user (a session about to expire, a failed save). An assertive region interrupts the screen reader's current utterance.
The session is active.
Announcing route changes
A single-page app repaints on navigation without a page load, so screen readers announce nothing. Feed a persistent LiveRegion the page name from your router's location, so it announces each completed navigation. The demo swaps pages with local state because the docs site cannot navigate inside an example. In your app, derive pageName from the router's location instead. The Route Announcer recipe is the complete pattern wired to React Router: page-name fallbacks, repeat-message handling, and tests.
Dashboard
API Reference
LiveRegion
All props from span, plus:
The derived role and aria-live read as defaults: a role or aria-live prop wins. aria-atomic defaults to "true" so the region re-reads the whole message, not the changed characters.