From cd7e18ed7483ee1512d6c5c3bb940e9345804b07 Mon Sep 17 00:00:00 2001 From: Kristiyan Kostadinov Date: Sat, 19 Dec 2020 16:17:52 +0100 Subject: [PATCH] feat(cdk/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. --- .../live-announcer/live-announcer.spec.ts | 30 ++++++++++++++----- src/cdk/a11y/live-announcer/live-announcer.ts | 5 +++- tools/public_api_guard/cdk/a11y.d.ts | 3 +- 3 files changed, 29 insertions(+), 9 deletions(-) diff --git a/src/cdk/a11y/live-announcer/live-announcer.spec.ts b/src/cdk/a11y/live-announcer/live-announcer.spec.ts index 86b886cdd11f..63f818222949 100644 --- a/src/cdk/a11y/live-announcer/live-announcer.spec.ts +++ b/src/cdk/a11y/live-announcer/live-announcer.spec.ts @@ -1,5 +1,5 @@ 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'; @@ -288,7 +288,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(() => { @@ -297,7 +297,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'; @@ -315,7 +315,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(() => { @@ -333,6 +333,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); + })); + }); @@ -349,8 +359,14 @@ class TestApp { } } -@Component({template: `
{{content}}
`}) +@Component({ + template: ` +
{{content}}
` +}) class DivWithCdkAriaLive { - @Input() politeness: AriaLivePoliteness; - @Input() content = 'Initial content'; + politeness = 'polite'; + content = 'Initial content'; + duration: number; } diff --git a/src/cdk/a11y/live-announcer/live-announcer.ts b/src/cdk/a11y/live-announcer/live-announcer.ts index 2a417482dd30..1fc123df3914 100644 --- a/src/cdk/a11y/live-announcer/live-announcer.ts +++ b/src/cdk/a11y/live-announcer/live-announcer.ts @@ -203,7 +203,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; } }); @@ -212,6 +212,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; diff --git a/tools/public_api_guard/cdk/a11y.d.ts b/tools/public_api_guard/cdk/a11y.d.ts index 69246c1732aa..84bb15282d95 100644 --- a/tools/public_api_guard/cdk/a11y.d.ts +++ b/tools/public_api_guard/cdk/a11y.d.ts @@ -27,11 +27,12 @@ export declare const CDK_DESCRIBEDBY_HOST_ATTRIBUTE = "cdk-describedby-host"; export declare const CDK_DESCRIBEDBY_ID_PREFIX = "cdk-describedby-message"; export declare class CdkAriaLive implements OnDestroy { + duration: number; get politeness(): AriaLivePoliteness; set politeness(value: AriaLivePoliteness); constructor(_elementRef: ElementRef, _liveAnnouncer: LiveAnnouncer, _contentObserver: ContentObserver, _ngZone: NgZone); ngOnDestroy(): void; - static ɵdir: i0.ɵɵDirectiveDefWithMeta; + static ɵdir: i0.ɵɵDirectiveDefWithMeta; static ɵfac: i0.ɵɵFactoryDef; }