docs/4.api/1.components/14.nuxt-announcer.md
::important This component is available in Nuxt v4.4.2+. ::
Add <NuxtAnnouncer/> in your app.vue or app/layouts/ to enable announcing dynamic content changes to screen readers. This is useful for form validation, toast notifications, loading states, and other in-page updates.
<template>
<NuxtAnnouncer />
<NuxtRouteAnnouncer />
<NuxtLayout>
<NuxtPage />
</NuxtLayout>
</template>
Then use the useAnnouncer composable anywhere in your app to announce messages:
<script setup lang="ts">
const { polite, assertive } = useAnnouncer()
async function submitForm () {
try {
await $fetch('/api/contact', { method: 'POST', body: formData })
polite('Message sent successfully')
} catch (error) {
assertive('Error: Failed to send message')
}
}
</script>
You can pass custom HTML or components through the announcer's default slot.
<template>
<NuxtAnnouncer>
<template #default="{ message }">
<p>{{ message }}</p>
</template>
</NuxtAnnouncer>
</template>
atomic: Controls if screen readers announce only changes or the entire content. Set to true for full content readouts on updates, false for changes only. (default true)politeness: Sets the default urgency for screen reader announcements: off (disable the announcement), polite (waits for silence), or assertive (interrupts immediately). (default polite)<NuxtRouteAnnouncer>| Aspect | <NuxtRouteAnnouncer> | <NuxtAnnouncer> |
|---|---|---|
| Purpose | Announces route/page changes | Announces any dynamic content |
| Trigger | Automatic on navigation | Manual via polite()/assertive() |
| Message source | Page <title> | Developer-provided |
| atomic default | false | true |
::callout This component is optional. :br To achieve full customization, you can implement your own one based on its source code. ::
::callout
You can hook into the underlying announcer instance using the useAnnouncer composable, which allows you to set custom announcement messages.
::