Components / Portal
Portal
Headless transport primitive. Teleports its slotted children into a target DOM node (default: document.body) — escapes clipping ancestors and stacking contexts. Used internally by modal, popover, tooltip, sheet, and toaster. Set `disabled` to render inline (SSR / no-portal mode).
layout v0.8.0
Playground
Examples
Inline (disabled)
<cg-portal disabled>
<cg-card padding="lg" style="max-width: 360px;">
<cg-stack direction="column" gap="sm">
<cg-text size="sm" weight="semibold">Portal disabled — rendering inline</cg-text>
<cg-text size="sm" muted>This card lives in the consumer's tree. Useful for SSR or when teleporting isn't needed.</cg-text>
</cg-stack>
</cg-card>
</cg-portal> Default (teleports to document.body)
document.body and won't appear inside this preview — open DevTools and inspect <body> to find it.<cg-text size="sm" muted>The card below teleports to <code>document.body</code> and won't appear inside this preview — open DevTools and inspect <code><body></code> to find it.</cg-text>
<cg-portal>
<cg-card padding="lg" style="position:fixed;bottom:24px;right:24px;max-width:320px;z-index:9999;">
<cg-stack direction="column" gap="sm">
<cg-text size="sm" weight="semibold">Teleported to body</cg-text>
<cg-text size="sm" muted>Look at the bottom-right corner of the page.</cg-text>
</cg-stack>
</cg-card>
</cg-portal> Modal pattern (used internally by cg-modal)
<cg-portal disabled>
<cg-card padding="lg" style="max-width: 480px;">
<cg-stack direction="column" gap="md">
<cg-text size="md" weight="semibold">Confirm action</cg-text>
<cg-text size="sm" muted>cg-modal, cg-sheet, cg-popover and cg-tooltip all wrap their content in cg-portal so they can escape their parent's overflow and stacking contexts.</cg-text>
<cg-stack direction="row" gap="sm" justify="end">
<cg-button variant="tertiary">Cancel</cg-button>
<cg-button variant="primary">Confirm</cg-button>
</cg-stack>
</cg-stack>
</cg-card>
</cg-portal> Import
import { CgPortal } from '@cognivo/components'; // Or tree-shake: import '@cognivo/components/cg-portal'; Per-component imports ship only that component (~8 kB gzip).
API Reference
| Prop | Type | Default | Description |
|---|---|---|---|
target | string | HTMLElement | "" | CSS selector or HTMLElement reference. Empty string falls back to document.body. |
disabled | boolean | false | When true, children render in place instead of teleporting |
Events
| Event | Detail | Description |
|---|---|---|
cg-portal-mount | { container: HTMLElement } | Children have been teleported to the target |
cg-portal-unmount | none | Children have been returned to the host (target change, disable, or disconnect) |