A function-based API for aria-live announcements. Announces messages to screen readers without requiring any component setup.
Installation
npm install betteruseUsage
import { echo } from 'betteruse'
// Polite announcement (default)
echo('Item added to cart')
// Assertive announcement (interrupts current speech)
echo.assertive('Error: Invalid email')
// With options
echo('Saved!', { timeout: 5000 })
API Reference
echo(message, options?)
Announces a message to screen readers.
| Prop | Type | Default | Description |
|---|---|---|---|
message* | string | - | The message to announce |
options | EchoOptions | - | Configuration options |
EchoOptions
| Prop | Type | Default | Description |
|---|---|---|---|
assertive | boolean | false | Use assertive mode (interrupts current speech) |
timeout | number | 1000 | Auto-clear timeout in milliseconds |
Methods
echo.assertive(message, options?)- Shorthand for assertive announcementsecho.polite(message, options?)- Shorthand for polite announcements
How It Works
echo creates a hidden aria-live region on first call and manages announcements through it:
- On first call, creates a visually hidden
<div>witharia-liveattribute - Updates the text content to trigger screen reader announcement
- Clears the content after the timeout to allow repeated announcements
The region is styled to be invisible but accessible to screen readers:
position: absolute;
width: 1px;
height: 1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
This hook is SSR-safe. The aria-live region is only created on the client.
Examples
Form Validation
function LoginForm() {
const handleSubmit = async (e: FormEvent) => {
e.preventDefault()
try {
await login(email, password)
echo('Successfully logged in')
} catch (error) {
echo.assertive('Login failed. Please check your credentials.')
}
}
return <form onSubmit={handleSubmit}>...</form>
}
Toast-like Notifications
function AddToCartButton({ productId }: { productId: string }) {
const handleClick = async () => {
await addToCart(productId)
echo('Item added to cart', { timeout: 3000 })
}
return <button onClick={handleClick}>Add to Cart</button>
}
Loading States
function DataLoader() {
const [isLoading, setIsLoading] = useState(false)
const loadData = async () => {
setIsLoading(true)
echo('Loading data...')
await fetchData()
setIsLoading(false)
echo('Data loaded successfully')
}
return <button onClick={loadData}>Load Data</button>
}
Accessibility
This hook is designed with accessibility in mind:
- Uses
aria-liveregions for screen reader compatibility - Supports both
politeandassertivemodes - Auto-clears messages to allow repeated announcements
- Works with all major screen readers (NVDA, JAWS, VoiceOver)