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
| Prop | Type | Default | Description |
|---|---|---|---|
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', 7000 | Imperatively announce a message. Empty string clears without announcing. |
clearAnnouncer(assertiveness?) | ('assertive' | 'polite') => void | — | Clear pending messages from one region, or both when omitted. |
destroyAnnouncer() | () => void | — | Remove the live region from the document entirely (teardown / tests). |