fix(material/snack-bar): flaky screen reader announcements for NVDA/JAWS - #20487
Conversation
crisbeto
left a comment
There was a problem hiding this comment.
My understanding is that this will only be a problem for snack bars that don't have an announcementMessage. What if, instead of setting a role on the container, we announced the textContent of the container with the LiveAnnouncer, when an announcementMessage isn't specified? The advantage would be that we won't have to add the extra timeout and we'll avoid having to move DOM nodes around.
6c2c961 to
3929ef1
Compare
|
I had previously considered an approach like you describe, using
Maybe a |
3929ef1 to
c47ba0d
Compare
c47ba0d to
01372a2
Compare
| // If an element in the snack bar content is focused before being moved | ||
| // track it and restore focus after moving to the live region. | ||
| let previouslyFocusedEle: HTMLElement | null = null; | ||
| if (this._platform.isBrowser && |
There was a problem hiding this comment.
Are the isBrowser check and the instanceof HTMLElement strictly necessary?
There was a problem hiding this comment.
The instanceof HTMLElement check is because document.activeElement is type Element which doesn't implement focus. So I check to make sure the active element is of type HTMLElement and therefore focusable.
I found without including the isBrowser check I would get some view_engine test failures related to document not existing. For mdc-snack-bar with the switch back to using setTimeout the call to _screenReaderAnnounce is already nested in a isBrowser check, so I've removed the redundant one. For snack-bar I've kept the check because it isn't done elsewhere in the component.
Here's an example test failure: https://app.circleci.com/pipelines/github/angular/components/13171/workflows/d5670bcf-b85d-4721-8372-86b96b5f872f/jobs/187667/parallel-runs/0/steps/0-107
f70b92b to
f3cdd40
Compare
jelbourn
left a comment
There was a problem hiding this comment.
Overall looks good, just one last comment about the extra change detection cycle from setTimeout
f3cdd40 to
4dd51ed
Compare
b12cd20 to
0628e6d
Compare
jelbourn
left a comment
There was a problem hiding this comment.
LGTM
Caretaker note: let me know if this results in a lot of failures
Fixes a bug where NVDA won't announce polite snack bars and JAWS won't announce any. This is because the live region (snack-bar-container) was added to the DOM, marked as a live region, and content was added to it in the same operation. Some screen readers require the live region to be added to the DOM, some time to pass, then content can be added. Now the snack bar content is added to an aria-hidden div then, 150ms later, moved to a div with aria-live defined. This won't cause any visual changes and keeps the snack bar content available immediatly after opening. Also, no longer using the alert or status roles. Instead just using aria-live as testing showed that NVDA will double announce with the alert role and JAWS won't announce any button text. BREAKING CHANGE: matSnackBarHarness.getRole() replaced with .getAriaLive() due to using aria-live rather than the alert and status roles.
0628e6d to
320b2c9
Compare
…AWS (angular#20487) Fixes a bug where NVDA won't announce polite snack bars and JAWS won't announce any. This is because the live region (snack-bar-container) was added to the DOM, marked as a live region, and content was added to it in the same operation. Some screen readers require the live region to be added to the DOM, some time to pass, then content can be added. Now the snack bar content is added to an aria-hidden div then, 150ms later, moved to a div with aria-live defined. This won't cause any visual changes and keeps the snack bar content available immediatly after opening. Also, no longer using the alert or status roles. Instead just using aria-live as testing showed that NVDA will double announce with the alert role and JAWS won't announce any button text. BREAKING CHANGE: matSnackBarHarness.getRole() replaced with .getAriaLive() due to using aria-live rather than the alert and status roles.
|
This issue has been automatically locked due to inactivity. Read more about our automatic conversation locking policy. This action has been performed automatically by a bot. |
Fixes a bug where NVDA won't announce polite snack bars and JAWS won't announce any.
This is because the live region (snack-bar-container) was added to the DOM, marked as a live
region, and content was added to it in the same operation. Some screen readers require the live
region to be added to the DOM, some time to pass, then content can be added. Now the snack bar
content is added to an aria-hidden div then, 150ms later, moved to a div with aria-live defined.
This won't cause any visual changes and keeps the snack bar content available immediatly after
opening. Also, no longer using the alert or status roles. Instead just using aria-live as testing
showed that NVDA will double announce with the alert role and JAWS won't announce any button text.
BREAKING CHANGE: matSnackBarHarness.getRole() replaced with .getAriaLive() due to using aria-live
rather than the alert and status roles.