Open yurii-shylov opened 4 years ago
In general I think this could be a good improvement. It would be great to see a specific proposal/design doc for updating the existing LiveAnnouncer
, since we would want to avoid any breaking changes.
In constructor LiveAnnouncer creates an aria-live
<div>
. Whenever user calls announce('Foo')
it erases the content of that <div>
and after a 100ms delay sets 'Foo' to it. Screen readers detect that change and read 'Foo' to the user.
If announce('Foo')
and announce('Bar')
are called approximatelly at the same time, second message overrides the value of that single <div>
element. It means that screen reader will only read 'Bar'.
There will be a TaskQueue
class with a single method enqueue(task: () => void, politeness: AriaLivePoliteness, delay = 0): void
. All tasks will be added to a single queue, they will be sorted by politeness only (so 'assertive' messages will always get announced before 'polite' ones, even if they were scheduled later). delay
will regulate the delay before task gets executed (similar to the 100ms described above). So calling enqueue(foo, 100); enqueu(bar, 100)
will execute task foo
in ~100ms from now and task bar
in ~200ms from now.
In constructor QueuedLiveAnnouncer creates only the TaskQueue
. Whenever user calls announce('Foo')
it creates a new <div>
element with appropriate aria-live
and attaches it to the DOM. It places a task to the queue with a 100ms delay; the task sets 'Foo' to the previously created <div>
and schedules a removal of that <div>
in 1000ms (originally we had 30s, but we've tested 1s in various screen readers, it's safe to use and allows to clean up DOM sooner). Screen readers detect new <div>
and read 'Foo' to the user.
If announce('Foo')
and announce('Bar')
are called approximatelly at the same time, both divs will also be attached to the DOM at the same time, but the innex test for them will be set with a guaranteed difference of at least 100ms. This allows screen readers to properly read both 'Foo' and 'Bar' one by one. Unlike regular LiveAnnounce it also allows to read 'Foo' more than once because different divs are used for them.
I see two potential problems:
announce('Foo'); announce('Foo'); announce('Foo'); announce('Bar');
produces only 2 messages.LiveAnnouncer
class. Having multiple API surfaces can be confusing for users. announce
because some applications may depend on this. One possible approach would be to add a new method to LiveAnnouncer
, enqueueAnnouncement
or announceWithQueue
<div>
element we do not need. Having an interface would automatically solve that issue)announce
untouched. I do not think that having an extra announceWithQueue
is the solution though. First of all, it provides similar confusion as a separate class would do. Secondly, personally I was surprised that announce('Foo'); announce('Bar')
actually announces only the second message, as a user who's seen LiveAnnounce for the first time I would expect that it handles that situation. Imho, announceWithQueue
should be the primary method, but it sounds secondary comparing to just the announce
one. What if we add a boolean config field to LiveAnnouncerDefaultOptions
which will control whether queue is used or not? It will be false
by default and people will have opportunity to switch it to true
for their whole project without changing the way they call LiveAnnouncer.I like the idea of using LiveAnnouncerDefaultOptions
for this.
Just a heads up that we kicked off a community voting process for your feature request. There are 20 days until the voting process ends.
Find more details about Angular's feature request process in our documentation.
Thank you for submitting your feature request! Looks like during the polling process it didn't collect a sufficient number of votes to move to the next stage.
We want to keep Angular rich and ergonomic and at the same time be mindful about its scope and learning journey. If you think your request could live outside Angular's scope, we'd encourage you to collaborate with the community on publishing it as an open source package.
You can find more details about the feature request process in our documentation.
Feature Description
LiveAnnouncer should be able to queue multiple messages and announce them one by one instead of announcing only the lates message.
Use Case
See https://stackblitz.com/edit/angular-b4jomd, it has a button which announces two messages "Table Foo was updated" and "Table Bar was updated" on click. It illustrates two use cases:
1) Simultaneous announcements. Current implementation of LiveAnnouncer uses a single DOM element for the announcement, so second message overrides the first one and screen reader users hear only the second message.
2) Consequent announcement of the same message. Current implementation will announce only distinct messages, i.e. clicking the button multiple times will produce only one message for the screen reader. That's not always convenient. For example, if you have a table on the page and you do some polling which updates the table 5 times, we need to be able to announce every of those updates so that screen reader users know what's happening on the page.
Implementation
We already have an implementation of a queued LiveAnnouncer which was used in GCP for the last 5 months, it alowed to fix a lot of accessibility problems on pages with heavy UIs. I will convert it to a PR here, but I'd like to have some discussion first. At the very least I'd like to know whether it should replace the existing LiveAnnouncer implementation or we should allow users to switch between two implementations