What is Popover?
Popover: A popover is a small floating panel anchored to the control that opened it, holding rich or interactive content, that closes on Escape or a click outside.
A popover is a panel that appears next to its trigger, positioned to stay on screen, and goes away when the user clicks elsewhere or presses Escape. It can hold anything: a form, a color picker, a calendar, a share link with a Copy button, a filter panel. That is what separates it from a tooltip, which is text only and appears on hover, and from a dropdown menu, which is a list of commands with its own keyboard rules.
When to use it
- Small, contextual tasks that would be heavy as a modal dialog: editing one field, picking a date, choosing a color, confirming a small action.
- Extra detail on demand, such as a user card on a name or a breakdown behind a number.
- Filters and settings attached to the control they affect, so the result updates in place.
- Not for content people need to compare with the page, or anything with more than a few controls; use a side sheet.
Accessibility
The trigger is a button with aria-expanded and, when the popover holds interactive content, aria-haspopup="dialog" and aria-controls pointing at the panel. The panel takes role="dialog" with a name from its heading. When it opens, focus moves inside it; when it closes, focus returns to the trigger. Escape closes it. Tab moves through the popover's controls and must not disappear into the page behind the panel; at the end, either wrap or close the popover and continue past the trigger. A popover that only shows text can skip the dialog role and the focus move.
The HTML popover attribute, supported in most browsers, renders an element in the top layer with light dismiss built in. It does not position the element next to its trigger on its own, so most React components still use a positioning library and a portal.
How to build one in React
MiniDev's Popover is built on Base UI, which handles positioning, the ARIA attributes, focus and dismissal. The render prop lets the trigger be your own Button:
import { Button } from "@/components/ui/button"
import { Popover, PopoverContent, PopoverDescription, PopoverHeader, PopoverTitle, PopoverTrigger } from "@/components/ui/popover"
export function ShareReport() {
return (
<Popover>
<PopoverTrigger render={<Button variant="outline" />}>Share</PopoverTrigger>
<PopoverContent align="start" side="bottom">
<PopoverHeader>
<PopoverTitle>Share Q3 revenue</PopoverTitle>
<PopoverDescription>Anyone with the link can view.</PopoverDescription>
</PopoverHeader>
<Button size="sm">Copy link</Button>
</PopoverContent>
</Popover>
)
}
side and align set the preferred placement, and the panel flips to the other side when it would leave the viewport. Keep popovers under about 320px wide and let the content scroll inside if it must. For hover previews use HoverCard, and for a list of actions, DropdownMenu. All three are in the overlays category.