Overlay
Popover
Non-modal floating panel anchored to a trigger element. Focus moves into the panel on open and returns to the trigger on close; twelve placements are supported.
Import
import { Popover } from "@zephora/react";Examples
Basic popover
The trigger element is cloned with toggle behavior and ARIA wiring.
<Popover trigger={<Button variant="outline">Details</Button>}>
<div style={{ padding: 12, maxWidth: 240 }}>
Rendered in a portal and positioned next to the trigger.
</div>
</Popover>Placement and arrow
`placement` picks the preferred side; `showArrow` points at the trigger.
<Popover
trigger={<Button variant="soft">Top</Button>}
placement="top"
showArrow
>
<div style={{ padding: 12 }}>Opens above the trigger.</div>
</Popover>
<Popover
trigger={<Button variant="soft">Right</Button>}
placement="right"
showArrow
>
<div style={{ padding: 12 }}>Opens to the right.</div>
</Popover>Controlled
Drive the open state yourself with `open` and `onOpenChange`.
const [open, setOpen] = React.useState(false);
<Popover
trigger={<Button>Filters</Button>}
open={open}
onOpenChange={setOpen}
>
<div style={{ padding: 12, display: "grid", gap: 8 }}>
<span>Panel content…</span>
<Button size="sm" onClick={() => setOpen(false)}>Apply</Button>
</div>
</Popover>API
Popover props
| Prop | Type | Default | Description |
|---|---|---|---|
trigger * | ReactElement | — | Element that anchors and toggles the popover. Cloned with a ref, onClick toggle, aria-haspopup and aria-expanded. |
open | boolean | — | Controlled open state. |
defaultOpen | boolean | false | Initial open state (uncontrolled). |
onOpenChange | (open: boolean) => void | — | Called whenever the popover requests an open state change. |
placement | Placement ("top" | "bottom" | "left" | "right" + "-start"/"-end" variants) | "bottom" | Preferred panel position relative to the trigger. |
showArrow | boolean | false | Renders a small arrow pointing at the trigger. The panel and arrow expose the resolved side via data-side (and the full data-placement) attributes for CSS targeting. |
closeOnBlur | boolean | true | Close when focus or an outside press leaves the popover. |
classNames | Partial<Record<"root" | "arrow", string>> | — | Per-slot class overrides: root targets the floating panel (alongside className), arrow the arrow element. Applied after module classes and also in unstyled mode. |
unstyled | boolean | false | Headless mode — skips Zephora styling. |
Keyboard
| Key | Action |
|---|---|
Enter / Space | On the trigger: toggles the popover. |
Escape | Closes the popover and returns focus to the trigger. |
Tab | Moves focus; leaving the panel closes it when closeOnBlur is on. |