Portal
Renders its children into document.body (or a container you choose)
instead of where the component sits in the tree. Content in a portal escapes
the overflow: hidden and stacking context of its ancestors, which is why
Modal, Drawer,
Menu, Popover and the
Toaster all render through it. Reach for it
directly when you build a custom overlay.
This box clips anything that overflows it. The card renders into the document body, so the clipping never reaches it.
"use client";
import { useState } from "react";
import { Box, Button, Card, Portal, Text, VStack } from "astralis-ui";
export function PortalDemo() {
const [open, setOpen] = useState(false);
return (
<Box overflow="hidden" p="4" rounded="lg" border="normal" borderColor="base" w="full" maxW="sm">
<VStack gap="3" alignItems="start">
<Text size="sm" color="muted">
This box clips anything that overflows it. The card renders into the document body,
so the clipping never reaches it.
</Text>
<Button size="sm" variant="outline" colorScheme="gray" onClick={() => setOpen((value) => !value)}>
{open ? "Hide the card" : "Show the card"}
</Button>
</VStack>
{open && (
<Portal>
<Card position="fixed" bottom="6" right="6" zIndex="high">
<Card.Body>
<Text size="sm">Rendered in document.body, outside the box.</Text>
</Card.Body>
</Card>
</Portal>
)}
</Box>
);
}Import#
import { Portal } from "astralis-ui";Usage#
Portalled content keeps its React context: events bubble to React parents and
the theme still applies, because Portal wraps its children in the library's
scoping class. The wrapper uses display: contents, so it never affects the
position of what you render.
Portal renders nothing on the server, and its children appear in the first client render, in the same commit as the component that opened them. That lets a positioned panel be measured as soon as it mounts.
<Portal container={document.getElementById("overlay-root") ?? undefined}>
<Backdrop />
</Portal>Props#
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | None | The content to render elsewhere. |
container | HTMLElement | document.body | The element to render into. |
Portal has no playground: it has no appearance of its own to configure.