Popover
A small floating panel anchored to a trigger for quick settings, sharing or filters that do not need a modal.
npx prodular-ui add popoverFilters
Set p-0 on the content and pad each section, so dividers run edge to edge.
import { ListFilterIcon } from "lucide-react"
import { Button } from "@/components/ui/button"import { Checkbox } from "@/components/ui/checkbox"import { Field, FieldLabel } from "@/components/ui/field"import { Popover, PopoverClose, PopoverContent, PopoverHeader, PopoverTitle, PopoverTrigger,} from "@/components/ui/popover"
const statuses = [ { label: "Open", count: 64, checked: true }, { label: "Waiting on customer", count: 18, checked: true }, { label: "Escalated", count: 5, checked: false }, { label: "Resolved", count: 312, checked: false },]
export default function PopoverFilters() { return ( <Popover> <PopoverTrigger render={<Button variant="outline" />}> <ListFilterIcon data-icon="inline-start" /> Status </PopoverTrigger> <PopoverContent align="start" className="w-64 gap-0 p-0"> <PopoverHeader className="border-b px-4 py-3"> <PopoverTitle>Filter by status</PopoverTitle> </PopoverHeader> <div className="flex flex-col gap-3 px-4 py-3"> {statuses.map((s) => ( <Field key={s.label} orientation="horizontal"> <Checkbox defaultChecked={s.checked} /> <FieldLabel className="flex-1 font-normal">{s.label}</FieldLabel> <span className="text-xs text-muted-foreground tabular-nums">{s.count}</span> </Field> ))} </div> <div className="flex justify-end gap-2 border-t px-3 py-2.5"> <PopoverClose render={<Button variant="ghost" size="sm" />}>Clear</PopoverClose> <PopoverClose render={<Button size="sm" />}>Apply</PopoverClose> </div> </PopoverContent> </Popover> )}Anatomy
<Popover> <PopoverTrigger render={<Button variant="outline" />}>Share</PopoverTrigger> <PopoverContent align="end"> <PopoverHeader> <PopoverTitle>Share Q4 pricing review</PopoverTitle> <PopoverDescription>Anyone in Halcyon with the link can view.</PopoverDescription> </PopoverHeader> {/* controls */} </PopoverContent></Popover>Guidance
Use it when
- Use for a few related controls tied to one button: share settings, a filter, a date, a color.
- Use PopoverHeader with PopoverTitle when the purpose is not obvious from the trigger.
Avoid
- Lists of actions. Use Dropdown menu, which has keyboard navigation for items.
- Help text on hover. Use Tooltip or Hover card.
- Anything longer than about six controls. Use a Sheet or Dialog.
Rules for AI agents
Published in llms-full.txt, the registry and the MCP server, so coding agents follow them when they build with this component.
- Open from PopoverTrigger with render={<Button variant="outline" />}.
- Set align to match where the trigger sits: start for left aligned toolbars, end for buttons on the right.
- Change width with a w-* class on PopoverContent. The default is w-72.
- Use PopoverClose for buttons that should dismiss the popover, such as Apply.
- Separate sections inside with border-t, never with nested cards.
- For map markers, chart points and graph nodes, pass anchor={pointAnchor(x, y, container)} to PopoverContent and control open, instead of hand-positioning a div with popover classes.
API
PopoverContent
| Prop | Type | Default | Description |
|---|---|---|---|
| side | "top" | "right" | "bottom" | "left" | "bottom" | Preferred side. Flips when there is no room. |
| align | "start" | "center" | "end" | "center" | Alignment against the trigger. |
| sideOffset | number | 6 | Gap to the trigger in px. |
| anchor | Element | VirtualAnchor | RefObject | Positions against something other than the trigger: pointAnchor() for map markers, chart points and the pointer. | |
| collisionPadding | number | Padding | 5 | Space kept from the viewport edge. |
| sticky | boolean | false | Keeps the popup in view after the anchor scrolls away. |
Popover
| Prop | Type | Default | Description |
|---|---|---|---|
| modal | boolean | "trap-focus" | false | Locks page scroll and outside clicks when true. |
Installation
The Prodular UI CLI adds the source to components/ui with everything it depends on. In a project that already uses shadcn/ui, the shadcn CLI installs it from the Prodular registry too. See Installation for the first setup.
npx prodular-ui add popover# or, with the registry in components.jsonnpx shadcn@latest add @prodular/popover