DOCS
v0.4

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)
Portal disabled — rendering inline This card lives in the consumer's tree. Useful for SSR or when teleporting isn't needed.
<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)
The card below teleports to document.body and won't appear inside this preview — open DevTools and inspect <body> to find it. Teleported to body Look at the bottom-right corner of the page.
<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>&lt;body&gt;</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)
Confirm action 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. Cancel Confirm
<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

PropTypeDefaultDescription
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

EventDetailDescription
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)