Skip to content
HyperDesign System

Popover

A small floating panel opened by a click, for controls that belong to one trigger: view options, a quick edit, a picker. Non-modal by default; Esc or a click outside closes it. Source: src/components/ui/popover.tsx.

Default

Header, then controls. Focus moves into the panel on open, Tab walks its fields, and Esc hands focus back to the trigger.

Placement

Bottom and centred by default. align lines it up with the trigger's start or end edge; side and sideOffset move it. Radix flips and shifts it to stay on screen.

Anchor

PopoverAnchor lets a small trigger open a panel that lines up with a larger element, here the whole field. The panel matches the anchor's width.

Every Monday, 09:00

Motion and layering

Asymmetric: 140ms in, 90ms out. Keyframes, so a popover closed mid-entrance plays its exit from where it is. Under reduced motion the global rule cuts both to near-zero.

Popover motion and layering tokens
ValueTokenUsage
50Same layer as menus and dialogs. The brand ladder (--z-dropdown 100) is defined but not wired in yet.
140msFade, scale from 95% and a 8px slide away from the trigger.
90msFade and scale back out.
quart-outThe curve for small surfaces that appear on click.
originThe scale grows out of the trigger, whichever side it lands on.
14pxThe brand popover surface: hairline ring instead of a border, glass shadow.

Props

Popover parts and props
Part / propTypeDefaultDescription
PopoverRadix Popover.Root—open, defaultOpen, onOpenChange, modal (false: the page stays interactive).
PopoverTriggerRadix Popover.Trigger—Use asChild around a Button. Gets aria-expanded and aria-controls.
PopoverAnchorRadix Popover.Anchor—Position against this element instead of the trigger.
PopoverContentRadix Popover.Content—Portals itself. Also takes side, alignOffset, collisionPadding, onOpenAutoFocus. No default width or padding.
align"start" | "center" | "end""center"Alignment against the trigger or anchor.
sideOffsetnumber4Gap from the trigger, in px.
PopoverHeaderComponentProps<"div">—A 2px-gap stack for title and description, 14px text.
PopoverTitleComponentProps<"h2">—Medium weight. Renders a div, so it is not a heading in the outline.
PopoverDescriptionComponentProps<"p">—Second text tier. Not wired to aria-describedby.

Best practices

When to use

  • A popover holds a few controls tied to its trigger. A list of actions is a DropdownMenu; a read-only preview on hover is a HoverCard.
  • If the content needs a submit button and validation, it probably wants a Dialog.
  • No product surface uses Popover yet; the composer's pickers are DropdownMenus.

Behavior

  • Changes apply as you make them; there is no Save inside a popover.
  • Close it after a single pick (as in the anchor demo) by controlling open.
  • Set a width and padding on PopoverContent; it ships with neither.

Accessibility

  • The trigger gets aria-expanded; give an icon-only trigger an aria-label.
  • PopoverTitle and PopoverDescription are plain text, not ARIA wiring. Label fields inside with Label.
  • Focus moves in on open and returns to the trigger on Esc.

Content

  • Short title, one-line description, then controls. No paragraphs.
  • Name the trigger after what it opens: View options, Change schedule.