useAnnouncer
A composable for announcing messages to screen readers.
This composable is available in Nuxt v3.17+.
Description
A composable for announcing dynamic content changes to screen readers. Unlike useRouteAnnouncer which automatically announces route changes, useAnnouncer gives you manual control over what and when to announce.
Use this for in-page updates like form validation, async operations, toast notifications, and live content changes.
Parameters
politeness: Sets the default urgency for screen reader announcements:off(disable the announcement),polite(waits for silence), orassertive(interrupts immediately). (defaultpolite)
Properties
message
- type:
Ref<string> - description: The current message to announce
politeness
- type:
Ref<'polite' | 'assertive' | 'off'> - description: Screen reader announcement urgency level
Methods
set(message, politeness = "polite")
Sets the message to announce with its urgency level.
polite(message)
Sets the message with politeness = "polite". Use for non-urgent updates that can wait for the screen reader to finish its current task.
assertive(message)
Sets the message with politeness = "assertive". Use for urgent updates that should interrupt the screen reader immediately.
Example
app/pages/contact.vue
<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>
Use Cases
Form Validation
app/components/LoginForm.vue
<script setup lang="ts">
const { assertive } = useAnnouncer()
function validateForm () {
const errors = []
if (!email.value) { errors.push('Email is required') }
if (!password.value) { errors.push('Password is required') }
if (errors.length) {
assertive(`Form has ${errors.length} errors: ${errors.join(', ')}`)
return false
}
return true
}
</script>
Loading States
app/pages/dashboard.vue
<script setup lang="ts">
const { polite } = useAnnouncer()
const { data, status } = await useFetch('/api/data')
watch(status, (newStatus) => {
if (newStatus === 'pending') {
polite('Loading data...')
} else if (newStatus === 'success') {
polite('Data loaded successfully')
}
})
</script>
Search Results
app/components/Search.vue
<script setup lang="ts">
const { polite } = useAnnouncer()
const results = ref([])
watch(results, (newResults) => {
polite(`Found ${newResults.length} results`)
})
</script>
You need to add the
<NuxtAnnouncer> component to your app for the announcements to be rendered in the DOM.For automatic announcements of route/page changes, use
useRouteAnnouncer with the <NuxtRouteAnnouncer> component instead.