Portal Component

A portal component for rendering content in an overlay, supporting fixed positions, anchored positioning, backdrop variants, and offset control.
import { Box, Portal, Text } from "@locus-ui/components";
<Portal.Root>  <Portal.Trigger>    <Box className="border" px="2" py="1">      <Text>Open Portal</Text>    </Box>  </Portal.Trigger>  <Portal.Backdrop variant="shadow" />  <Portal.Content>

Anatomy

Import the component and its parts:

Anatomy

import { Box, Portal, Text } from "@locus-ui/components";
<Portal.Root>  <Portal.Trigger />  <Portal.Backdrop />  <Portal.Content /></Portal.Root>

Examples

Positions

The position prop on Portal.Content controls where the content appears on screen. Available positions are tl, top, tr, left, center, right, bl, bottom, and br.

positions.tsx

import { Box, Portal, Text } from "@locus-ui/components";
const positions = ["tl", "top", "tr", "left", "center", "right", "bl", "bottom", "br"];
return positions.map((position) => (  <Portal.Root key={position}>    <Portal.Trigger>      <Box className="border" px="2" py="1">        <Text>{position.toUpperCase()}</Text>      </Box>    </Portal.Trigger>

Variants

The Portal.Backdrop component supports three variants: clear, shadow, and blurred.

variants.tsx

import { Box, Portal, Text } from "@locus-ui/components";
const variants = ["clear", "shadow", "blurred"];
return variants.map((variant) => (  <Portal.Root key={variant}>    <Portal.Trigger>      <Box className="border" px="2" py="1">        <Text>{variant.charAt(0).toUpperCase() + variant.slice(1)}</Text>      </Box>    </Portal.Trigger>

Anchor

When the anchored prop is set on Portal.Content, the content is positioned relative to the trigger element.

anchor.tsx

import { Box, Portal, Text } from "@locus-ui/components";
<Portal.Root>  <Portal.Trigger>    <Box className="border" px="2" py="1">      <Text>Anchor</Text>    </Box>  </Portal.Trigger>  <Portal.Backdrop />  <Portal.Content anchored side="bottom" align="end">

Anchor Positions

The side prop controls which side of the trigger the anchored content appears on: top, right, bottom, or left.

anchor-positions.tsx

import { Box, Portal, Text } from "@locus-ui/components";
const sides = ["top", "right", "bottom", "left"];
return sides.map((side) => (  <Portal.Root key={side}>    <Portal.Trigger>      <Box className="border" px="2" py="1">        <Text>{side.charAt(0).toUpperCase() + side.slice(1)}</Text>      </Box>    </Portal.Trigger>

Anchor Aligns

The align prop controls the alignment of the anchored content relative to the trigger: start, center, or end.

anchor-aligns.tsx

import { Box, Portal, Text } from "@locus-ui/components";
const aligns = ["start", "center", "end"];
return aligns.map((align) => (  <Portal.Root key={align}>    <Portal.Trigger>      <Box className="border" px="2" py="1">        <Text>{align.charAt(0).toUpperCase() + align.slice(1)}</Text>      </Box>    </Portal.Trigger>

Offset

Use sideOffset and alignOffset to fine-tune the position of anchored content.

offset.tsx

import { Box, Portal, Text } from "@locus-ui/components";
<Portal.Root>  <Portal.Trigger>    <Box className="border" px="2" py="1">      <Text>Side Offset</Text>    </Box>  </Portal.Trigger>  <Portal.Backdrop />  <Portal.Content anchored side="bottom" align="start" sideOffset="32">