announce
elements man ui/behaviors/announceSpeaks a message through a screen reader without moving focus. Two visually
hidden live regions, polite and assertive, are created in <body> on first
use and reused. While a modal dialog is open they move into it, since
everything outside a modal is inert and a region left on <body> would be
ignored.
Signaturesfunction announce(message: Announcement, politeness?: Politeness, opts?: AnnounceOptions): void; function clearAnnouncements(politeness?: Politeness): void; function destroyAnnouncer(): void; type Politeness = "polite" | "assertive"; type Announcement = string | { "aria-labelledby": string };
| Argument | Type | Default | What it does |
|---|---|---|---|
message |
Announcement |
required | The text to speak, or { "aria-labelledby": id } to read an element's text instead. |
politeness |
Politeness |
"polite" |
"polite" never interrupts what is being read; "assertive" is an alert and does. |
opts.timeout |
number |
stays until the next message | ms after which the message is cleared from the region. |
The region is cleared first and the message written a frame later as its own node, so the same message announced twice is spoken twice. Several announced at once are written one per frame, each kept for a frame, so all of them are spoken. A message announced within 100ms of the regions' creation waits until then, so the screen reader has registered the regions before it reads one.
clearAnnouncements(politeness?) empties one region or both and drops
messages not yet written. destroyAnnouncer() removes the regions; the next
announce() creates them again.
In a template of your own
app/shared/templates/save-button/index.ehtmlimport { announce } from "@elements/ui/behaviors"; async function onSave(save: () => Promise<void>) { try { await save(); announce("Saved"); } catch { announce("Save failed", "assertive"); } } <SaveButton (save: () => Promise<void>)> <button type="button" onclick={() => onSave(save)}><slot/></button> </SaveButton>
Writes
Two hidden elements, #ui-announcer-polite (a log) and
#ui-announcer-assertive (an alert), each with data-ui-announcer, on
<body> or inside the top open modal dialog, and one node per message
inside them.
Used by
Chart (opens in a new tab), Combobox (opens in a new tab), DataTable (opens in a new tab), DatePicker (opens in a new tab), FileUpload (opens in a new tab), Kanban (opens in a new tab), TagsInput (opens in a new tab), Toast (opens in a new tab), and drag (opens in a new tab) in grab mode.