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) [React]: Focus trap doesn't keep focus when tabbing to element with tabIndex outside of the Dialog #1656

Closed
joshsmith opened this issue Jul 10, 2022 · 2 comments · Fixed by #2093
Assignees

Comments

@joshsmith
Copy link

What package within Headless UI are you using?

@headlessui/react

What version of that package are you using?

v1.6.6

What browser are you using?

Chrome

Reproduction URL

Minimum reproducible example on CodeSandbox

Describe your issue

The Transition component loses the focus trap when elements of Dialog contain a tabIndex.

Go to the CodeSandbox, click Open Me, tab through the buttons and see that I'm another button gains focus. This issue is not present if tabIndex is not present. If this is expected behavior, it seems to break the ability to define which elements are tabbed in order.

@RobinMalfait
Copy link
Member

Hey! Thank you for your bug report!
Much appreciated! 🙏

Just for future reference, this doesn't look like a Transition related issue but a Dialog/FocusTrap issue because if you remove the Transition altogether the issue is still there. Updated CodeSandbox: https://codesandbox.io/s/jolly-scott-zofw49?file=/src/App.js

@RobinMalfait RobinMalfait changed the title (bug) [React]: Transition loses focus trap when elements of Dialog contain tabIndex (bug) [React]: Focus trap doesn't keep focus when tabbing to element with tabIndex outside of the Dialog Aug 24, 2022
@RobinMalfait RobinMalfait self-assigned this Aug 30, 2022
RobinMalfait added a commit that referenced this issue Dec 14, 2022
This code will now ensure that we can't escape the FocusTrap if you use
`<tab>` and you happen to tab to an element outside of the FocusTrap
because the next item in line happens to be outside of the FocusTrap and
we never hit any of the focus guard elements.

How it works is as follows:

1. The `onBlur` is implemented on the `FocusTrap` itself, this will give
   us some information in the event itself.
   - `e.target` is the element that is being blurred (think of it as `from`)
   - `e.currentTarget` is the element with the event listener (the dialog)
   - `e.relatedTarget` is the element we are going to (think of it as `to`)
2. If the blur happened due to a `<tab>` or `<shift>+<tab>`, then we
   will move focus back inside the FocusTrap, and go from the `e.target`
   to the next or previous value.
3. If the blur happened programmatically (so no tab keys are involved,
   aka no direction is known), then the focus is restored to the
   `e.target` value.

Fixes: #1656
@RobinMalfait
Copy link
Member

Hey!

Sorry that this took a while... but this should be fixed by #2093, and will be available in the next release.

You can already try it (in a few minutes) using:

  • npm install @headlessui/react@insiders.
  • npm install @headlessui/vue@insiders.

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

Successfully merging a pull request may close this issue.

3 participants