diff --git a/packages/@headlessui-react/src/components/dialog/dialog.tsx b/packages/@headlessui-react/src/components/dialog/dialog.tsx index 4f3d0ed6ff..351c28ad25 100644 --- a/packages/@headlessui-react/src/components/dialog/dialog.tsx +++ b/packages/@headlessui-react/src/components/dialog/dialog.tsx @@ -198,14 +198,14 @@ let DialogRoot = forwardRefWithAs(function Dialog< useOutsideClick( () => { // Third party roots - let rootContainers = Array.from(ownerDocument?.querySelectorAll('body > *') ?? []).filter( - (container) => { - if (!(container instanceof HTMLElement)) return false // Skip non-HTMLElements - if (container.contains(mainTreeNode.current)) return false // Skip if it is the main app - if (state.panelRef.current && container.contains(state.panelRef.current)) return false - return true // Keep - } - ) + let rootContainers = Array.from( + ownerDocument?.querySelectorAll('body > *, [data-headlessui-portal]') ?? [] + ).filter((container) => { + if (!(container instanceof HTMLElement)) return false // Skip non-HTMLElements + if (container.contains(mainTreeNode.current)) return false // Skip if it is the main app + if (state.panelRef.current && container.contains(state.panelRef.current)) return false + return true // Keep + }) return [ ...rootContainers, diff --git a/packages/@headlessui-react/src/components/portal/portal.test.tsx b/packages/@headlessui-react/src/components/portal/portal.test.tsx index 6b21ea7a5c..d434dd6084 100644 --- a/packages/@headlessui-react/src/components/portal/portal.test.tsx +++ b/packages/@headlessui-react/src/components/portal/portal.test.tsx @@ -299,6 +299,6 @@ it('should be possible to force the Portal into a specific element using Portal. render() expect(document.body.innerHTML).toMatchInlineSnapshot( - `"
B
I am in the portal root
"` + `"
B
I am in the portal root
"` ) }) diff --git a/packages/@headlessui-react/src/components/portal/portal.tsx b/packages/@headlessui-react/src/components/portal/portal.tsx index c6b55d8171..86bdba171b 100644 --- a/packages/@headlessui-react/src/components/portal/portal.tsx +++ b/packages/@headlessui-react/src/components/portal/portal.tsx @@ -95,6 +95,7 @@ let PortalRoot = forwardRefWithAs(function Portal< // Element already exists in target, always calling target.appendChild(element) will cause a // brief unmount/remount. if (!target.contains(element)) { + element.setAttribute('data-headlessui-portal', '') target.appendChild(element) } diff --git a/packages/@headlessui-vue/src/components/dialog/dialog.ts b/packages/@headlessui-vue/src/components/dialog/dialog.ts index 217ea2f873..dd1b24c7f3 100644 --- a/packages/@headlessui-vue/src/components/dialog/dialog.ts +++ b/packages/@headlessui-vue/src/components/dialog/dialog.ts @@ -179,7 +179,7 @@ export let Dialog = defineComponent({ () => { // Third party roots let rootContainers = Array.from( - ownerDocument.value?.querySelectorAll('body > *') ?? [] + ownerDocument.value?.querySelectorAll('body > *, [data-headlessui-portal]') ?? [] ).filter((container) => { if (!(container instanceof HTMLElement)) return false // Skip non-HTMLElements if (container.contains(dom(mainTreeNode))) return false // Skip if it is the main app diff --git a/packages/@headlessui-vue/src/components/portal/portal.test.ts b/packages/@headlessui-vue/src/components/portal/portal.test.ts index e0baae06d0..266f3dc987 100644 --- a/packages/@headlessui-vue/src/components/portal/portal.test.ts +++ b/packages/@headlessui-vue/src/components/portal/portal.test.ts @@ -403,6 +403,6 @@ it('should be possible to force the Portal into a specific element using PortalG await new Promise(nextTick) expect(document.body.innerHTML).toMatchInlineSnapshot( - `"
B
"` + `"
B
"` ) }) diff --git a/packages/@headlessui-vue/src/components/portal/portal.ts b/packages/@headlessui-vue/src/components/portal/portal.ts index 3ee164d0bf..fc8e1aabe5 100644 --- a/packages/@headlessui-vue/src/components/portal/portal.ts +++ b/packages/@headlessui-vue/src/components/portal/portal.ts @@ -79,6 +79,7 @@ export let Portal = defineComponent({ let ourProps = { ref: element, + 'data-headlessui-portal': '', } return h(