Skip to content

Commit

Permalink
feat(cdk/a11y): add input to control the duration of the aria live di…
Browse files Browse the repository at this point in the history
…rective

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.
  • Loading branch information
crisbeto committed Feb 26, 2022
1 parent 0dfc490 commit 2a11276
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 10 deletions.
32 changes: 24 additions & 8 deletions src/cdk/a11y/live-announcer/live-announcer.spec.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import {MutationObserverFactory} from '@angular/cdk/observers';
import {Component, Input} from '@angular/core';
import {Component} from '@angular/core';
import {ComponentFixture, fakeAsync, flush, inject, TestBed, tick} from '@angular/core/testing';
import {By} from '@angular/platform-browser';
import {A11yModule, AriaLivePoliteness} from '../index';
import {A11yModule} from '../index';
import {LiveAnnouncer} from './live-announcer';
import {
LIVE_ANNOUNCER_ELEMENT_TOKEN,
Expand Down Expand Up @@ -280,7 +280,7 @@ describe('CdkAriaLive', () => {
invokeMutationCallbacks();
flush();

expect(announcer.announce).toHaveBeenCalledWith('New content', 'polite');
expect(announcer.announce).toHaveBeenCalledWith('New content', 'polite', undefined);
}));

it('should dynamically update the politeness', fakeAsync(() => {
Expand All @@ -289,7 +289,7 @@ describe('CdkAriaLive', () => {
invokeMutationCallbacks();
flush();

expect(announcer.announce).toHaveBeenCalledWith('New content', 'polite');
expect(announcer.announce).toHaveBeenCalledWith('New content', 'polite', undefined);

announcerSpy.calls.reset();
fixture.componentInstance.politeness = 'off';
Expand All @@ -307,7 +307,7 @@ describe('CdkAriaLive', () => {
invokeMutationCallbacks();
flush();

expect(announcer.announce).toHaveBeenCalledWith('Newest content', 'assertive');
expect(announcer.announce).toHaveBeenCalledWith('Newest content', 'assertive', undefined);
}));

it('should not announce the same text multiple times', fakeAsync(() => {
Expand All @@ -324,6 +324,16 @@ describe('CdkAriaLive', () => {

expect(announcer.announce).toHaveBeenCalledTimes(1);
}));

it('should be able to pass in a duration', fakeAsync(() => {
fixture.componentInstance.content = 'New content';
fixture.componentInstance.duration = 1337;
fixture.detectChanges();
invokeMutationCallbacks();
flush();

expect(announcer.announce).toHaveBeenCalledWith('New content', 'polite', 1337);
}));
});

function getLiveElement(): Element {
Expand All @@ -339,8 +349,14 @@ class TestApp {
}
}

@Component({template: `<div [cdkAriaLive]="politeness ? politeness : null">{{content}}</div>`})
@Component({
template: `
<div
[cdkAriaLive]="politeness ? politeness : null"
[cdkAriaLiveDuration]="duration">{{content}}</div>`,
})
class DivWithCdkAriaLive {
@Input() politeness: AriaLivePoliteness;
@Input() content = 'Initial content';
politeness = 'polite';
content = 'Initial content';
duration: number;
}
5 changes: 4 additions & 1 deletion src/cdk/a11y/live-announcer/live-announcer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ export class CdkAriaLive implements OnDestroy {
// The `MutationObserver` fires also for attribute
// changes which we don't want to announce.
if (elementText !== this._previousAnnouncedText) {
this._liveAnnouncer.announce(elementText, this._politeness);
this._liveAnnouncer.announce(elementText, this._politeness, this.duration);
this._previousAnnouncedText = elementText;
}
});
Expand All @@ -207,6 +207,9 @@ export class CdkAriaLive implements OnDestroy {
}
private _politeness: AriaLivePoliteness = 'polite';

/** Time in milliseconds after which to clear out the announcer element. */
@Input('cdkAriaLiveDuration') duration: number;

private _previousAnnouncedText?: string;
private _subscription: Subscription | null;

Expand Down
3 changes: 2 additions & 1 deletion tools/public_api_guard/cdk/a11y.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,13 @@ export const CDK_DESCRIBEDBY_ID_PREFIX = "cdk-describedby-message";
// @public
export class CdkAriaLive implements OnDestroy {
constructor(_elementRef: ElementRef, _liveAnnouncer: LiveAnnouncer, _contentObserver: ContentObserver, _ngZone: NgZone);
duration: number;
// (undocumented)
ngOnDestroy(): void;
get politeness(): AriaLivePoliteness;
set politeness(value: AriaLivePoliteness);
// (undocumented)
static ɵdir: i0.ɵɵDirectiveDeclaration<CdkAriaLive, "[cdkAriaLive]", ["cdkAriaLive"], { "politeness": "cdkAriaLive"; }, {}, never>;
static ɵdir: i0.ɵɵDirectiveDeclaration<CdkAriaLive, "[cdkAriaLive]", ["cdkAriaLive"], { "politeness": "cdkAriaLive"; "duration": "cdkAriaLiveDuration"; }, {}, never>;
// (undocumented)
static ɵfac: i0.ɵɵFactoryDeclaration<CdkAriaLive, never>;
}
Expand Down

0 comments on commit 2a11276

Please sign in to comment.