# announce Speaks a message through a screen reader without moving focus. Two visually hidden live regions, polite and assertive, are created in `` 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 `` would be ignored. ```ts 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 ```ehtml app/shared/templates/save-button/index.ehtml import { announce } from "@elements/ui/behaviors"; async function onSave(save: () => Promise) { try { await save(); announce("Saved"); } catch { announce("Save failed", "assertive"); } } Promise)> ``` ## Writes Two hidden elements, `#ui-announcer-polite` (a log) and `#ui-announcer-assertive` (an alert), each with `data-ui-announcer`, on `` or inside the top open modal dialog, and one node per message inside them. ## Used by [Chart](../templates/chart), [Combobox](../templates/combobox), [DataTable](../templates/data-table), [DatePicker](../templates/date-picker), [FileUpload](../templates/file-upload), [Kanban](../templates/kanban), [TagsInput](../templates/tags-input), [Toast](../templates/toast), and [drag](drag) in grab mode.