Skip to content

Commit

Permalink
ensure outside click properly works with Poratl components
Browse files Browse the repository at this point in the history
Usually this works out of the box, however our Portal components will
render inside the Dialog component "root" to ensure that it is inside
the non-inert tree and is inside the Dialog visually.

This means that the Portal is not in a separate container and
technically outside of the `Dialog.Panel` which means that it will close
when you click on a non-interactive item inside that Portal...

This fixes that and allows all Portal components.
  • Loading branch information
RobinMalfait committed Jun 3, 2022
1 parent 7acaf08 commit b9c60fd
Show file tree
Hide file tree
Showing 6 changed files with 13 additions and 11 deletions.
16 changes: 8 additions & 8 deletions packages/@headlessui-react/src/components/dialog/dialog.tsx
Expand Up @@ -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,
Expand Down
Expand Up @@ -299,6 +299,6 @@ it('should be possible to force the Portal into a specific element using Portal.
render(<Example />)

expect(document.body.innerHTML).toMatchInlineSnapshot(
`"<div><main><aside id=\\"group-1\\">A<div>Next to A</div></aside><section id=\\"group-2\\"><span>B</span></section></main></div><div id=\\"headlessui-portal-root\\"><div>I am in the portal root</div></div>"`
`"<div><main><aside id=\\"group-1\\">A<div data-headlessui-portal=\\"\\">Next to A</div></aside><section id=\\"group-2\\"><span>B</span></section></main></div><div id=\\"headlessui-portal-root\\"><div data-headlessui-portal=\\"\\">I am in the portal root</div></div>"`
)
})
Expand Up @@ -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)
}

Expand Down
2 changes: 1 addition & 1 deletion packages/@headlessui-vue/src/components/dialog/dialog.ts
Expand Up @@ -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
Expand Down
Expand Up @@ -403,6 +403,6 @@ it('should be possible to force the Portal into a specific element using PortalG
await new Promise<void>(nextTick)

expect(document.body.innerHTML).toMatchInlineSnapshot(
`"<div><div><div data-v-app=\\"\\"><main><aside id=\\"group-1\\">A<div>Next to A</div></aside><section id=\\"group-2\\"><span>B</span></section><!--teleport start--><!--teleport end--></main></div></div></div>"`
`"<div><div><div data-v-app=\\"\\"><main><aside id=\\"group-1\\">A<div data-headlessui-portal=\\"\\">Next to A</div></aside><section id=\\"group-2\\"><span>B</span></section><!--teleport start--><!--teleport end--></main></div></div></div>"`
)
})
1 change: 1 addition & 0 deletions packages/@headlessui-vue/src/components/portal/portal.ts
Expand Up @@ -79,6 +79,7 @@ export let Portal = defineComponent({

let ourProps = {
ref: element,
'data-headlessui-portal': '',
}

return h(
Expand Down

0 comments on commit b9c60fd

Please sign in to comment.