Popover
A small panel anchored to a button, wrapping the Base UI Popover. Non-modal by default, so the page behind stays interactive; for a plain text label, the lighter Tooltip is the better fit.
Playground
Every control maps to a prop. The Code tab always shows the markup for exactly what you've configured.
Variants
Four sides, and each flips to the opposite when there's no room; align (start, center, end) slides the panel along the chosen edge. Open each one: the panel scales in from the trigger's side.
States
Closed and open are the only two, and both are live: click a trigger. While open, the trigger carries data-popup-open and the panel data-open; a disabled trigger (disable the button you render) never opens.
Styling states
The trigger carries data-popup-open while open; the popup carries data-side and the data-starting-style/data-ending-style enter and exit hooks:
.ub-popover-trigger[data-popup-open] {
background: var(--ub-bg-muted);
}Props
Position lives on the content; the title and description wire the panel's accessible name and description automatically. The essentials, by part:
| Prop | Type | Default | Description |
|---|---|---|---|
PopoverRoot.open | boolean | – | Controlled state. Pair with onOpenChange; defaultOpen for uncontrolled. |
PopoverRoot.onOpenChange | (open: boolean) => void | – | Called on every open and close, including Escape and outside clicks. |
PopoverRoot.modal | boolean | false | Traps focus and blocks the page behind; prefer a dialog at that point. |
PopoverTrigger.render | ReactElement | – | The real control that opens the panel, usually a Bones Button. |
PopoverContent.side | "top" | "right" | "bottom" | "left" | "bottom" | Preferred side; flips to the opposite when out of room. |
PopoverContent.align | "center" | "start" | "end" | "center" | Alignment along the chosen side. |
PopoverContent.sideOffset | number | 8 | Gap between the trigger and the panel, in pixels. |
PopoverContent.initialFocus | boolean | RefObject<HTMLElement | null> | (openType) => ... | – | Where focus lands on open; defaults to the first focusable part. |
Agent instructions
Working with a coding agent? Paste this into its context, or point it at llms.txt for the whole library.
PopoverRoot, PopoverTrigger, PopoverContent, PopoverTitle, PopoverDescription, PopoverClose, from @usebones/react.
- Structure: PopoverRoot wraps PopoverTrigger + PopoverContent; put PopoverTitle (names the panel), PopoverDescription, and any controls inside the content. PopoverClose closes it.
- Attach trigger and close to real controls via render={<Button ... />}; a disabled rendered button never opens.
- PopoverContent: side "bottom" (default) | "top" | "right" | "left", align "center" | "start" | "end", sideOffset (8). Escape and outside clicks dismiss; focus returns to the trigger.
- Non-modal by default; modal traps focus (prefer a dialog then). For a plain text label use Tooltip.
- Restyle in CSS via .ub-popover-popup, .ub-popover-title, .ub-popover-description, [data-popup-open] on the trigger, [data-open]/[data-side] on the popup, [data-starting-style]/[data-ending-style] for enter/exit. Tokens only.