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

Return focus after dialogs close #11999

Merged
merged 6 commits into from
May 16, 2022
Merged

Return focus after dialogs close #11999

merged 6 commits into from
May 16, 2022

Conversation

steverep
Copy link
Member

Proposed change

Adds an event handler to return focus, where possible, to the button or control that opened the dialog. This is best practice for good accessibility. Here are some details on the implementation:

  • Finds and stores the active element and possibly dialog generically right before new dialog is shown
  • Data is stored in the module in tag dictionary same as created elements, and typing was added for better code quality
  • Handles the common special case where dialog is opened from a popup menu and returns focus to the trigger
  • Handles the replace situation for more info / entity settings
  • When dialog is opened from another dialog, focus method for mwc-dialog becomes the fallback in case of failure

Limitations

  1. Assumes the dialog fires the dialog-closed event. The majority of the 70+ dialogs do, but about 20 or so need to be updated in future changes.
  2. Assumes the element that opened the dialog is focusable, which is not always the case, but should be for keyboard accessibility (e.g. entity settings dialogs from configuration page and some more info dialogs from certain cards)

Type of change

  • Dependency upgrade
  • Bugfix (non-breaking change which fixes an issue)
  • New feature (thank you!)
  • Breaking change (fix/feature causing existing functionality to break)
  • Code quality improvements to existing code or addition of tests

Example configuration

Additional information

Checklist

  • The code change is tested and works locally.
  • There is no commented out code in this PR.
  • Tests have been added to verify that the new code works.

@steverep
Copy link
Member Author

Approvals is slower than usual... something I did? 😕 😄

@zsarnett
Copy link
Contributor

Bram is on Holiday 😄 I haven't been able to take a look yet.

@steverep
Copy link
Member Author

Ah I was wondering where he disappeared to. Okay thanks for the heads up.

@steverep
Copy link
Member Author

Any chance this can get a review in time for April's beta?

@bramkragten
Copy link
Member

I wonder if we need this change, as mwc-dialog should handle this (it does here I think? https://material-components.github.io/material-web/demos/dialog/)

I think the issue is the location in the DOM where we add the dialogs probably? They are in a different place in the DOM then the element that triggers it...

Would have to look in to that

@steverep
Copy link
Member Author

There's no code in mwc-dialog to handle returning focus. What OS/browser are you using on those demos? Focus is not put back on the trigger for me in Chrome or Firefox on Windows. It's just letting the browser handle it, which varies with browser. For example, Firefox always throws focus back to the top of the document, whereas Chrome tends to throw focus further down the page.

You could make the argument that mwc-dialog should have a default to return to the last focused element, but that will only ever handle a subset of cases. For example, mwc-dialog is never going to handle cases of replacing dialogs, trigger buttons becoming hidden, dialogs changing the DOM on close, etc. That logic needs to be specific to the app.

@bramkragten
Copy link
Member

I'm using Chrome on MacOS

@steverep
Copy link
Member Author

I'm using Chrome on MacOS

I don't have a Mac to reproduce that, but I'd be shocked if webkit was actively trying to return focus. It doesn't do that on iOS.

In any case,leaving it up to the browser isn't a good or even consistent approach as I said, and it's definitely not mwc-dialog code. All the component does is use PolymerLabs/blocking-elements to set the inert and aria-hidden="true" attributes outside the dialog when it's open, and removes them when it's closed. The only code regarding focus is to set it when the dialog is open, but only if the dialogInitialFocus attribute is set.

@steverep
Copy link
Member Author

PS - At least on that demo page, Chrome/blink on Windows seems to send focus to the next button rather than the one that opened the dialog, which is not the desired behavior.

@steverep
Copy link
Member Author

steverep commented Apr 3, 2022

@bramkragten so what's the review verdict here? Have I convinced you this code is needed independent of mwc-dialog in order to handle HA situations?

@bramkragten
Copy link
Member

Yeah, I'm seriously considering it, want to make it as easy as possible to maintain... Will get back to you this week.

@steverep
Copy link
Member Author

@bramkragten I don't understand the maintainability concerns. This is not particularly complicated code. Of course I'm open to review suggestions.

@zsarnett can you add your review cents here?

@steverep
Copy link
Member Author

@balloob can you intercede here? I've commented in the past that HA does not prioritize accessibility and this PR lingering on without a review is an example. This implements simple focus management for dialogs - a fundamental piece of good keyboard accessibility.

@zsarnett
Copy link
Contributor

Please stop pinging developers. Bram advised he will be reviewing.

This is not about limiting Accessibility so don't try to pull on that string. This is about maintainability.

Normally your PRs go through without much question. This one adds a lot of code we have to maintain. Be patient

@steverep
Copy link
Member Author

Please stop pinging developers. Bram advised he will be reviewing.

That was weeks ago and much work has come and merged since. I don't see any problem with trying to call attention and start a discussion with the project's lead on prioritizing accessibility. It was not meant to offend anyone.

This is not about limiting Accessibility so don't try to pull on that string. This is about maintainability.

I didn't accuse the project of limiting accessibility. I accused the project of not prioritizing it. There's a huge difference. If there is a way to make it more maintainable, then review and I'd be happy to implement it. No one has done that.

Normally your PRs go through without much question. This one adds a lot of code we have to maintain. Be patient

Please don't pretend like this is an exorbitant amount of code. Again, many more lines have come and merged since. And, just as food for thought, do you have any idea how often people with disabilities are told to be patient when trying to resolve accessibility or accommodation issues? It's not about patience - it's just about treating those issues with the priority they deserve.

bramkragten
bramkragten previously approved these changes Apr 25, 2022
@steverep steverep requested a review from bramkragten May 2, 2022 18:30
The closed targets are now just a set based on a search for the active element and flagged ancestors, and no details of components are needed outside their constructor:
- Revert previous changes to deepActiveElement
- Add new utility to find flagged ancestors
- Flag certain components as safe focus targets
- Await next paint instead of just underlay dialog to be more robust
@steverep steverep requested a review from bramkragten May 15, 2022 01:32
@steverep
Copy link
Member Author

@bramkragten this is ready for another look. I like this version better and I think it settles all your issues.

@bramkragten
Copy link
Member

Looks a lot better 👍

@steverep steverep requested a review from bramkragten May 16, 2022 14:38
@bramkragten bramkragten merged commit ae2d48f into home-assistant:dev May 16, 2022
@steverep steverep deleted the closed-dialog-focus branch May 16, 2022 16:51
@github-actions github-actions bot locked and limited conversation to collaborators May 17, 2022
@steverep steverep linked an issue Aug 13, 2022 that may be closed by this pull request
3 tasks
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Modal dialogs need keyboard focus management
4 participants