# 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