Skip to content
Accessibility

Announcer

Imperatively announce messages to screen readers for feedback that has no visual anchor — async results, background updates, undo confirmations. A single shared, visually-hidden ARIA live region does the work; import announce or useAnnouncer from @mikenotthepope/substrateui/hooks.

Why

Some feedback never reaches screen-reader users because nothing on screen changes where their focus is: a search that finishes loading, a toast that fades, an item removed from a list. A live region announces that text out loud without moving focus or rendering anything visible.

Example

Turn on a screen reader (VoiceOver, NVDA) and press a button — the message is read aloud. The box below mirrors it for sighted testing.

Sighted mirror (what a screen reader just heard)

Nothing announced yet — turn on a screen reader and press a button.

Imperative use

Outside React — in a store, a fetch callback, a utility — call announce directly. It lazily creates the shared region on first use and is a safe no-op during SSR.

announce("Draft saved", "polite")

Politeness

Prefer "polite"(the default): it waits for the screen reader to finish what it's saying. Reserve "assertive" for genuinely urgent messages — errors that block the user — since it interrupts immediately.

API Reference

PropTypeDefaultDescription
useAnnouncer()() => { announce, clear }React hook returning a stable announce/clear pair for use in effects and handlers.
announce(message, assertiveness?, timeout?)(string, 'assertive' | 'polite', number) => void'polite', 7000Imperatively announce a message. Empty string clears without announcing.
clearAnnouncer(assertiveness?)('assertive' | 'polite') => voidClear pending messages from one region, or both when omitted.
destroyAnnouncer()() => voidRemove the live region from the document entirely (teardown / tests).