Components
Popover
Displays rich content — text, controls, or a small form — in a floating panel anchored to a trigger, dismissed by clicking away or pressing Escape.
Basic usage
Wrap a PopoverTrigger and PopoverContent in a Popover. Use asChild on the trigger to render a Button. Reach for a popover when the panel holds free-form layout; reach for DropdownMenu when it holds a list of menu items with roving-focus keyboard navigation.
With a form
Popovers are ideal for compact, inline editing — compose them from the package's own Label and Input rather than bare markup, so the fields pick up the same focus ring and error tokens as the rest of a form. Widen the panel past its default w-72 by passing a width utility to className.
Placement
Control where the panel appears with side, align and sideOffset on PopoverContent. It automatically flips to stay in the viewport.
Anchoring to another element
PopoverAnchor separates what opens the panel from what the panel lines up against. Wrap the element you want to measure against and the trigger can be any control inside it — useful for table rows, list items and inline editors where a tiny icon button would otherwise drag the panel out of alignment.
Props
Every part forwards the full Radix prop set and exports its own prop type — PopoverProps, PopoverTriggerProps, PopoverContentProps and PopoverAnchorProps — so wrappers in your app can extend them without re-deriving the types.
Popover — the root container that manages open state.
| Prop | Type | Default | Description |
|---|---|---|---|
open | boolean | — | Controlled open state. Omit for uncontrolled, Radix-managed behavior. |
defaultOpen | boolean | false | Open state when initially rendered (uncontrolled). |
onOpenChange | (open: boolean) => void | — | Called when the open state changes via interaction. |
modal | boolean | false | When true, interaction outside the content is blocked and scroll is locked. |
PopoverTrigger — the element that toggles the panel.
| Prop | Type | Default | Description |
|---|---|---|---|
asChild | boolean | false | Merges props onto the single child instead of rendering a button — use to wire up a Button. |
PopoverContent — the floating panel, portaled to the body. It ships as w-72 with p-4, a border and the shadow-overlay elevation token, so the drop shadow follows the light and dark palettes instead of a baked-in colour.
| Prop | Type | Default | Description |
|---|---|---|---|
side | 'top' | 'right' | 'bottom' | 'left' | 'bottom' | Preferred side of the anchor to render against. |
align | 'start' | 'center' | 'end' | 'center' | Alignment of the content against the anchor. Set by the package, not by Radix. |
sideOffset | number | 4 | Distance in pixels between the content and the anchor. Set by the package, not by Radix. |
alignOffset | number | 0 | Offset in pixels along the alignment axis. |
avoidCollisions | boolean | true | Flips and shifts the panel to keep it inside the viewport. |
className | string | — | Additional Tailwind classes merged onto the panel — most often to override the default w-72 width. |
PopoverAnchor — optional positioning reference. When present, the panel is measured against it instead of the trigger.
| Prop | Type | Default | Description |
|---|---|---|---|
asChild | boolean | false | Merges props onto the single child instead of rendering a div — use to anchor to an existing element. |
virtualRef | React.RefObject<Measurable> | — | Position against a measurable object (a text range, a canvas cell) instead of a DOM node. |
Accessibility
- Built on Radix Popover — the trigger and content are linked via
aria-controls,aria-expandedandaria-haspopupautomatically. - Focus moves into the panel on open and returns to the trigger on close, so keyboard users never lose their place.
- Pressing Escape or clicking outside dismisses the panel. Tab walks the focusable content inside it and then continues out into the page — focus is only trapped when
modalis set. - Always render the trigger as an interactive element (a
ButtonviaasChild) so it is reachable and operable by keyboard.PopoverAnchoris a positioning hint only — it never becomes the interactive element. - Set
modalwhen the panel must be answered before anything else; it traps focus and hides the rest of the page from assistive tech. Leave it off for the ordinary non-blocking case.