diff --git a/packages/portal/src/index.tsx b/packages/portal/src/index.tsx index 9fe314242..2b4c5f166 100644 --- a/packages/portal/src/index.tsx +++ b/packages/portal/src/index.tsx @@ -20,7 +20,11 @@ import { createPortal } from "react-dom"; * * @see Docs https://reach.tech/portal#portal */ -const Portal: React.FC = ({ children, type = "reach-portal" }) => { +const Portal: React.FC = ({ + children, + type = "reach-portal", + containerRef, +}) => { let mountNode = React.useRef(null); let portalNode = React.useRef(null); let forceUpdate = useForceUpdate(); @@ -32,11 +36,12 @@ const Portal: React.FC = ({ children, type = "reach-portal" }) => { // In that case, it's important to append to the correct document element. const ownerDocument = mountNode.current!.ownerDocument; portalNode.current = ownerDocument?.createElement(type)!; - ownerDocument!.body.appendChild(portalNode.current); + const body = containerRef?.current || ownerDocument.body; + body.appendChild(portalNode.current); forceUpdate(); return () => { - if (portalNode.current && portalNode.current.ownerDocument) { - portalNode.current.ownerDocument.body.removeChild(portalNode.current); + if (portalNode.current && body) { + body.removeChild(portalNode.current); } }; }, [type, forceUpdate]); @@ -64,6 +69,12 @@ type PortalProps = { * @see Docs https://reach.tech/portal#portal-type */ type?: string; + /** + * Optional container ref to render the portal in. + * + * @see Docs https://reach.tech/portal#portal-containerRef + */ + containerRef?: React.RefObject; }; if (__DEV__) { diff --git a/website/src/pages/portal.mdx b/website/src/pages/portal.mdx index 160028568..e419935dc 100644 --- a/website/src/pages/portal.mdx +++ b/website/src/pages/portal.mdx @@ -62,9 +62,11 @@ Renders content inside of a portal at the end of the DOM tree. #### Portal Props -| Prop | Type | Required | -| ----------------------- | ---- | -------- | -| [`children`](#children) | node | true | +| Prop | Type | Required | +| ------------------------------- | ------ | -------- | +| [`children`](#children) | node | true | +| [`type`](#type) | string | false | +| [`containerRef`](#containerRef) | ref | false | ##### Portal children @@ -83,3 +85,9 @@ Any content you want to render inside of the portal. _Type_: `string` default: `reach-portal` The DOM element type to render. + +##### Portal containerRef + +_containerRef_: `ref` default: `document.body` + +Ref to the container in where to render the portal. If not set the portal will be appended to the body of the document.