Popover
A floating panel anchored to a trigger element, built on Base UI's Popover primitive.
Overview
Popover is a compound component that operates in a non-modal manner, unlike Dialog, and does not block interaction with the rest of the page. Use it for supplementary information, inline forms, or rich tooltips.
- Composed with a compound API:
Popover,Popover.Trigger,Popover.Content,Popover.Arrow - Operates non-modally; clicking outside closes the popover without blocking interaction.
- Supports
sideandalignpositioning props. Popover.Arrowrenders an arrow caret pointing toward the trigger.- Supports both controlled (
open+onOpenChange) and uncontrolled (defaultOpen) usage.
Guidelines
- Use Popover for supplementary information, inline forms, or rich interactive content anchored to a trigger.
- For short text-only hints, use Tooltip instead (lighter weight, hover-only).
- For content that demands user attention, use Dialog (modal, focus-trapping).
Accessibility
- Non-modal by default — does not trap focus or block interaction with the rest of the page.
- Clicking outside or pressing
Escapecloses the popover. - The trigger element receives
aria-expandedto communicate the popover's open state. - Focus management follows natural tab order within the popover content. Use with interactive elements like forms and buttons.
Import
import { Popover } from "@cocso-ui/react";Default
A popover with a title, description text, and an arrow indicator.
"use client";
import { Button, Popover, Typography } from "@cocso-ui/react";
export default function PopoverDefault() {
return (
<div className="p-4">
<Popover>
<Popover.Trigger render={<Button variant="secondary" />}>Open Popover</Popover.Trigger>
<Popover.Content>
<div className="flex flex-col gap-2 p-3">
<Typography type="custom" size={14} weight="semibold">Popover Title</Typography>
<Typography type="custom" size={13}>This is the popover content. It can contain any elements.</Typography>
</div>
<Popover.Arrow />
</Popover.Content>
</Popover>
</div>
);
}Positions
Use the
side prop on Popover.Content to control which side of the trigger the popover appears on."use client";
import { Button, Popover, Typography } from "@cocso-ui/react";
export default function PopoverPositions() {
return (
<div className="flex flex-wrap gap-3 p-4">
{(["top", "bottom", "left", "right"] as const).map((side) => (
<Popover key={side}>
<Popover.Trigger render={<Button variant="outline" />}>{side}</Popover.Trigger>
<Popover.Content side={side}>
<div className="p-3">
<Typography size={13}>Popover on {side}</Typography>
</div>
<Popover.Arrow />
</Popover.Content>
</Popover>
))}
</div>
);
}API Reference
Popover (Root Container)
| Prop | Type | Default | Description |
|---|---|---|---|
open | boolean | - | Controlled open state. Use together with `onOpenChange` for programmatic popover control. |
onOpenChange | (open: boolean) => void | - | Callback invoked when the popover should open or close. Receives the new boolean state. |
defaultOpen | boolean | false | Initial open state for uncontrolled usage. |
Popover.Trigger
| Prop | Type | Default | Description |
|---|---|---|---|
render* | ReactElement | - | The element to render as the popover trigger. Receives click handler and `aria-expanded` via prop merging. |
Popover.Content
| Prop | Type | Default | Description |
|---|---|---|---|
side | "top" | "bottom" | "left" | "right" | "bottom" | Preferred placement side relative to the trigger. Auto-flips if there is insufficient space on the preferred side. |
sideOffset | number | 4 | Distance in pixels between the trigger and the popover panel. |
align | "start" | "center" | "end" | "center" | Alignment of the popover along the trigger edge. `start` aligns to the leading edge, `end` to the trailing edge. |
alignOffset | number | 0 | Offset in pixels along the alignment axis for fine-tuning position. |
arrowPadding | number | 4 | Minimum distance in pixels between the arrow and the popover edge, preventing the arrow from overflowing corners. |
Popover.Arrow
| Prop | Type | Default | Description |
|---|---|---|---|
width | number | 10 | Width of the arrow caret in pixels. |
height | number | 5 | Height of the arrow caret in pixels. |