Manual UI Behaviors announce

announce

elements man ui/behaviors/announce

Speaks 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.

Signatures
function 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.ehtml
import { 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.