Skip to content

Commit b503e21

Browse files
committed
feat(a11y): add input to control the duration of the aria live directive
Adds an input that allows the consumer to control how long it takes before the messages that are announced by `CdkAriaLive` to be cleared from the DOM.
1 parent 12edc0b commit b503e21

File tree

3 files changed

+25
-8
lines changed

3 files changed

+25
-8
lines changed

src/cdk/a11y/live-announcer/live-announcer.spec.ts

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import {MutationObserverFactory} from '@angular/cdk/observers';
2-
import {Component, Input} from '@angular/core';
2+
import {Component} from '@angular/core';
33
import {ComponentFixture, fakeAsync, flush, inject, TestBed, tick} from '@angular/core/testing';
44
import {By} from '@angular/platform-browser';
55
import {A11yModule} from '../index';
@@ -288,7 +288,7 @@ describe('CdkAriaLive', () => {
288288
invokeMutationCallbacks();
289289
flush();
290290

291-
expect(announcer.announce).toHaveBeenCalledWith('New content', 'polite');
291+
expect(announcer.announce).toHaveBeenCalledWith('New content', 'polite', undefined);
292292

293293
announcerSpy.calls.reset();
294294
fixture.componentInstance.politeness = 'off';
@@ -306,7 +306,7 @@ describe('CdkAriaLive', () => {
306306
invokeMutationCallbacks();
307307
flush();
308308

309-
expect(announcer.announce).toHaveBeenCalledWith('Newest content', 'assertive');
309+
expect(announcer.announce).toHaveBeenCalledWith('Newest content', 'assertive', undefined);
310310
}));
311311

312312
it('should not announce the same text multiple times', fakeAsync(() => {
@@ -324,6 +324,16 @@ describe('CdkAriaLive', () => {
324324
expect(announcer.announce).toHaveBeenCalledTimes(1);
325325
}));
326326

327+
it('should be able to pass in a duration', fakeAsync(() => {
328+
fixture.componentInstance.content = 'New content';
329+
fixture.componentInstance.duration = 1337;
330+
fixture.detectChanges();
331+
invokeMutationCallbacks();
332+
flush();
333+
334+
expect(announcer.announce).toHaveBeenCalledWith('New content', 'polite', 1337);
335+
}));
336+
327337
});
328338

329339

@@ -340,8 +350,11 @@ class TestApp {
340350
}
341351
}
342352

343-
@Component({template: `<div [cdkAriaLive]="politeness">{{content}}</div>`})
353+
@Component({
354+
template: `<div [cdkAriaLive]="politeness" [cdkAriaLiveDuration]="duration">{{content}}</div>`
355+
})
344356
class DivWithCdkAriaLive {
345-
@Input() politeness = 'polite';
346-
@Input() content = 'Initial content';
357+
politeness = 'polite';
358+
content = 'Initial content';
359+
duration: number;
347360
}

src/cdk/a11y/live-announcer/live-announcer.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ export class CdkAriaLive implements OnDestroy {
203203
// The `MutationObserver` fires also for attribute
204204
// changes which we don't want to announce.
205205
if (elementText !== this._previousAnnouncedText) {
206-
this._liveAnnouncer.announce(elementText, this._politeness);
206+
this._liveAnnouncer.announce(elementText, this._politeness, this.duration);
207207
this._previousAnnouncedText = elementText;
208208
}
209209
});
@@ -212,6 +212,9 @@ export class CdkAriaLive implements OnDestroy {
212212
}
213213
private _politeness: AriaLivePoliteness = 'off';
214214

215+
/** Time in milliseconds after which to clear out the announcer element. */
216+
@Input('cdkAriaLiveDuration') duration: number;
217+
215218
private _previousAnnouncedText?: string;
216219
private _subscription: Subscription | null;
217220

tools/public_api_guard/cdk/a11y.d.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,12 @@ export declare const CDK_DESCRIBEDBY_HOST_ATTRIBUTE = "cdk-describedby-host";
2525
export declare const CDK_DESCRIBEDBY_ID_PREFIX = "cdk-describedby-message";
2626

2727
export declare class CdkAriaLive implements OnDestroy {
28+
duration: number;
2829
get politeness(): AriaLivePoliteness;
2930
set politeness(value: AriaLivePoliteness);
3031
constructor(_elementRef: ElementRef, _liveAnnouncer: LiveAnnouncer, _contentObserver: ContentObserver, _ngZone: NgZone);
3132
ngOnDestroy(): void;
32-
static ɵdir: i0.ɵɵDirectiveDefWithMeta<CdkAriaLive, "[cdkAriaLive]", ["cdkAriaLive"], { "politeness": "cdkAriaLive"; }, {}, never>;
33+
static ɵdir: i0.ɵɵDirectiveDefWithMeta<CdkAriaLive, "[cdkAriaLive]", ["cdkAriaLive"], { "politeness": "cdkAriaLive"; "duration": "cdkAriaLiveDuration"; }, {}, never>;
3334
static ɵfac: i0.ɵɵFactoryDef<CdkAriaLive>;
3435
}
3536

0 commit comments

Comments
 (0)