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

Improve "outside click" behaviour in combination with 3rd party libraries #2572

Merged
merged 4 commits into from Jul 3, 2023

Conversation

RobinMalfait
Copy link
Collaborator

@RobinMalfait RobinMalfait commented Jul 3, 2023

This PR improves the outside click behaviour when using our components in combination with 3rd party libraries. It also improves the outside click behaviour on touch devices.

We already use some logic to try and capture the target element outside of the main click listener. We do this by listening to a mousedown on the document while using the capture phase (instead of the bubble phase). Some 3rd party tools already use en event.preventDefault() in these scenarios.

To try and solve this, we will also listen for pointerdown events to capture the target element instead of only relying on the mousedown event. We can't just switch to pointerdown alone because those events aren't available on older versions of iOS for example.

Another small improvement is to also listen for touchend events. This will also be triggered on mobile devices which also improves the "outside click" behaviour in case the mousedown event is using e.preventDefault().

Fixes: #2564

This is necessary for calculating the target where the focus will
eventually move to. Some other libraries will use an
`event.preventDefault()` and if we are not listening for all "down"
events then we might not capture the necessary target.

We already tried to ensure this was always captured by using the
`capture` phase of the event but that's not enough.

This change won't be enough on its own, but this will improve the
experience with certain 3rd party libraries already.
@vercel
Copy link

vercel bot commented Jul 3, 2023

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
headlessui-react ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jul 3, 2023 2:17pm
headlessui-vue ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jul 3, 2023 2:17pm

@TomKremer
Copy link

TomKremer commented Jan 7, 2024

Hey Robin. I was on 1.7.13 (vue) before and now I have a bug with 1.7.16. I have multiple slide-overs, two Dialogs to be specific. When I touch/click in the last opened, the first one gets closed. Going back to 1.7.13 for now but anyhow I have to say my thanks for this awesome library. It saved me ton of work and I love it.
Edit: just saw #2876 which seems to be the same issue. I will try nesting the components.

RobinMalfait added a commit that referenced this pull request Jan 9, 2024
When using a `Dialog`, we should prevent the default behaviour of the
event that triggered the "close" in the `useOutsideClick` call.

We recently made improvements to improve outside click behaviour on
touch devices (#2572) but
due to the `touchend` event, the touch is still forwarded and therefore
a potential button _behind_ the "backdrop" will also be clicked. This is
not what we want.

Added the `event.preventDefault()` for the Dialog specifically because
there are other places where we use `useOutsideClick` and where we _do_
want the behaviour where the click just continues. A concrete example of
this is 2 `Menu`'s next to eachother where you open the first one, and
then click on the second one. This should close first one (outside
click) and open the second one (by not preventing the event)
RobinMalfait added a commit that referenced this pull request Jan 9, 2024
…2919)

* use `event.preventDefault()` in the `useOutsideClick` on Dialog's

When using a `Dialog`, we should prevent the default behaviour of the
event that triggered the "close" in the `useOutsideClick` call.

We recently made improvements to improve outside click behaviour on
touch devices (#2572) but
due to the `touchend` event, the touch is still forwarded and therefore
a potential button _behind_ the "backdrop" will also be clicked. This is
not what we want.

Added the `event.preventDefault()` for the Dialog specifically because
there are other places where we use `useOutsideClick` and where we _do_
want the behaviour where the click just continues. A concrete example of
this is 2 `Menu`'s next to eachother where you open the first one, and
then click on the second one. This should close first one (outside
click) and open the second one (by not preventing the event)

* update changelog
RobinMalfait added a commit that referenced this pull request Apr 15, 2024
…2919)

* use `event.preventDefault()` in the `useOutsideClick` on Dialog's

When using a `Dialog`, we should prevent the default behaviour of the
event that triggered the "close" in the `useOutsideClick` call.

We recently made improvements to improve outside click behaviour on
touch devices (#2572) but
due to the `touchend` event, the touch is still forwarded and therefore
a potential button _behind_ the "backdrop" will also be clicked. This is
not what we want.

Added the `event.preventDefault()` for the Dialog specifically because
there are other places where we use `useOutsideClick` and where we _do_
want the behaviour where the click just continues. A concrete example of
this is 2 `Menu`'s next to eachother where you open the first one, and
then click on the second one. This should close first one (outside
click) and open the second one (by not preventing the event)

* update changelog
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 this pull request may close these issues.

useOutsideClick interoperability with libraries that use event.preventDefault
3 participants