tetra-ui Logotetra ui

Popover

Displays content in a portal relative to the triggering button element.

popover

Installation

npx shadcn@latest add @tetra-ui/popover

Usage

First ensure that you have the PortalHost component in your root layout.

import { PortalHost } from "@/components/ui/portal";

export default function RootLayout() {
  return (
    <>
      <Stack />
      <PortalHost />
    </>
  );
}
import { Button, ButtonText } from "@/components/ui/button";
import {
  Popover,
  PopoverContent,
  PopoverOverlay,
  PopoverPortal,
  PopoverTrigger,
} from "@/components/ui/popover";
<Popover>
  <PopoverTrigger asChild>
    <Button>
      <ButtonText>Open</ButtonText>
    </Button>
  </PopoverTrigger>
  <PopoverPortal>
    <PopoverOverlay />
    <PopoverContent>
      <Text>Popover Content</Text>
    </PopoverContent>
  </PopoverPortal>
</Popover>

Positioning

Control placement with side and align on PopoverContent:

<PopoverContent side="top" align="center">
  <Text>Tooltip above the trigger</Text>
</PopoverContent>

Supported values:

  • side: "top" | "bottom" | "left" | "right"
  • align: "start" | "center" | "end"

Use sideOffset and alignOffset to fine-tune distance from the trigger. Set width="trigger" to match the trigger width, or pass a percentage or pixel value.

Without overlay

Omit PopoverOverlay for lightweight tooltips that don't dim the background:

<Popover>
  <PopoverTrigger asChild>
    <Button variant="outline">Open</Button>
  </PopoverTrigger>
  <PopoverPortal>
    <PopoverContent>
      <Text>No backdrop</Text>
      <PopoverClose asChild>
        <Button size="sm" variant="link">Close</Button>
      </PopoverClose>
    </PopoverContent>
  </PopoverPortal>
</Popover>

Controlled

Pass open and onOpenChange for controlled state:

const [open, setOpen] = useState(false);

<Popover open={open} onOpenChange={setOpen}>
  {/* ... */}
</Popover>

Scrollable content

Wrap long content in a ScrollView and constrain the popover height:

<PopoverContent className="h-1/2 p-0" width="50%">
  <ScrollView className="p-4">
    {/* long content */}
  </ScrollView>
</PopoverContent>

On this page