Skip to content

fix(container-menu)!: improves logic for returning focus to trigger #659

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

Merged
merged 8 commits into from
Sep 25, 2024

Conversation

ze-flo
Copy link
Contributor

@ze-flo ze-flo commented Aug 30, 2024

Description

Improve the logic for returning focus to trigger. Adds optional restoreFocus prop to manager focus return to trigger.

💥 BREAKING CHANGE:

A new restoreFocus prop has been added. By default restoreFocus is true and will return the focus to the trigger on menu item selection, ESC / TAB key press, and clicking outside the menu dropdown. User who need to keep the dropdown open on selection must set restoreFocus={false} and manually handle the focus return.

Detail

  • Returning focus to trigger is now executed synchronously before calling the onChange callback. Now, when a menu item triggers Garden's Modal open, the focus will automatically be restored to the menu trigger after the modal has closed.
Screen.Recording.2024-08-29.at.10.19.34.AM.mov

Checklist

  • 🌐 demo is up-to-date (npm start)
  • 💂‍♂️ includes new unit tests
  • ♿ tested for WCAG 2.1 AA compliance
  • 📝 tested in Chrome, Firefox, Safari, and Edge

@ze-flo ze-flo requested a review from a team as a code owner August 30, 2024 20:39
@coveralls
Copy link

coveralls commented Aug 30, 2024

Coverage Status

coverage: 95.786% (+0.07%) from 95.716%
when pulling ac1f4b9 on ze-flo/menu-focus-fix
into ec77a9d on main.

geotrev
geotrev previously approved these changes Sep 4, 2024
Copy link
Contributor

@geotrev geotrev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like this approach. To reiterate what we discussed, we agreed that deferring trigger focus didn't make sense as consumers can't (and shouldn't) control this behavior anyway. It also leaves room for folks to refocus another element in response to menu closing without affecting screen reader announcements.

Copy link
Contributor

@geotrev geotrev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Quick status comment:

Flo and I met offline to go over the current approach and how we can maybe improve focus behavior between controlled and uncontrolled instances of isExpanded. Currently, this PR will only synchronously focus the button if isExpanded is uncontrolled.

Instead, we think there could be an opportunity here to give more direct trigger focus control through the use of a new parameter, which would also slightly change how Menu works in controlled scenarios by requiring consumers to focus their buttons when isExpanded is false.

To-be-discussed at tomorrow's meeting of the minds to get team consensus. 🧐

@@ -272,22 +278,32 @@ export const useMenu = <T extends HTMLElement = HTMLElement, M extends HTMLEleme
event.stopPropagation();

const changeType = StateChangeTypes.TriggerClick;
const nextIsExpanded = !controlledIsExpanded;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I actually think the code below reads better if we use !controlledIsExpanded. I confused nextisExpanded as referring to the next / nested menu state.

@geotrev geotrev dismissed their stale review September 11, 2024 22:07

awaiting consensus on new direction

@ze-flo ze-flo changed the title fix(container-menu): improves logic for returning focus to trigger fix!(container-menu): improves logic for returning focus to trigger Sep 13, 2024
Copy link
Contributor

@geotrev geotrev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I love how well the new direction cleaned up with the code!

Copy link
Member

@jzempel jzempel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There was also the general comment about pulling the #661 demo into [patterns]. But if we think the tests are sufficient here to cover that case, then I'm fine (and even more in favor) with that.

if (KEYS.ESCAPE === key) {
focusTriggerRef.current = true;
}
// TODO: Investigate why focus goes to body instead of next interactive element on TAB keydown. Meanwhile, returning focus to trigger.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What are the current results of this investigation?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The mystery prevails. 🤔

I verified that returnFocusToTrigger is only called once on TAB keypress. ✅

The browser first sets the activeElement to body. Pressing TAB once more sets the focus to the next interactive element. That implies the placement in the tab sequence isn't reset. I created a JIRA task to revisit.

@ze-flo ze-flo changed the title fix!(container-menu): improves logic for returning focus to trigger fix(container-menu)!: improves logic for returning focus to trigger Sep 25, 2024
@ze-flo ze-flo merged commit 93b6278 into main Sep 25, 2024
4 checks passed
@ze-flo ze-flo deleted the ze-flo/menu-focus-fix branch September 25, 2024 22:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

5 participants