Popover
A non-modal dialog anchored to a trigger, for interactive content.
Popover opens on click and contains an interactive, non-modal dialog. Use a focusable trigger that forwards its ref and event handlers, such as Puzzle Button.
Import
import { Popover } from "@puzzle-ui/ui";Basic usage
Name the dialog with a visible title. closable adds a close button alongside the title.
Position, alignment, and offset
position requests top, right, bottom, or left; placement can change when space is limited. align accepts start, center, or end. offset changes the gap in pixels.
Accessible name and close label
When there is no visible title, provide aria-label. Customize closeLabel to describe the close action in the language of your application.
Controlled visibility
Pair open with onOpenChange to respond to trigger clicks and dismissal. Application actions inside the popover can close it through the same state. For uncontrolled usage, defaultOpen sets only the initial visibility.
API
| Prop | Type | Default | Description |
|---|---|---|---|
trigger | ReactElement | Required | Single trigger accepting DOM attributes and a ref. |
children | ReactNode | Required | Dialog body; may contain interactive controls. |
title | ReactNode | - | Visible heading and accessible dialog name. |
aria-label | string | - | Dialog name when no title is provided. |
closable | boolean | false | Displays a close button. |
closeLabel | string | "Close" | Accessible name of the close button. |
position | "top" | "right" | "bottom" | "left" | "bottom" | Preferred popup side. |
align | "start" | "center" | "end" | "center" | Popup alignment along the trigger. |
offset | number | 8 | Gap from the trigger in pixels. |
open | boolean | - | Controlled visibility. |
defaultOpen | boolean | false | Initial uncontrolled visibility. |
onOpenChange | (open: boolean) => void | - | Called when visibility changes are requested. |
className | string | - | Additional class on the dialog. |
triggerClassName | string | - | Additional class merged onto the trigger. |
Focus behavior
- Opening moves focus to the first focusable element, or to the dialog itself. A popover that is open on first render does not take focus.
- Tab from the trigger enters the popover; Shift+Tab from its first element returns to the trigger.
- Tabbing past the last element, Escape and the close button close the popover and return focus to the trigger.
- Moving focus elsewhere or clicking outside closes it.
The dialog has role="dialog". The trigger exposes aria-haspopup="dialog", aria-expanded, and, while open, aria-controls.
Use Tooltip for short, non-interactive hints.