Skip to content

feat(a11y): allow to queue announcements in LiveAnnouncer #17986

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed

feat(a11y): allow to queue announcements in LiveAnnouncer #17986

wants to merge 1 commit into from

Conversation

yurii-shylov
Copy link

Standard LiveAnnouncer operates with a single aria-live element, which means that if several
announcements happen at the same time, only the latest one is actually announced. This change adds
useQueue configuration to LiveAnnouncerDefaultOptions. When it's set to true LiveAnnouncer
creates a separate aria-live element for each of the announcements and places all messages in
the queue, so they are announced one by one.

Fixes #17852

@googlebot
Copy link

We found a Contributor License Agreement for you (the sender of this pull request), but were unable to find agreements for all the commit author(s) or Co-authors. If you authored these, maybe you used a different email address in the git commits than was used to sign the CLA (login here to double check)? If these were authored by someone else, then they will need to sign a CLA as well, and confirm that they're okay with these being contributed to Google.
In order to pass this check, please resolve this problem and then comment @googlebot I fixed it.. If the bot doesn't comment, it means it doesn't think anything has changed.

ℹ️ Googlers: Go here for more info.

@googlebot googlebot added the cla: no PR author must sign Google's Contributor License Agreement: https://opensource.google.com/docs/cla label Dec 17, 2019
@yurii-shylov
Copy link
Author

@googlebot I fixed it.

@googlebot
Copy link

CLAs look good, thanks!

ℹ️ Googlers: Go here for more info.

@googlebot googlebot added cla: yes PR author has agreed to Google's Contributor License Agreement and removed cla: no PR author must sign Google's Contributor License Agreement: https://opensource.google.com/docs/cla labels Dec 17, 2019
return this._ngZone.runOutsideAngular(() => {
return new Promise(resolve => {
clearTimeout(this._previousTimeout);
this._previousTimeout = setTimeout(() => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should run outside the NgZone.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm unfamiliar with how zone.js works. The promise is already wrapped in ngZone.runOutsideAngular, is it enough or there should be another similar wrapper around setTimeout?

Also this particular code was just moved from another location. If it's a bug, let me know, it's probably better to fix it in a separate PR

Standard LiveAnnouncer operates with a single aria-live element, which means that if several
announcements happen at the same time, only the latest one is actually announced. This change adds
`useQueue` configuration to LiveAnnouncerDefaultOptions. When it's set to `true` LiveAnnouncer
creates a separate aria-live element for each of the announcements and places all messages in
the queue, so they are announced one by one.

Fixes #17852
@jelbourn jelbourn added the target: minor This PR is targeted for the next minor release label Jan 29, 2020
Copy link
Member

@jelbourn jelbourn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for the delay, recovering from the post-holiday backlog took a long time.


/**
* Indicates whether announcements should be queued or each next one should
* override the previous one.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* override the previous one.
* override the previous one. Defaults to `false`.

const ARIA_LIVE_ANNOUNCER_REMOVAL_DELAY_MS = 1000;

/** Class for the hidden div element with an aria-live attribute. */
const LIVE_ELEMENT_CLASS = 'cdk-live-announcer-element';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const LIVE_ELEMENT_CLASS = 'cdk-live-announcer-element';
const LIVE_ELEMENT_CSS_CLASS = 'cdk-live-announcer-element';

message: string, politeness: AriaLivePoliteness, duration?: number): Promise<void> {
const liveElement = this._createLiveElement();
// TODO: ensure changing the politeness works on all environments we support.
liveElement.setAttribute('aria-live', politeness);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The politeness should be set at the same time the queued announcement is made, otherwise it will get out of sync. Both the immediate and queued code path should really call the same method that sets the politeness and updates the textContent

* queued live announce messages are read, even if the node containing them is
* removed before the message starts playing.
*/
const ARIA_LIVE_ANNOUNCER_REMOVAL_DELAY_MS = 1000;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will screen-readers continue reading a long message if it's removed from the DOM before the announcement is done? I worry that some will and that one second is too short.

liveElement.setAttribute('aria-live', politeness);

return new Promise(resolve => {
this._taskQueue.enqueue(() => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Upon looking at the code, I think the TaskQueue isn't strictly necessary and that this could be done a bit more simply. You could instead keep two arrays, _assertiveQueue and _politeQueue. After any given announcement finishes, pop the front message from _assertiveQueue if not empty, then _politeQueue, and repeat.

@jelbourn jelbourn added the Accessibility This issue is related to accessibility (a11y) label Apr 3, 2020
@devversion devversion removed their request for review August 18, 2021 13:01
@andrewseguin andrewseguin removed the cla: yes PR author has agreed to Google's Contributor License Agreement label Dec 28, 2021
@andrewseguin
Copy link
Contributor

Closing due to inactivity since the latest comments. Feel free to re-open a new PR if you'd like to try and get this landed

@angular-automatic-lock-bot
Copy link

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Apr 28, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Accessibility This issue is related to accessibility (a11y) target: minor This PR is targeted for the next minor release
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Queue messages sent to LiveAnnouncer
5 participants