-
-
Notifications
You must be signed in to change notification settings - Fork 32.5k
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
[Snackbar] Accessibility - Keyboard focus should move to the Snackbar when it opens #22354
Comments
We should be very careful with making this the default behavior. For UIs using the snackbar for notifications (possible displaying multiple) you don't want the Snackbar to steal focus. I don't think Snackbar should be used as an alertdialog due to their positioning. In the case of the Snackbar with an undo action it's probably better to add a keyboard shortcut. Otherwise it might be disruptive if you trigger an action and every time the focus is moved to an option "undo" element. So there's a lot of nuance to this component. We didn't do a good job making it accessible by default especially due to the poor naming and customization points without oversight. Some brainstorming on how to recommend better a11y (without having looked into prior art for accessible notifications/undo popups):
|
I didn't think of a scenario where Snackbar was used for notifications, I see your point. However, in the case of Snackbar appearing after a user interaction, I think focus moving to the Snackbar could still be a valid scenario. Even if we decide not to implement moving the focus to the Snackbar when it's been opened, in any case there should probably be better visual indications of where the focus is after closing a Snackbar (on https://material-ui.com/components/snackbars/#simple-snackbars, after you close the Snackbar you have no visual indicators as to where your focus is - it seems like focus is lost when the Snackbar is removed from the DOM).
Any chance you could expand on this? Our use case would be one such as showing an alert dialog as a toaster after a user interaction (say, clicking a button to submit a form and having a dismissible "Success!" toaster appear on screen).
I agree, maybe my ask for the focus should move automatically to the "X" button of the snackbar instead of the first interact-able element.
It's late in the day for me so you'll have to forgive me for not following this one 😂 - how would this work from a user perspective?
Portaling, if I understand correctly, would render the toaster in a different area of the DOM like in https://material-ui.com/components/portal/ - that seems reasonable but in that case I would definitely want to see focus moved to the toaster after a user interaction - otherwise I'm wondering would a keyboard-only/screenreader user have a hard time "finding" the snackbar on the page? @eps1lon I really appreciate your thoroughness on this! A11y is so subjective - it's hard to know exactly what the right approach is. |
That's not an alertdialog as it's defined in the ARIA authoring practices:
-- https://www.w3.org/TR/wai-aria-practices-1.1/#alertdialog ARIA is not as clear. A snackbar can definitely act as an alertdialog where you want the user to confirm but I don't believe this is the best UI for this type of notification due to its placement. Using it as an alertdialog is actually less accessible for sighted users I'd say.
Definitely. It's why having concrete examples is so important when filing issues. It also reveals problems with a component if it can be used for too many UI patterns. Then it fails to provide real value to developers if they have to customize it before it actually works. We already improved in that area by implementing a standalone Alert.
At the top of my had I can't recall any toast-like element that should steal focus. A popular use case where you have it as a confirmation with an action to undo can be accessible by providing a different shortcut to undo e.g
Basically something like |
It's probably worth revisiting what the Snackbar's intended use is: https://material.io/components/snackbars#usage When to useSnackbars communicate messages that are minimally interruptive and don’t require user action.
|
Thanks @mbrookes @eps1lon that all makes sense - I think Snackbar is the appropriate component for our "success" message use case but you're right, it doesn't need to get focus automatically because it doesn't require interaction from the user. |
@mbrookes So it would support the idea that the Snackbar should be portal, so it can't be reached with Tab? To be fair, I believe that most applications use the Snackbar with a global dispatch system anyway (e.g. redux). So in practice, the Snackbar is most likely not reachable with Tab unless reaching the end (most likely) or the beginning of the page (depending on how it was set up). I have been advocating for something similar in #21053 (comment). Regarding:
Should it be deferred to the userland? Not something Material-UI handles in the core?
As focus moves back to the body? What other behavior did you envision? |
One that doesn't interrupt the current workflow. |
I'm not so sure... User interaction is optional, but there may be an action the user wants to take, such as "Undo". What does a keyboard user do in that scenario if they can't focus the button? |
Have a global shortcut which has a faster workflow for power users since you don't have to TAB and ENTER just hit a single combination:
It's really hard to discuss this without user testing. It isn't clear to me if putting it in tab order isn't disrupting or if users even understand what's going on if they tab into an "undo" action that wasn't there before. |
Part of the problem is also that the Material UI snackbars read the buttons when using a screen reader unlike the Material IO demo (https://material-components.github.io/material-components-web-catalog/#/component/snackbar). If the component is changed to not read the buttons and you include the shortcut text for screen readers only as mentioned above then it would solve the problem. I also identified some issues with a variety of screen reader / browser combos that seem to be resolved if you move the role=alert to the text of the snackbar (#29080). |
One thing I want to note really quickly is that browsers do have an internal focus cursor that we don't have access to with DOM APIs and that may cause disorienting behavior with portals i.e. our current Snackbar implementation. Say you have a document with 3 Buttons: <button />
<button />
<button /> Now we tab to the second button ( <button />
-><button />
<button /> Now we remove <button />
->
<button /> If we TAB again, the focus cursor moves to the next element i.e. <button />
-><button /> So moving focus to the Snackbar may result in a focus cursor that is no longer in the list if the previously focus element is removed when the snackbar opens. For example, take list of TODO items with a remove action ( <ListItem>A</ListItem>
<ListItem>B</ListItem>
<ListItem>C</ListItem> We TAB to the second item: <ListItem>A</ListItem>
-><ListItem>B</ListItem>
<ListItem>C</ListItem> and remove it: <ListItem>A</ListItem>
->
<ListItem>C</ListItem> which prompts a Snackbar asking us to undo <ListItem>A</ListItem>
<ListItem>C</ListItem>
<Snackbar>
-> <Undo />
</Snackbar> So now we have to handle focus restoration depending on whether we undo or not. If we just blur the undo button we land at the end of document since this is were the undo button was located: <ListItem>A</ListItem>
<ListItem>C</ListItem>
-> I have a small codesandbox illustrating the issue: https://codesandbox.io/s/move-focus-to-snackbar-focus-cursor-issue-btsbv The only leverage we have is in the case of undo but the Snackbar would not be able to restore since the restored ListItem would be a new HTMLButtonElement. The correct solution would be to keep What my concern is that this behavior isn't trivial to implement and the problem itself is most likely not obvious to most people since it's "only" a keyboard related issues. We can avoid this footgun entirely if we don't move focus around and add an affordance to "undo" (or whatever action you have in your Snackbar) with a separate keyboard combination. Alternatively we hijack tabbing behavior enitrely and re-implement a focus cursor that considers the React tree not DOM tree. I hope this helps illustrating why moving focus to the Snackbar is potentially dangerous. If I left anything unclear, please comment on what's missing or unclear. |
Just noticed that Snackbar isn't portaled. So the problem doesn't exist right now. But there is considerable desire to allow for imperative toasts that would require a single Snackbar instance that will probably be portaled so we need to consider this in #18098. |
Note that you can already implement this behavior with <Snackbar
open={open}
onClose={handleClose}
message="Note archived"
action={<button autoFocus>UNDO</button>}
/>; Considering this behavior is already implementable and making this the default behavior is potentially interruptive, I'm closing this issue for now. I don't see how we can safely do the right thing automatically. What do we do with multiple actions? How do we restore focus if the element triggering the Snackbar got removed? It would help a lot if we could gather use cases where focus should be moved so that we may be able to create more specific components. I just don't see compelling evidence for moving focus into a generic "toast" component. |
Current Behavior 😯
When you activate a snackbar toast and the contents of the toast are announced to the user, the focus should also move to the toast. It seems like the focus is lost at the moment / it is unclear where exactly the keyboard focus is when the toast first opens. When the toast is closed, focus should return to the original element that opened the toast (if it is still present on the page).
Expected Behavior 🤔
When you activate a snackbar toast and the contents of the toast are announced to the user, the focus should also move to the first interact-able element of the toast (like the action or close buttons). When you close the toast, focus should return back to the element that opened the toast.
While there are no specific aria guidelines for toasts, a modal dialog is probably the closest example:
https://www.w3.org/TR/wai-aria-practices-1.1/examples/dialog-modal/alertdialog.html
We've also been given this feedback from our users.
Steps to Reproduce 🕹
Steps:
Context 🔦
Our keyboard-only users expect to be able to keep track of focus as they interact with elements that fire toasts.
Your Environment 🌎
The text was updated successfully, but these errors were encountered: