Popover
A Popover shows users a small panel next to its trigger and keeps the rest of the page interactive.
When to Use
- for one or two fields that change a setting in place, such as the days before a payment reminder
- to explain one item on the page, like why a message was not delivered
- to show a Calendar for choosing a date
When Not to Use
- to name an icon-only Button (use a Tooltip)
- to preview the page behind a link (use a Hover Card)
- to offer a list of actions (use a Dropdown Menu)
- for a task that users have to finish or cancel before anything else (use a Dialog)
| Popover | Tooltip | Hover Card | |
|---|---|---|---|
| Purpose | Fields or detail for one control | The name of a control | A preview of a link’s target |
| Trigger | A button | A button | An a |
| Opening | A click | Hover after 200ms, or keyboard focus | Hover or keyboard focus, after 600ms |
| Touch | A tap opens it | Doesn’t open | Doesn’t open |
| Focus | Moves into the popup | Stays on the trigger | Stays on the link |
| Content | Text and controls | A few words and a Kbd | Text and images, with no controls |
| Screen Reader | Announces a dialog | Reads the trigger’s own name only | Reads the link only |
| Width | 288px | At most 320px | 256px |
| Default Side | Below | Above | Below |
Anatomy
| Element | Usage |
|---|---|
| Trigger | Required |
| Popup | Required |
| Title* | Optional |
| Description | Optional |
* The title is the popup’s accessible name. If the popup has no title, set an aria-label on it.
PopoverContent renders the portal, the positioner, and the popup, so you don’t need to add them.
Behavior
A Popover isn’t modal: while it is open, the page scrolls and stays interactive, and users can move focus out of the popup with Tab.
By default, the popup opens below the trigger and is centered on it. If the popup doesn’t fit there, Base UI moves it to another side. To change its position, use side, sideOffset, align, and alignOffset on PopoverContent.
The popup is 288px wide and as tall as its content.
Accessibility
Base UI’s Popover sets the role, moves focus into the popup, and closes when users press Escape. You provide the title that names the popup.
A Popover has the role dialog, so it needs a name for screen readers to announce it, as WCAG 2.2 SC 4.1.2 Name, Role, Value
requires. To provide one, add a PopoverTitle, or set aria-label on PopoverContent if the popup has no title.
Installation
npx shadcn@latest add @summit/popoverUsage
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import {
Popover,
PopoverContent,
PopoverDescription,
PopoverHeader,
PopoverTitle,
PopoverTrigger,
} from '@/components/ui/popover';
<Popover>
<PopoverTrigger render={<Button variant="outline" />}>Set reminder</PopoverTrigger>
<PopoverContent>
<PopoverHeader>
<PopoverTitle>Payment reminder</PopoverTitle>
<PopoverDescription>Sent to the client before an invoice is due.</PopoverDescription>
</PopoverHeader>
<div className="grid gap-2">
<Label htmlFor="days">Days before the due date</Label>
<Input id="days" type="number" defaultValue={3} />
</div>
</PopoverContent>
</Popover>;Open on Hover
If openOnHover is set on PopoverTrigger, the Popover also opens when the pointer has rested on the trigger for 300ms. Touch users and screen reader users can still reach the text, which a Tooltip hides from both. Use openOnHover for the text behind an info icon.
import { InfoIcon } from '@phosphor-icons/react';
<Popover>
<PopoverTrigger openOnHover render={<Button variant="ghost" size="icon" aria-label="About the tax number" />}>
<InfoIcon />
</PopoverTrigger>
<PopoverContent aria-label="About the tax number">Printed on every invoice you send.</PopoverContent>
</Popover>;API Reference
The parts accept the props of their matching parts in Base UI’s Popover, where PopoverContent is Popover.Popup. PopoverHeader accepts the props of a div. Summit doesn’t wrap the close button, the arrow, or the backdrop of Base UI’s Popover. See the Base UI Popover documentation for modal, openOnHover, initialFocus, finalFocus, and Popover.Close.
PopoverContent
| Prop | Type | Default | Description |
|---|---|---|---|
side | 'top' | 'bottom' | 'left' | 'right' | 'inline-start' | 'inline-end' | 'bottom' | The side of the trigger the popup opens on |
sideOffset | number | OffsetFunction | 4 | The gap between the trigger and the popup, in pixels |
align | 'start' | 'center' | 'end' | 'center' | The edge of the trigger the popup is aligned with |
alignOffset | number | OffsetFunction | 0 | A shift along that edge, in pixels |