diff --git a/packages/@headlessui-react/CHANGELOG.md b/packages/@headlessui-react/CHANGELOG.md index 15172d2a54..81a084ad23 100644 --- a/packages/@headlessui-react/CHANGELOG.md +++ b/packages/@headlessui-react/CHANGELOG.md @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fix focus styles showing up when using the mouse ([#2347](https://github.com/tailwindlabs/headlessui/pull/2347)) - Fix "Can't perform a React state update on an unmounted component." when using the `Transition` component ([#2374](https://github.com/tailwindlabs/headlessui/pull/2374)) +- Add `FocusTrap` event listeners once document has loaded ([#2389](https://github.com/tailwindlabs/headlessui/pull/2389)) ### Added diff --git a/packages/@headlessui-react/src/components/focus-trap/focus-trap.tsx b/packages/@headlessui-react/src/components/focus-trap/focus-trap.tsx index 7e4e5bc0bd..0ee2c70ce5 100644 --- a/packages/@headlessui-react/src/components/focus-trap/focus-trap.tsx +++ b/packages/@headlessui-react/src/components/focus-trap/focus-trap.tsx @@ -24,6 +24,7 @@ import { useEventListener } from '../../hooks/use-event-listener' import { microTask } from '../../utils/micro-task' import { useWatch } from '../../hooks/use-watch' import { useDisposables } from '../../hooks/use-disposables' +import { onDocumentReady } from '../../utils/document-ready' type Containers = // Lazy resolved containers @@ -211,7 +212,7 @@ export let FocusTrap = Object.assign(FocusTrapRoot, { // --- let history: HTMLElement[] = [] -if (typeof window !== 'undefined' && typeof document !== 'undefined') { +onDocumentReady(() => { function handle(e: Event) { if (!(e.target instanceof HTMLElement)) return if (e.target === document.body) return @@ -231,7 +232,7 @@ if (typeof window !== 'undefined' && typeof document !== 'undefined') { document.body.addEventListener('click', handle, { capture: true }) document.body.addEventListener('mousedown', handle, { capture: true }) document.body.addEventListener('focus', handle, { capture: true }) -} +}) function useRestoreElement(enabled: boolean = true) { let localHistory = useRef(history.slice()) diff --git a/packages/@headlessui-react/src/utils/document-ready.ts b/packages/@headlessui-react/src/utils/document-ready.ts new file mode 100644 index 0000000000..fe241140a2 --- /dev/null +++ b/packages/@headlessui-react/src/utils/document-ready.ts @@ -0,0 +1,12 @@ +export function onDocumentReady(cb: () => void) { + function check() { + if (document.readyState === 'loading') return + cb() + document.removeEventListener('DOMContentLoaded', check) + } + + if (typeof window !== 'undefined' && typeof document !== 'undefined') { + document.addEventListener('DOMContentLoaded', check) + check() + } +} diff --git a/packages/@headlessui-vue/CHANGELOG.md b/packages/@headlessui-vue/CHANGELOG.md index 9c65ee757f..5786acfb18 100644 --- a/packages/@headlessui-vue/CHANGELOG.md +++ b/packages/@headlessui-vue/CHANGELOG.md @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fix focus styles showing up when using the mouse ([#2347](https://github.com/tailwindlabs/headlessui/pull/2347)) - Disable `ComboboxInput` when its `Combobox` is disabled ([#2375](https://github.com/tailwindlabs/headlessui/pull/2375)) +- Add `FocusTrap` event listeners once document has loaded ([#2389](https://github.com/tailwindlabs/headlessui/pull/2389)) ### Added diff --git a/packages/@headlessui-vue/src/components/focus-trap/focus-trap.ts b/packages/@headlessui-vue/src/components/focus-trap/focus-trap.ts index 7fef0eceb2..434cfd89ac 100644 --- a/packages/@headlessui-vue/src/components/focus-trap/focus-trap.ts +++ b/packages/@headlessui-vue/src/components/focus-trap/focus-trap.ts @@ -22,6 +22,7 @@ import { useTabDirection, Direction as TabDirection } from '../../hooks/use-tab- import { getOwnerDocument } from '../../utils/owner' import { useEventListener } from '../../hooks/use-event-listener' import { microTask } from '../../utils/micro-task' +import { onDocumentReady } from '../../utils/document-ready' type Containers = // Lazy resolved containers @@ -209,7 +210,7 @@ export let FocusTrap = Object.assign( ) let history: HTMLElement[] = [] -if (typeof window !== 'undefined' && typeof document !== 'undefined') { +onDocumentReady(() => { function handle(e: Event) { if (!(e.target instanceof HTMLElement)) return if (e.target === document.body) return @@ -229,7 +230,7 @@ if (typeof window !== 'undefined' && typeof document !== 'undefined') { document.body.addEventListener('click', handle, { capture: true }) document.body.addEventListener('mousedown', handle, { capture: true }) document.body.addEventListener('focus', handle, { capture: true }) -} +}) function useRestoreElement(enabled: Ref) { let localHistory = ref(history.slice()) diff --git a/packages/@headlessui-vue/src/utils/document-ready.ts b/packages/@headlessui-vue/src/utils/document-ready.ts new file mode 100644 index 0000000000..fe241140a2 --- /dev/null +++ b/packages/@headlessui-vue/src/utils/document-ready.ts @@ -0,0 +1,12 @@ +export function onDocumentReady(cb: () => void) { + function check() { + if (document.readyState === 'loading') return + cb() + document.removeEventListener('DOMContentLoaded', check) + } + + if (typeof window !== 'undefined' && typeof document !== 'undefined') { + document.addEventListener('DOMContentLoaded', check) + check() + } +}