diff --git a/packages/react/README.md b/packages/react/README.md index 1443939b..a4c34360 100644 --- a/packages/react/README.md +++ b/packages/react/README.md @@ -35,13 +35,14 @@ Then in your root route/layout, import `ThemeProvider` and CSS ```TSX // layout.tsx -import { ThemeProvider } from '@interchain-ui/react'; +import { ThemeProvider, OverlaysManager } from '@interchain-ui/react'; import '@interchain-ui/react/styles'; export function RootLayout(props: LayoutProps) { return ( {props.children} + ) } diff --git a/packages/react/scaffolds/chain-swap-combobox/chain-swap-combobox.tsx b/packages/react/scaffolds/chain-swap-combobox/chain-swap-combobox.tsx index 9a45ed1e..0f47d378 100644 --- a/packages/react/scaffolds/chain-swap-combobox/chain-swap-combobox.tsx +++ b/packages/react/scaffolds/chain-swap-combobox/chain-swap-combobox.tsx @@ -26,6 +26,7 @@ import type { ChainListItemProps } from "@/ui/chain-list-item/chain-list-item.ty import type { Sprinkles } from "@/styles/rainbow-sprinkles.css"; import { overlays } from "@/ui/overlays-manager/overlays"; import useTheme from "@/ui/hooks/use-theme"; +import { getOwnerDocument } from "@/helpers/platform"; interface ItemProps { isActive: boolean; @@ -211,8 +212,12 @@ export default function ChainSwapCombobox(props: ChainSwapComboboxProps) { if (props.rootNode) { return setMountRoot(props.rootNode); } + if (!containerRef.current) return; - setMountRoot(overlays.getOrCreateOverlayRoot(containerRef.current)); + const ownerDocument = getOwnerDocument(containerRef.current); + if (!ownerDocument) return; + + setMountRoot(overlays.getOrCreateOverlayRoot(ownerDocument)); }, []); return ( diff --git a/src/helpers/platform.ts b/src/helpers/platform.ts index cd2576e4..80b7283a 100644 --- a/src/helpers/platform.ts +++ b/src/helpers/platform.ts @@ -42,3 +42,7 @@ export function closestBodyElement(node: HTMLElement) { } return null; } + +export function getOwnerDocument(node: HTMLElement) { + return node.ownerDocument; +} diff --git a/src/ui/overlays-manager/overlays.tsx b/src/ui/overlays-manager/overlays.tsx index aa5657a5..fd6700af 100644 --- a/src/ui/overlays-manager/overlays.tsx +++ b/src/ui/overlays-manager/overlays.tsx @@ -6,6 +6,10 @@ class Overlays { private constructor() {} + private static isBrowser(): boolean { + return typeof window !== "undefined"; + } + public static getInstance(): Overlays { if (!Overlays.instance) { Overlays.instance = new Overlays(); @@ -13,24 +17,25 @@ class Overlays { return Overlays.instance; } - public getOrCreateOverlayRoot(ownerDocument: Document): HTMLElement { + public getOrCreateOverlayRoot(ownerDocument: Document): HTMLElement | null { + if (!Overlays.isBrowser()) { + return null; + } + if (!this.overlayRoots.has(ownerDocument)) { const root = ownerDocument.createElement("div"); root.id = OVERLAYS_MANAGER_ID; - // root.style.position = "fixed"; - // root.style.top = "0"; - // root.style.left = "0"; - // root.style.width = "100%"; - // root.style.height = "100%"; - // root.style.pointerEvents = "none"; - // root.style.zIndex = "1000"; ownerDocument.body.appendChild(root); this.overlayRoots.set(ownerDocument, root); } - return this.overlayRoots.get(ownerDocument)!; + return this.overlayRoots.get(ownerDocument) || null; } - public cleanup() { + public cleanup(): void { + if (!Overlays.isBrowser()) { + return; + } + this.overlayRoots.forEach((root, doc) => { doc.body.removeChild(root); });