Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Improve outside click on Safari iOS (#1712)
* ensure outside click works on Safari in iOS When tapping on an element that is not clickable (like a div), then the `click` and `mousedown` events will not reach the `window.addEventListener('click')` listeners. The only event that does that could be interesting for us is the `pointerdown` event. The issue with this one is that we then run into the big issue we ran in a few months ago where clicks on a scrollbar *also* fired while a click doesn't. This issue was not an issue in React land, the `window.addEventListener('click')` was fired even when tapping on a `div`. This was very very confusing, but we think this is because of the syntethic event system, where the event listener is added to the root of your application (E.g.: #app) and React manually bubbles the events. Because this is done manually, it *does* reach the window as well. The confusing part is, how does React convert a `pointerdown` event to a `mousedown` and `click`. There is no code for that in their codebase? Turns out they don't, and turns out the events **do** bubble, but up until the `document`, not the `window`. But since they are manually bubbling events it all makes sense. So the solution? Let's switch from `window` to `document`... * update Dialog example to use DialogPanel * update changelog
- Loading branch information
1 parent
5af3bd4
commit b2c4023
Showing
7 changed files
with
50 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
20 changes: 20 additions & 0 deletions
20
packages/@headlessui-react/src/hooks/use-document-event.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import { useEffect } from 'react' | ||
|
||
import { useLatestValue } from './use-latest-value' | ||
|
||
export function useDocumentEvent<TType extends keyof DocumentEventMap>( | ||
type: TType, | ||
listener: (ev: DocumentEventMap[TType]) => any, | ||
options?: boolean | AddEventListenerOptions | ||
) { | ||
let listenerRef = useLatestValue(listener) | ||
|
||
useEffect(() => { | ||
function handler(event: DocumentEventMap[TType]) { | ||
listenerRef.current(event) | ||
} | ||
|
||
document.addEventListener(type, handler, options) | ||
return () => document.removeEventListener(type, handler, options) | ||
}, [type, options]) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import { watchEffect } from 'vue' | ||
import { isServer } from '../utils/ssr' | ||
|
||
export function useDocumentEvent<TType extends keyof DocumentEventMap>( | ||
type: TType, | ||
listener: (this: Document, ev: DocumentEventMap[TType]) => any, | ||
options?: boolean | AddEventListenerOptions | ||
) { | ||
if (isServer) return | ||
|
||
watchEffect((onInvalidate) => { | ||
document.addEventListener(type, listener, options) | ||
onInvalidate(() => document.removeEventListener(type, listener, options)) | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters