LiveAnnouncer
Signal-based wrapper around Angular CDK's LiveAnnouncer. Reactively track and announce messages for screen readers.
CDK Interop Package Required
This utility requires the @signality/cdk-interop and @angular/cdk packages to be installed:
bash
npm install @signality/cdk-interop @angular/cdkUsage
angular-ts
import { Component } from '@angular/core';
import { liveAnnouncer } from '@signality/cdk-interop';
@Component({
template: `
<button (click)="save()">Save</button>
<p>Last announcement: {{ announcer.lastMessage() ?? 'none' }}</p>
`,
})
export class SaveButton {
readonly announcer = liveAnnouncer();
save() {
this.announcer.announce('Document saved successfully');
}
}Parameters
| Parameter | Type | Description |
|---|---|---|
options | LiveAnnouncerOptions | Optional configuration (see Options below) |
Options
The LiveAnnouncerOptions extends WithInjector:
| Option | Type | Default | Description |
|---|---|---|---|
defaultPoliteness | 'polite' | 'assertive' | 'off' | 'polite' | Default politeness level for announcements. See ARIA live regions |
injector | Injector | - | Optional injector for DI context |
Return Value
The liveAnnouncer() function returns a LiveAnnouncerRef object:
| Property | Type | Description |
|---|---|---|
lastMessage | Signal<string | null> | Last announced message |
announce | (message: string, politeness?: AriaLivePoliteness) => void | Announce a message to screen readers |
clear | () => void | Clear all announcements |
Examples
Form validation feedback
angular-ts
import { Component, effect } from '@angular/core';
import { liveAnnouncer } from '@signality/cdk-interop';
@Component({
template: `
<form>
<input #email type="email" />
<button type="submit">Submit</button>
</form>
`,
})
export class ContactForm {
readonly announcer = liveAnnouncer();
readonly email = viewChild<ElementRef>('email');
onSubmit() {
if (!this.email()?.nativeElement.validity.valid) {
this.announcer.announce('Please enter a valid email', 'assertive');
}
}
}Dynamic content updates
angular-ts
import { Component, effect } from '@angular/core';
import { liveAnnouncer } from '@signality/cdk-interop';
@Component({
template: `
<button (click)="addItem()">Add Item</button>
<p>Items: {{ items().length }}</p>
`,
})
export class ShoppingCart {
readonly announcer = liveAnnouncer();
readonly items = signal<string[]>([]);
addItem() {
this.items.update(items => [...items, 'New item']);
this.announcer.announce(`Item added. Total: ${this.items().length}`);
}
}Navigation announcements
angular-ts
import { Component, inject, DOCUMENT } from '@angular/core';
import { liveAnnouncer } from '@signality/cdk-interop';
import { routerListener } from '@signality/core';
@Component({
template: `<router-outlet />`,
})
export class App {
readonly document = inject(DOCUMENT);
readonly announcer = liveAnnouncer();
constructor() {
routerListener('navigationend', () => {
const pageTitle = this.document.title || 'Page loaded';
this.announcer.announce(`Navigated to ${pageTitle}`);
});
}
}Type Definitions
typescript
type AriaLivePoliteness = 'polite' | 'assertive' | 'off';
interface LiveAnnouncerOptions extends WithInjector {
readonly defaultPoliteness?: AriaLivePoliteness;
}
interface LiveAnnouncerRef {
readonly lastMessage: Signal<string | null>;
readonly announce: (message: string, politeness?: AriaLivePoliteness) => void;
readonly clear: () => void;
}
function liveAnnouncer(options?: LiveAnnouncerOptions): LiveAnnouncerRef;Related
- focusMonitor — Monitor focus state with origin detection
- inputModality — Track current input method