LiveAnnouncer
A service and component for making announcements to screen readers via ARIA live regions.
Demo
Click the buttons below to trigger announcements. If you have a screen reader enabled, you'll hear the announcement. The announcement text is also shown below for visual feedback.
Features
- Reliable screen reader announcements using React Aria's proven pattern
- Supports both polite (non-interrupting) and assertive (immediate) announcements
- Automatic cleanup after 7 seconds (following React Aria's timing)
- Safari-compatible with 100ms initialization delay
- Simple dependency injection pattern
- Used internally by Calendar, Combobox, and other SummitUI components
Installation
dotnet add package SummitUISetup
Two steps are required to enable announcements:
1. Add the component to your layout
Place SmLiveAnnouncer once at the root of your application (e.g., MainLayout.razor).
This component initializes the JavaScript module that handles screen reader announcements.
@* MainLayout.razor *@
@using SummitUI
<SmLiveAnnouncer />
<main>
@Body
</main>2. Inject the service where needed
Inject ILiveAnnouncer into any component that needs to make announcements.
@using SummitUI.Services
@inject ILiveAnnouncer Announcer
<button @onclick="HandleClick">Select Item</button>
@code {
private void HandleClick()
{
Announcer.Announce("Item selected");
}
}API Reference
ILiveAnnouncer (Service)
| Method | Parameters | Description |
|---|---|---|
| Announce | string message, AnnouncementPriority priority = Polite | Announces a message to screen readers |
| Clear | AnnouncementPriority priority | Clears announcements for the specified priority |
| ClearAll | (none) | Clears all announcements (both polite and assertive) |
AnnouncementPriority (Enum)
| Value | ARIA Equivalent | Description |
|---|---|---|
| Polite | aria-live="polite" | Waits for the user to finish their current task before announcing. Use for non-urgent information. |
| Assertive | aria-live="assertive" | Interrupts the user immediately. Use sparingly for urgent information like errors. |
SmLiveAnnouncer (Component)
This component has no parameters. It simply initializes the JavaScript live announcer module when placed in your layout.
How It Works
The Problem
Screen readers monitor ARIA live regions for content changes, but they only reliably detect DOM node additions, not content replacements. When Blazor re-renders a component, it replaces elements rather than appending new ones, which screen readers often miss.
The Solution
SummitUI uses React Aria's proven pattern: vanilla JavaScript DOM manipulation that appends new child elements to the live region. This triggers reliable screen reader announcements across all major assistive technologies.
Technical Details
- Live regions:
Two hidden
divelements withrole="log"andaria-relevant="additions" - Announcement:
New
divelement appended as a child with the message text - Cleanup: Messages removed after 7000ms (following React Aria's timing)
- Safari fix: 100ms delay before first announcement to ensure live region is recognized
Examples
Basic Announcement
@using SummitUI.Services
@inject ILiveAnnouncer Announcer
<button @onclick="AnnounceMessage">Make Announcement</button>
@code {
private void AnnounceMessage()
{
// Polite announcement (default) - waits for user to finish current task
Announcer.Announce("Your changes have been saved");
}
}Form Validation Error
Use assertive priority for errors that need immediate attention.
@using SummitUI.Services
@inject ILiveAnnouncer Announcer
<EditForm Model="model" OnValidSubmit="HandleSubmit" OnInvalidSubmit="HandleInvalidSubmit">
<DataAnnotationsValidator />
<InputText @bind-Value="model.Email" />
<button type="submit">Submit</button>
</EditForm>
@code {
private MyModel model = new();
private void HandleInvalidSubmit()
{
// Assertive announcement - interrupts immediately for errors
Announcer.Announce("Error: Please fix the form errors before submitting",
AnnouncementPriority.Assertive);
}
private void HandleSubmit()
{
// Polite announcement for success
Announcer.Announce("Form submitted successfully");
}
}Selection Confirmation
Use polite priority for confirmations and status updates.
@using SummitUI.Services
@inject ILiveAnnouncer Announcer
<ul role="listbox">
@foreach (var item in items)
{
<li role="option"
aria-selected="@(selectedItem == item)"
@onclick="() => SelectItem(item)">
@item.Name
</li>
}
</ul>
@code {
private List<Item> items = new() { /* ... */ };
private Item? selectedItem;
private void SelectItem(Item item)
{
selectedItem = item;
Announcer.Announce($"{item.Name} selected");
}
}Search Results
Announce dynamic content updates like search results.
@using SummitUI.Services
@inject ILiveAnnouncer Announcer
<input type="search" @bind="searchTerm" @bind:event="oninput" @onkeyup="Search" />
<ul>
@foreach (var result in results)
{
<li>@result.Title</li>
}
</ul>
@code {
private string searchTerm = "";
private List<SearchResult> results = new();
private async Task Search()
{
results = await SearchService.SearchAsync(searchTerm);
// Announce the result count
var message = results.Count switch
{
0 => "No results found",
1 => "1 result found",
_ => $"{results.Count} results found"
};
Announcer.Announce(message);
}
}When to Use Each Priority
| Priority | Use Case | Example |
|---|---|---|
| Polite | Selection confirmations | "January 15, 2026 selected" |
| Polite | Status updates | "5 results found" |
| Polite | Progress updates | "Upload complete" |
| Assertive | Validation errors | "Error: Email is required" |
| Assertive | Time-sensitive alerts | "Session expires in 2 minutes" |
| Assertive | Critical failures | "Connection lost" |
Accessibility
Best Practices
- Prefer polite: Use assertive only for truly urgent information
- Be concise: Keep messages short and to the point
- Include context: Make messages understandable without visual context
- Localize: The caller is responsible for localizing messages
- Don't over-announce: Too many announcements become noise
Testing with Screen Readers
- -
VoiceOver (macOS): Press
Cmd + F5to toggle - - NVDA (Windows): Free screen reader for testing
- - JAWS (Windows): Commercial screen reader widely used
- - TalkBack (Android): Built-in Android screen reader
Integration with SummitUI Components
The following SummitUI components use LiveAnnouncer internally for accessibility:
- Calendar Announces date selection (e.g., "January 15, 2026 selected")
When using these components, ensure SmLiveAnnouncer is placed in your layout
to enable the announcements.