floating-ui / floating-ui

A JavaScript library to position floating elements and create interactions for them.
https://floating-ui.com
MIT License
29.93k stars 1.6k forks source link

useHover sets focus on reference, causing focus indicator to appear #1999

Closed mihkeleidast closed 1 year ago

mihkeleidast commented 1 year ago

Reproduction: https://codesandbox.io/s/cool-framework-yzkhwh?file=/src/DropdownMenu.tsx

Video just in case: https://user-images.githubusercontent.com/1892091/205591138-78b7eaa4-1cfa-4c7d-8722-1c08acfda334.mp4

In the video, in the beginning hovering the reference button works as expected, e.g. there is no visible focus indicator. Once I tab to the button at least once and close the menu, after that when hovering the button the focus indicator is shown.

Note that sometimes it does not even need the tabbing, it just shows the focus indicator when hovering.

This also does not seem to be related to the use of useFocus hook, i.e. if I only use useHover, it still behaves like this.

atomiks commented 1 year ago

Try with these props instead:

<FloatingFocusManager
  context={context}
  modal={false}
  initialFocus={-1}

I also updated the dropdown menu example in general (on the docs) which works much better

mihkeleidast commented 1 year ago

It sometimes work better, but is still flaky, I can for example sometimes unhover the reference element, which does not hide the floating element, and still shows the focus outline:

image

https://codesandbox.io/s/reverent-dream-uwttqe?file=/src/DropdownMenu.tsx

atomiks commented 1 year ago

What type of component is this exactly? It doesn't follow WAI-ARIA authoring if it's trying to be a dropdown menu

mihkeleidast commented 1 year ago

Sorry, I haven't really focused on the semantics for these reproductions at all. It's a two-level navigation component. The "reference button" in my case is also a link. Hovering or focusing that shows a submenu. If you're familiar with how the WordPress admin menu works, I'm effectively trying to accomplish the collapsed state of that.

mihkeleidast commented 1 year ago

Perhaps a more realistic example based on my actual needs, I made the buttons links and added multiple of them, so now it should represents a navigation menu more: https://codesandbox.io/s/loving-aj-12v6cc?file=/src/DropdownMenu.tsx

atomiks commented 1 year ago

Got it, I'll have to investigate it

atomiks commented 1 year ago

Ok so this is really easy to fix, just set returnFocus={false} on the focus manager component. Since it's a list of nav links with non-modal focus, you don't need to return focus ever.

mihkeleidast commented 1 year ago

@atomiks one scenario when I do want to return focus is when the user has tabbed into the floating element and then closes it via ESC key. If I set returnFocus={false}, it loses the focus completely.

atomiks commented 1 year ago

Hmm true, I guess you'd need to conditionally set returnFocus based on some state then