Skip to content

Commit 9ecd8dd

Browse files
authored
Fix Dialog cleanup when the Dialog becomes hidden (#2303)
* use the Dialog's parent as the root for the Intersection observer We have some code that allows us to auto-close the dialog the moment it gets hidden. This is useful if you use a dialog for a mobile menu and you resizet he browser. If you wrap the dialog in a `md:hidden` then it auto closes. If we don't do this, then the dialog is still locking the scrolling, keeping the focus in the dialog, ... but it is not visible. To solve this we use an `IntersectionObserver` to verify that the `boundingClientRect` is "gone" (x = 0, y = 0, width = 0 and height = 0). However, the intersection observer is not always triggered. This happens if the main content is scrollable. Setting the `root` of the `IntersectionObserver` to the parent of the `Dialog` does seem to solve it. Not 100% sure what causes this behaviour exactly. * use a `ResizeObserver` instead of `IntersectionObserver` * implement a `ResizeObserver` for the tests * update changelog
1 parent d1ca3a9 commit 9ecd8dd

File tree

6 files changed

+10
-16
lines changed

6 files changed

+10
-16
lines changed

packages/@headlessui-react/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1616
- Ensure the main tree and parent `Dialog` components are marked as `inert` ([#2290](https://github.com/tailwindlabs/headlessui/pull/2290))
1717
- Fix nested `Popover` components not opening ([#2293](https://github.com/tailwindlabs/headlessui/pull/2293))
1818
- Make React types more compatible with other libraries ([#2282](https://github.com/tailwindlabs/headlessui/pull/2282))
19+
- Fix `Dialog` cleanup when the `Dialog` becomes hidden ([#2303](https://github.com/tailwindlabs/headlessui/pull/2303))
1920

2021
## [1.7.11] - 2023-02-15
2122

packages/@headlessui-react/src/components/dialog/dialog.test.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ import { OpenClosedProvider, State } from '../../internal/open-closed'
3030
jest.mock('../../hooks/use-id')
3131

3232
// @ts-expect-error
33-
global.IntersectionObserver = class FakeIntersectionObserver {
33+
global.ResizeObserver = class FakeResizeObserver {
3434
observe() {}
3535
disconnect() {}
3636
}

packages/@headlessui-react/src/components/dialog/dialog.tsx

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -309,14 +309,10 @@ function DialogFn<TTag extends ElementType = typeof DEFAULT_DIALOG_TAG>(
309309
if (dialogState !== DialogStates.Open) return
310310
if (!internalDialogRef.current) return
311311

312-
let observer = new IntersectionObserver((entries) => {
312+
let observer = new ResizeObserver((entries) => {
313313
for (let entry of entries) {
314-
if (
315-
entry.boundingClientRect.x === 0 &&
316-
entry.boundingClientRect.y === 0 &&
317-
entry.boundingClientRect.width === 0 &&
318-
entry.boundingClientRect.height === 0
319-
) {
314+
let rect = entry.target.getBoundingClientRect()
315+
if (rect.x === 0 && rect.y === 0 && rect.width === 0 && rect.height === 0) {
320316
close()
321317
}
322318
}

packages/@headlessui-vue/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1212
- Ensure the main tree and parent `Dialog` components are marked as `inert` ([#2290](https://github.com/tailwindlabs/headlessui/pull/2290))
1313
- Fix nested `Popover` components not opening ([#2293](https://github.com/tailwindlabs/headlessui/pull/2293))
1414
- Fix `change` event incorrectly getting called on `blur` ([#2296](https://github.com/tailwindlabs/headlessui/pull/2296))
15+
- Fix `Dialog` cleanup when the `Dialog` becomes hidden ([#2303](https://github.com/tailwindlabs/headlessui/pull/2303))
1516

1617
## [1.7.10] - 2023-02-15
1718

packages/@headlessui-vue/src/components/dialog/dialog.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ import { html } from '../../test-utils/html'
4444
import { useOpenClosedProvider, State } from '../../internal/open-closed'
4545

4646
// @ts-expect-error
47-
global.IntersectionObserver = class FakeIntersectionObserver {
47+
global.ResizeObserver = class FakeResizeObserver {
4848
observe() {}
4949
disconnect() {}
5050
}

packages/@headlessui-vue/src/components/dialog/dialog.ts

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -280,14 +280,10 @@ export let Dialog = defineComponent({
280280
let container = dom(internalDialogRef)
281281
if (!container) return
282282

283-
let observer = new IntersectionObserver((entries) => {
283+
let observer = new ResizeObserver((entries) => {
284284
for (let entry of entries) {
285-
if (
286-
entry.boundingClientRect.x === 0 &&
287-
entry.boundingClientRect.y === 0 &&
288-
entry.boundingClientRect.width === 0 &&
289-
entry.boundingClientRect.height === 0
290-
) {
285+
let rect = entry.target.getBoundingClientRect()
286+
if (rect.x === 0 && rect.y === 0 && rect.width === 0 && rect.height === 0) {
291287
api.close()
292288
}
293289
}

0 commit comments

Comments
 (0)