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

[Bug]: MenuItem / MenuList forcefully steals focus when hovered over with no ability to override behavior. #33818

Open
2 tasks done
lekevin-microsoft opened this issue Feb 11, 2025 · 3 comments

Comments

@lekevin-microsoft
Copy link

lekevin-microsoft commented Feb 11, 2025

Component

MenuList

Package version

9.55.1

React version

18.2.0

Environment

(Having trouble obtaining this, apologies. Using codespaces and unable to npm login to properly grab that command.)

Current Behavior

I'm working with FluentUI's v9 <Menu> component and creating a dropdown where there is an input box followed by <MenuItem>s after it:

Image

For this bug report, that top component is just a simple <Input> component (it doesn't quite matter what component, any input component will do) and the rest of the items are regular <MenuItem>s.

I'm seeing an issue where when a user has focus within the input box, if they hover over any of the <MenuItem>s then focus will immediately jump to the menu item. This is particularly unwanted behavior as input boxes can have lots of ongoing text, and when focus is reset to a menu item, pressing keys like "r" will trigger certain hotkeys (e.g. "Reload the window") which is particularly unwanted.

Image

Of note, this is the exact same issue that was fixed back in 2021 with ContextualMenu via this ticket: Ticket #20552. The fix here was that ContextualMenu has a delayUpdateFocusOnHover prop added that wasn't quite working, which was fixed from that ticket (PR here).

I am looking for an ask to have it implemented in or a similar mechanism such that a user can opt in or out of the functionality that on-hover for MenuItems will automatically focus.

The code that is causing this auto-focus is here:

Image

From useMenuItem.tsx on line 77. I've tested locally that when this block of code is commented out, the behavior is resolved and focus is no longer stolen away.

Expected Behavior

The expected behavior is that hovering over a menu item does not steal away focus from another active menu item. In this case, a user should be able to continue typing in the Input component while moving the mouse around their screen, without worry that focus would be stolen and any subsequent button presses would trigger browser hotkeys.

Perhaps something similar to Ticket #20552., where a property delayUpdateFocusOnHover is added?

I was able to confirm locally that when commenting out the onMouseMove from useMenuItem.tsx on line 77, the issue is resolved. Perhaps we can introduce a new property to MenuItem or MenuList such that, when this property is true, focus is not automatically triggered on mouse move.

A possibly easier solution that doesn't introduce a new property would be to simply reorder a few lines such that the user has ability to preventDefault() the behavior.

As it stands now, the code is like so:

          onMouseMove: useEventCallback(event => {
            if (event.currentTarget.ownerDocument.activeElement !== event.currentTarget) {
              innerRef.current?.focus();
            }

            props.onMouseMove?.(event);
          }),

props.onMouseMove() is called after the focus() call, so it's too late to do anything. A way to fix this would be:

          onMouseMove: useEventCallback(event => {
            props.onMouseMove?.(event);  // Move this to be the first call

            if (!event.isDefaultPrevented() && // First call `isDefaultPrevented()` check
                 event.currentTarget.ownerDocument.activeElement !== event.currentTarget) {
              innerRef.current?.focus();
            }
          }),

Reproduction

https://stackblitz.com/edit/vprprnxa?file=src%2Fexample.tsx

Steps to reproduce

  1. Click on "Toggle Menu" in the Stackblitz
  2. Click into the Input component (first one) in the dropdown
  3. Begin typing the word "test"
  4. After the letter 's', move your mouse to any other menu item within the dropdown like "New" or "New Window"
  5. Observe that focus is lost, and that if you press that final letter 't' in "test", you will invoke the browser's default behavior which is opening a new tab.

Are you reporting an Accessibility issue?

None

Suggested severity

High - No workaround

Products/sites affected

Outlook Web, New Outlook for Windows

Are you willing to submit a PR to fix?

Yes, PR created.

Validations

  • Check that there isn't already an issue that reports the same bug to avoid creating a duplicate.
  • The provided reproduction is a minimal reproducible example of the bug.
@lekevin-microsoft
Copy link
Author

I've created a PR here that implements the lighter-weight option of rearranging when focus() is called and when props.onMouseMove() is called: #33836.

@ling1726
Copy link
Member

My thought on this kind of UI patterns is rather if it's not just a combobox with a different design (no popover just static items)

Is there any advantage to using a menu over an aria-activedescendant implementation apart from the fact that we do not have it yet?

@CampbellOwen
Copy link
Contributor

Assigning to you @ling1726 based on your discussion here and in the PR

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants