Skip to content

Commit 6743015

Browse files
committed
allow to pass in custom ownerDocument into the internal <Portal>
This allows us to use a custom `ownerDocument`. This is useful if a `<Menu>` is rendered in an `<iframe>`, then we can use the `ownerDocument` from the `<MenuButton>` to know where to render the `<MenuItems>` (when portalling)
1 parent d71fb9c commit 6743015

File tree

1 file changed

+8
-8
lines changed
  • packages/@headlessui-react/src/components/portal

1 file changed

+8
-8
lines changed

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

+8-8
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,10 @@ import type { Props } from '../../types'
2525
import { env } from '../../utils/env'
2626
import { forwardRefWithAs, useRender, type HasDisplayName, type RefProp } from '../../utils/render'
2727

28-
function usePortalTarget(ref: MutableRefObject<HTMLElement | null>): HTMLElement | null {
28+
function usePortalTarget(ownerDocument: Document | null): HTMLElement | null {
2929
let forceInRoot = usePortalRoot()
3030
let groupTarget = useContext(PortalGroupContext)
3131

32-
let ownerDocument = useOwnerDocument(ref)
33-
3432
let [target, setTarget] = useState(() => {
3533
// Group context is used, but still null
3634
if (!forceInRoot && groupTarget !== null) return groupTarget.current ?? null
@@ -77,22 +75,24 @@ export type PortalProps<TTag extends ElementType = typeof DEFAULT_PORTAL_TAG> =
7775
PortalPropsWeControl,
7876
{
7977
enabled?: boolean
78+
ownerDocument?: Document | null
8079
}
8180
>
8281

8382
let InternalPortalFn = forwardRefWithAs(function InternalPortalFn<
8483
TTag extends ElementType = typeof DEFAULT_PORTAL_TAG,
8584
>(props: PortalProps<TTag>, ref: Ref<HTMLElement>) {
86-
let theirProps = props
85+
let { ownerDocument: incomingOwnerDocument = null, ...theirProps } = props
8786
let internalPortalRootRef = useRef<HTMLElement | null>(null)
8887
let portalRef = useSyncRefs(
8988
optionalRef<(typeof internalPortalRootRef)['current']>((ref) => {
9089
internalPortalRootRef.current = ref
9190
}),
9291
ref
9392
)
94-
let ownerDocument = useOwnerDocument(internalPortalRootRef)
95-
let target = usePortalTarget(internalPortalRootRef)
93+
let defaultOwnerDocument = useOwnerDocument(internalPortalRootRef)
94+
let ownerDocument = incomingOwnerDocument ?? defaultOwnerDocument
95+
let target = usePortalTarget(ownerDocument)
9696
let [element] = useState<HTMLDivElement | null>(() =>
9797
env.isServer ? null : ownerDocument?.createElement('div') ?? null
9898
)
@@ -154,12 +154,12 @@ function PortalFn<TTag extends ElementType = typeof DEFAULT_PORTAL_TAG>(
154154
) {
155155
let portalRef = useSyncRefs(ref)
156156

157-
let { enabled = true, ...theirProps } = props
157+
let { enabled = true, ownerDocument, ...theirProps } = props
158158

159159
let render = useRender()
160160

161161
return enabled ? (
162-
<InternalPortalFn {...theirProps} ref={portalRef} />
162+
<InternalPortalFn {...theirProps} ownerDocument={ownerDocument} ref={portalRef} />
163163
) : (
164164
render({
165165
ourProps: { ref: portalRef },

0 commit comments

Comments
 (0)