Popover
Displays rich content in a portal, triggered by a button.
When to Use
Use Popover when you need to:
- Display interactive content like forms, settings, or filters in a floating panel
- Show rich multi-element content triggered by a button click
- Provide inline editing without navigating away from the current context
- Present secondary controls or options without cluttering the main interface
- Build date pickers, color pickers, or other compound input patterns
When Not to Use
- Simple text hints on hover - use Tooltip instead
- Preview content on hover - use Hover Card instead
- A list of actions or commands - use Dropdown Menu
- Critical confirmations that block the page - use Alert Dialog
Default
Popover with form inputs for setting dimensions. Demonstrates a common pattern for inline editing.
Simple
Basic popover with text content. The simplest usage pattern.
Positions
Popover can be positioned on any side of the trigger using the side prop: top, right, bottom, or left.
UX & Design Guidelines
Content Strategy
Keep popover content focused on a single task or group of related settings. Avoid deeply nested layouts or excessive scrolling inside popovers. If the content grows beyond what fits comfortably in a floating panel, consider using a Dialog or Sheet instead. Include a clear heading so users understand the popover's purpose at a glance.
Positioning & Overflow
The popover automatically flips to the opposite side when there is not enough viewport space. Use sideOffset to control the gap between the trigger and the panel (default is 4px). For alignment fine-tuning, combine align with alignOffset. The default width is w-72 (288px); override it with a className when needed.
Trigger Design
Always use asChild on PopoverTrigger to render a styled Button rather than a plain element. The trigger should clearly indicate that it opens additional content, for example by including a chevron icon or descriptive label.
Color & Contrast
The popover surface uses bg-popover with text-popover-foreground for consistent theming across light and dark modes. Borders, shadows, and rounded corners are applied by default. Inner content should continue to use semantic tokens like text-muted-foreground for descriptions and border-border for dividers.
Accessibility
Keyboard Navigation
- Tab — Move focus to the popover trigger
- Enter or Space — Open or close the popover
- Tab — When open, move focus through interactive elements inside the popover
- Escape — Close the popover and return focus to the trigger
Screen Reader Support
- The trigger automatically receives
aria-expandedreflecting the open state - The trigger is linked to the content via
aria-controls - Icon-only triggers require
aria-labelfor screen reader users - Use
aria-describedbyfor additional context about what the popover contains
Focus Management
When the popover opens, focus moves to the first focusable element inside the content panel. When modal is set to true, focus is trapped within the popover until it is dismissed. On close, focus returns to the trigger element automatically.
Dismiss Behavior
The popover closes when pressing Escape, clicking outside the content, or when another popover opens. In modal mode, only Escape and explicit close actions dismiss the popover.
ARIA Attributes
{/* Standard popover with descriptive trigger */}
<Popover>
<PopoverTrigger asChild>
<Button variant="outline" aria-label="Edit dimensions">
<Settings className="size-4" />
</Button>
</PopoverTrigger>
<PopoverContent>
{/* Interactive content receives focus */}
</PopoverContent>
</Popover>
{/* Modal popover - traps focus within */}
<Popover modal>
<PopoverTrigger asChild>
<Button>Open modal popover</Button>
</PopoverTrigger>
<PopoverContent>
{/* Focus is trapped until popover is dismissed */}
</PopoverContent>
</Popover>
{/* Popover with explicit description */}
<Popover>
<PopoverTrigger asChild>
<Button aria-describedby="filter-hint">Filters</Button>
</PopoverTrigger>
<PopoverContent>
<span id="filter-hint" className="sr-only">
Opens a panel to configure search filters
</span>
{/* Filter form content */}
</PopoverContent>
</Popover>Related Components
API Reference
The Popover component is composed of four sub-components. Each accepts the props listed below in addition to standard HTML attributes.
Popover (Root)
| Prop | Type | Default | Description |
|---|---|---|---|
| open | boolean | — | Controlled open state of the popover. |
| onOpenChange | (open: boolean) => void | — | Event handler called when the open state changes. |
| defaultOpen | boolean | false | The initial open state when uncontrolled. |
| modal | boolean | false | When true, interaction with outside elements is disabled and only popover content is visible to screen readers. |
PopoverTrigger
| Prop | Type | Default | Description |
|---|---|---|---|
| asChild | boolean | false | When true, the trigger renders its child as the root element, merging props and behavior. |
PopoverContent
| Prop | Type | Default | Description |
|---|---|---|---|
| side | "top" | "right" | "bottom" | "left" | "bottom" | The preferred side of the trigger to render against. |
| sideOffset | number | 4 | Distance in pixels from the trigger element. |
| align | "start" | "center" | "end" | "center" | Alignment relative to the trigger element. |
| alignOffset | number | 0 | Offset in pixels from the aligned edge. |
| className | string | — | Additional CSS classes to apply to the popover content. |
PopoverAnchor
| Prop | Type | Default | Description |
|---|---|---|---|
| asChild | boolean | false | When true, uses the child element as the anchor reference for positioning. |