Skip to content
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

Potential Live Region Issues with Alert Component (amongst others) #1359

Open
garyb1 opened this issue Jun 2, 2023 · 4 comments
Open

Potential Live Region Issues with Alert Component (amongst others) #1359

garyb1 opened this issue Jun 2, 2023 · 4 comments
Assignees
Labels
a11y Anything relating to accessibility.

Comments

@garyb1
Copy link

garyb1 commented Jun 2, 2023

Describe the bug

Hey, I was looking at the Alert component and I noticed it added an ARIA alert role to the component base in the shadow DOM. This component becomes hidden from the accessibility tree with aria-hidden="true" and also styled with display: none via the hidden attribute.

Scott O'Hara talks about live regions in a post called are we live.

Dynamically injecting a live region node or changing an existing live region from display: none to display: block are effectively the same. In both cases (being absent or set to display: none) the live region does not exist in the a11y tree. Rather, as the following test cases show, ensuring an empty live region exists in your DOM, and injecting content into it when necessary, proves to be the most robust way to ensure a live region will be announced.

Hopefully this helps, and I'm happy to help with a potential solution.

@garyb1 garyb1 added the bug Things that aren't working right in the library. label Jun 2, 2023
@claviska
Copy link
Member

Hey, sorry for the late reply! We'd love a hand with this. What are you proposing as a workaround?

Note that <sl-alert> is designed to be hidden by default and only visible with the open attribute. Not sure if that was obvious or not, but figured I'd call it out.

I'm looking forward to your thoughts on this one!

@garyb1
Copy link
Author

garyb1 commented Jul 12, 2023

Hey @claviska,
No worries at all, thanks for your response. Yeah I was actually going to reach out about this one on discord because there is a lot to discuss. I'l share my thoughts below.

Live Region Container

The approach I was thinking of is having a live region available in the DOM as the page loads. You could add this whenever an <sl-alert> component is present, even if it's closed. This would support WCAG 4.1.3 Status Message (AA).

An example that is similar in approach is the magenta11y alert component demo, or even the APG Alert example where the live region is available beside the show alert button. Although magenta11y are using "inert" when the role="alert" is not open which may cause issues also.

Severity of Alerts

Some people might not consider a success message an alert, and depending on context, info and warning might not be either. So you might need both a role="alert" (assertive), and role="status" (polite) nodes available in the DOM on page load.

Focus Management

In the scenario where users have alerts/toasts auto-focused, I'm not sure if we allow for that in the component or why we would want that, but if that did happen it would then cause duplicate announcements (from the live region and then the focused element). We would not want duplicate announcements so we would need a way to turn them off in this scenario I think.

Toasts

Toast accessibility can be tricky so I'm going to defer to these post on accessible toasts by Scott O'Hara and defining toast messages by Adrian Roselli.

Both makes some really good points.

We mentioned already about the status message. Toast is a good candidate for having a status container.

A toast component should be considered a type of status message, and thus should be injected into a role="status".

There could be a potential WCAG 2.2.1 Violation in how you hide toasts after a few seconds.

If you follow the pattern where they go away after a few seconds, then you are in violation. There are ways around it, detailed in the 2.2.1 Understanding document, and includes letting the user adjust the duration in advance, allowing the user to extend their display time on a case-by-case basis, or letting the messages display for 20 hours.

Our toasts have an action button to dismiss which complicates things also.

@claviska
Copy link
Member

The approach I was thinking of is having a live region available in the DOM as the page loads. You could add this whenever an component is present, even if it's closed.

Apologies for the delay. We currently use the toast stack to group alerts when they're emitted as toasts. The logic is quite simple, but it's worth noting that the stack gets created only when a toast is first emitted and destroyed when the last toast is dismissed.

What do you suggest for handling both of these use cases?

  1. Alerts that live inline, but only show at certain moments? (e.g. after an invalid form submission)
  2. Alerts that live as toasts (using the toast stack)

Side note — we probably need to add more guidance as to how and when to use alerts. Despite them being closed by default, I think a lot of people confuse them for inline banners. 🤔

Some people might not consider a success message an alert, and depending on context, info and warning might not be either. So you might need both a role="alert" (assertive), and role="status" (polite) nodes available in the DOM on page load.

It sounds like we probably won't be able to guess the correct role here, so we may want to expose this for users. What would you recommend as a default, and what other options should we let them opt into?

If we're able to simplify and abstract this, I'm thinking it might be better to default to polite and allow them to use an attribute to make them assertive as needed. Does that feel reasonable?

In the scenario where users have alerts/toasts auto-focused, I'm not sure if we allow for that in the component or why we would want that, but if that did happen it would then cause duplicate announcements (from the live region and then the focused element). We would not want duplicate announcements so we would need a way to turn them off in this scenario I think.

We're not currently doing this, but I guess people could slot in some buttons and force focus on their own. In your opinion, could we be clever about it and listen to focusin/focusout and turn it off based on that? Or do you think this will come back to bite us later on?

I'm trying to avoid putting more work on end users, because that tends to lead to a worse experience and folks not doing the right things at the right times. If we can be smart about these things, users won't have to bear those burdens.

There could be a potential WCAG 2.2.1 Violation in how you hide toasts after a few seconds.

Got it. We only allow this when toasts don't require acknowledgement. This is called out in the docs. Should we change anything here, or is that OK for this specific use case?

@claviska claviska added a11y Anything relating to accessibility. and removed bug Things that aren't working right in the library. labels Aug 11, 2023
@claviska claviska added this to the 3.0 (future) milestone Oct 26, 2023
@garyb1
Copy link
Author

garyb1 commented Dec 4, 2023

Hey @claviska
My apologies for the not responding over the past few months. Only getting back to things over the last few weeks.

Alerts that live inline, but only show at certain moments? (e.g. after an invalid form submission)

I am not sure how to answer this to be honest. To me this kind of feels like it might fall into more of an error summary and inline validation type of component. Kind of like what the GDS UK have done, which tends to perform good. This would also include inline validation messages for each form element, linked with aria-describedby. See an example form for GOV UK Account Creation. There is also a backlog/discussion issue for the error summary componenton Github. Would love your thoughts on that.

Joe Lanman from the GDS UK team mentioned that numerous projects across various government teams exist, but they do not all get built the same.

Alerts that live as toasts (using the toast stack)

Hmmm, yeah this is tricky. What if the stack container was present in the DOM on page load? Or a recommendation that it should be?

Some interesting notes I found on the salesforce alert component:

Toast should contain role="alert" on the container to signal to assistive technology that they require the user’s attention.
When the design uses multiple toasts simultaneously, set the role to role="status". Historically, toasts would use the role of alert, but because you can invoke multiple toasts, assertive alerts would override previous toasts in the screen reader's speech queue. The role of status is a polite live region, which does not clear the queue, reducing the risk of a missed toast message.

I believe if you fire multiple role="alert" messages at the same time can cause JAWS to cut itself off and only read one message, rather than queueing the messages, hence why they use role="status" for multiple alerts.

We only allow this when toasts don't require acknowledgement. This is called out in the docs. Should we change anything here, or is that OK for this specific use case?

I do think this would require an update to the docs to mention the potential violations with doing this. If you follow the pattern where they alerts automatically dismiss (go away) after a few seconds, then you are in violation of 2.2.1. In the docs under duration you have "This is useful for alerts that don’t require acknowledgement". It should not matter if the toast requires acknowledgment or not, if they auto-dismiss they are in violation of that success criterion.

There is a lot to digest here, but happy to discuss with you on a call, or on discord if you prefer.
Thanks.

@claviska claviska removed this from the 3.0 (future) milestone Mar 13, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
a11y Anything relating to accessibility.
Projects
None yet
Development

No branches or pull requests

2 participants