Popover
StableA floating panel anchored to a trigger for small, interactive content — settings, quick forms and pickers — without blocking the page.
Installation
$ pnpm dlx shadcn@latest add https://www.prfct.dev/r/popover.jsonUsage
import {
Popover,
PopoverContent,
PopoverDescription,
PopoverHeader,
PopoverTitle,
PopoverTrigger,
} from "@/components/ui/popover"<Popover>
<PopoverTrigger render={<Button variant="outline" />}>Dimensions</PopoverTrigger>
<PopoverContent>
<PopoverHeader>
<PopoverTitle>Dimensions</PopoverTitle>
<PopoverDescription>Set the size of the selected frame.</PopoverDescription>
</PopoverHeader>
{/* … */}
</PopoverContent>
</Popover>The popover is positioned by Floating UI: it opens below its trigger, flips to the other side when there isn't room, and stays inside the viewport. It enters from the trigger's direction — the popup-motion choreography shared by every prfct floating surface.
Examples
Quick input
A popover can hold a small form. Control it with open and onOpenChange so it closes after a successful submit, and confirm with a Toast.
Header
PopoverHeader, PopoverTitle and PopoverDescription give a popover a title that names it for assistive technology. Use them whenever the content has more than one control.
Side
side places the popover on the top, right, bottom (default) or left of its trigger. If the preferred side doesn't fit, it flips.
Alignment
align lines the popover up with the start, center (default) or end of the trigger. Align to the start for menus that read left to right, and to the end for triggers near the right edge.
Guidelines
When to use
- For controls that act on one element: formatting, dimensions, filters for a single column.
- For quick inputs that don't need a full dialog: a note, a rename, a date.
- For pickers: colors, emoji, dates.
When not to use
- To show a plain text label — use a Tooltip.
- To preview a link on hover — use a Hover Card.
- For a list of actions — use a Dropdown Menu, which gives you arrow-key navigation and typeahead.
- For tasks that need focus and a clear finish — use a Dialog.
Keep it small
A popover is a glance, not a destination. If its content needs to scroll, needs more than a few controls, or needs a Save button, it has outgrown the popover. Keep it under ~20rem wide and a few rows tall.
Accessibility
The trigger is a button with aria-expanded and aria-haspopup="dialog"; the popup is a non-modal dialog, labeled by PopoverTitle when present.
| Key | Behavior |
|---|---|
EnterSpace | On the trigger: toggles the popover. |
Tab | Moves focus into the popover, then through its controls and on to the rest of the page. |
Esc | Closes the popover and returns focus to the trigger. |
- Non-modal by default. The page stays interactive; clicking outside or moving focus away closes the popover. Pass
modalto trap focus and lock scroll, ormodal="trap-focus"to trap focus only. - Name it. Use
PopoverTitlefor any popover with controls. Without a visible title, add anaria-labeltoPopoverContent. - Hover opening is opt-in.
openOnHoveron the trigger also opens it on hover, but it always opens on click and keyboard too — never make hover the only way in.
API reference
Popover
The root. Doesn't render an element. Accepts every prop of Base UI Popover.Root.
PopoverTrigger
Toggles the popover. Renders a <button>; use render to render a prfct Button.
PopoverContent
Renders the portal, positioner and popup.
PopoverHeader, PopoverTitle, PopoverDescription
PopoverHeader stacks the title and description. PopoverTitle renders an <h2> that labels the popover; PopoverDescription renders a <p> that describes it.