I am trying to make a toast message component accessible (to comply with WCAG 2.1 AA standards) in Angular. The toast message has 4 types (Success, Warning, Error, Info) and each type has a dynamic message.
The html of the toast component looks like this,
toast.component.html
<div aria-live="assertive" class="toast-wrapper toast-error">
<span id="toast_heading">{{toast.heading}}</span>
<sapn id="toast_message">{{toast.message}}</span>
</div>
app.component.html
<app-component>
<toast-component *ngIf="showToast"></toast-component>
</app-component>
The visibility of the toast is controlled by the showToast
variable and there are no multiple toast components showing up at the sametime as well. The toasts are also set to autohide after 3 seconds (I have been told this is not a good thing in an accessibility perspective).
However the toasts were not read by the screen reader (NVDA) I use when they are shown (In chrome, did not test in other browsers).
After searching about this I found out that the aria-live
attribute has to be present when the webpage is loading for some screen readers to pick it up and since the toast-component
is only being generated when a toast is needed, it is not being read by the screen reader.
I also found this webpage https://terrillthompson.com/tests/aria/live-scores.html where in the "Game 3" example the author has used a separate status div
to read the score and set role="presentation"
for the scoreboard.
I implemented it in my app like this:
toast.component.html
<div role="presentation" class="toast-wrapper toast-error">
<span id="toast_heading">{{toast.heading}}</span>
<sapn id="toast_message">{{toast.message}}</span>
</div>
app.component.html
<app-component>
<div aria-live="assertive" class="visiually-hidden" id="assertive_div">
{{toast.heading}} - {{toast.message}}
</div>
<toast-component *ngIf="showToast"></toast-component>
</app-component>
Now when I trigger a toast message it is being read by the screen reader eg: "Error - cannot delete the selected user" , "Successfull - 15 records were saved".
The question I have now is this approach of having a separate div
for screen readers to read as the toast message acceptable instead of reading it through the actual toast component ?
Plus, any areas to improve ?
It's true that live regions should exist on the page and not be dynamically added.
See my answer about live regions.
There's nothing wrong with having a separate <div>
to contain the live text that will be announced but I try to avoid that if I can mainly from a coding efficiency perspective. I don't like to have repeated blocks of text if I can get it to work with one block of text.
A few other things, I would recommend using polite
instead of assertive
for the live region. Assertive should be reserved for critical messages that absolutely have to be announced. Polite should be used in almost all cases.
The toasts are also set to autohide after 3 seconds (I have been told this is not a good thing in an accessibility perspective).
I agree with that this would cause an accessibility issue. It would fail 2.2.1 Timing Adjustable.
Toast messages, in general, are not a great UX. If you really want to use them, make then for messages that are not important so if the user doesn't see them, it's not a big deal. It's usually better to have a message area appear and not automatically disappear but have an X-close button on them.