Skip to content

Popover

<Popover> is a click-anchored floating panel — content the user opens, interacts with, then dismisses. Lives between a Tooltip (read-only hover label) and a Dialog (centered modal task).

import from "@na/ui/components/popover" ▶ Open in Storybook packages/ui/src/components/popover.tsx

When to use

  • Anchored mini-forms (rename inline, set a date, pick a color).
  • Quick-action menus that aren’t a <select>.
  • Color picker, date picker, mention picker — anything an anchor + content fits.

Don’t use Popover for: read-only labels (Tooltip), full-form tasks (Dialog), confirmations (ConfirmPopover).

Basic

<Popover>
<PopoverTrigger asChild>
<Button variant="outline">Open settings</Button>
</PopoverTrigger>
<PopoverContent className="w-72">
<Label>Display name</Label>
<Input defaultValue="Alice" />
</PopoverContent>
</Popover>

API

Popover

Prop Type Default Description
open boolean Controlled. Pair with onOpenChange.
defaultOpen boolean false Initial state.
onOpenChange (open: boolean) => void Fires on open / close.
modal boolean false When true, traps focus + makes outside inert.

PopoverContent

Prop Type Default Description
side "top" | "right" | "bottom" | "left" "bottom" Preferred placement.
sideOffset number 4 Pixels between trigger and content.
align "start" | "center" | "end" "center" Anchor alignment.
className string Almost always — set a width.

PopoverAnchor is available when the trigger isn’t the element you want the popover anchored to.

Design guidelines

✓ Do

  • Cap the popover width — w-72 to w-96 is the comfort range.
  • Close on outside click + Esc. Don't intercept those without a strong reason.
  • Pair every Popover form with explicit Save / Cancel — auto-save on blur is unsafe inside popovers.

✗ Don't

  • Use Popover for read-only labels. That's a Tooltip.
  • Stack popovers. If you open a popover from inside another, you need a Dialog.
  • Make the popover full-page width. The motion / anchor breaks down.

Accessibility

  • Composes Radix Popover — first focusable element receives focus on open; Esc closes; outside-click closes.
  • Trigger is <button aria-haspopup="dialog" aria-expanded>.

▶ Open Popover stories in Storybook