Mount-gate DialogPortal for SSR safety

Defensive guard so the portal only mounts client-side. Radix's Portal is
already SSR-safe, so this is belt-and-suspenders.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019RCfQKfr64YJbFRs3Ai9v2
This commit is contained in:
Rami Bitar
2026-06-30 17:26:30 -04:00
parent 1037183769
commit b37625007b

View File

@@ -22,6 +22,15 @@ function DialogTrigger({
function DialogPortal({
...props
}: React.ComponentProps<typeof DialogPrimitive.Portal>) {
// Radix's Portal calls createPortal(children, document.body) as soon as it
// renders. During static prerendering there's no `document`, so gate the
// portal behind an effect that only runs in the browser. Closed dialogs
// render nothing on the server anyway, so there's no visual/hydration change.
const [mounted, setMounted] = React.useState(false)
React.useEffect(() => setMounted(true), [])
if (!mounted) return null
return <DialogPrimitive.Portal data-slot="dialog-portal" {...props} />
}