Files
my-website-v2/frontend/islands/portal.tsx

39 lines
1.0 KiB
TypeScript
Raw Normal View History

import { useEffect, useState } from "preact/hooks";
import { createPortal } from "preact/compat";
import type { ComponentChildren } from "preact";
type PortalProps = {
into?: string | HTMLElement;
children: ComponentChildren;
};
export function Portal({ into = "body", children }: PortalProps) {
const [host, setHost] = useState<HTMLElement | null>(null);
useEffect(() => {
if (typeof document === "undefined") return;
let target: HTMLElement | null = null;
if (typeof into === "string") {
target = into === "body" ? document.body : document.querySelector(into);
} else {
target = into;
}
if (!target) target = document.body;
const wrapper = document.createElement("div");
wrapper.className = "preact-portal-root";
target.appendChild(wrapper);
setHost(wrapper);
return () => {
if (wrapper.parentNode) wrapper.parentNode.removeChild(wrapper);
setHost(null);
};
}, [into]);
if (!host) return null;
return createPortal(children, host);
}