Popover
A floating panel anchored to a trigger element. Click to open, click-outside or ESC to dismiss. Use for contextual actions, mini-forms, or rich inline info that doesn't warrant a full dialog. Built on @base-ui/react/popover.
Anatomy
PopoverContent is a floating panel with a default width of w-72. It accepts side, align, and sideOffset for positioning. Optional helpers PopoverHeader, PopoverTitle, and PopoverDescription provide consistent internal layout.
side="bottom" (default)align="center" (default)w-72 default width
Positioning
The sideprop controls which side of the trigger the panel appears on. The popover auto-flips if there isn't enough space in the preferred direction.
side="top"side="right"side="bottom"side="left"Alignment
The align prop shifts the panel relative to the trigger along the cross-axis.
align="start"align="center"align="end"Examples
Mini-form
Info panel
Notification config
Design Guidelines
Do
- Use for contextual forms and inline info. Popovers are anchored — they make sense for editing a specific value or explaining a specific element.
- Keep content focused. A popover should serve one purpose. If it grows complex, promote it to a Dialog or Sheet.
- Use
sideOffsetfor visual breathing room. The default of 4px provides a natural separation from the trigger.
Don't
- Don't use as a dropdown menu. For lists of actions use
DropdownMenu— it handles keyboard navigation, roles, and item focus automatically. - Don't put too much content inside. If the popover scrolls, it's trying to be a Dialog — use one instead.
- Don't rely on hover to trigger. Hover-based popovers are inaccessible on touch devices — use
HoverCardonly for supplemental previews.
Developer Reference
Accessibility
role="dialog"— focus moves into the popover on open.- ESC key and clicking outside both dismiss the panel.
- Renders in a portal — visually floats above the page, still in the accessible DOM tree.
PopoverHeader,PopoverTitle,PopoverDescriptionare layout helpers that do not add semantic roles — use them for consistent spacing.
Usage
import {
Popover,
PopoverTrigger,
PopoverContent,
PopoverHeader,
PopoverTitle,
PopoverDescription,
} from "@/components/ui/popover"
// Basic
<Popover>
<PopoverTrigger asChild>
<Button>Open</Button>
</PopoverTrigger>
<PopoverContent>
<PopoverHeader>
<PopoverTitle>Title</PopoverTitle>
<PopoverDescription>Supporting text.</PopoverDescription>
</PopoverHeader>
</PopoverContent>
</Popover>
// Positioning
<PopoverContent side="top" align="start" sideOffset={8}>
...
</PopoverContent>
// Custom width
<PopoverContent className="w-96">
...
</PopoverContent>
// Controlled
const [open, setOpen] = useState(false)
<Popover open={open} onOpenChange={setOpen}>...</Popover>