Popover
A floating panel anchored to a trigger element.
Installation
$
Usage
import { Popover, PopoverTrigger, PopoverContent } from "@/components/ui/popover"Examples
Default
API Reference
| Prop | Type | Default | Description |
|---|---|---|---|
| openPopover | boolean | - | Controlled open state. Use with onOpenChange. |
| onOpenChangePopover | (open: boolean) => void | - | Called when the open state changes. |
| modalPopover | boolean | false | When true, blocks interaction with outside elements while the popover is open. |
| sidePopoverContent | "top" | "right" | "bottom" | "left" | "bottom" | Preferred edge of the trigger to render against. |
| alignPopoverContent | "start" | "center" | "end" | "center" | Alignment against the trigger along the chosen side. |
| sideOffsetPopoverContent | number | 4 | Distance in pixels between the popover and the trigger. |
| collisionAvoidancePopoverContent | CollisionAvoidance | { fallbackAxisSide: "end" } | Object controlling how the popover avoids viewport collisions on the side and alignment axes, e.g. { side: 'none', align: 'none' } to always honor side/align. |
"use client"
import * as React from "react"
import { Popover as PopoverPrimitive } from "@base-ui/react/popover"
import { cn } from "@/registry/lib/utils"
function Popover({
...props
}: React.ComponentProps<typeof PopoverPrimitive.Root>) {
return <PopoverPrimitive.Root data-slot="popover" {...props} />
}
function PopoverTrigger({
...props
}: React.ComponentProps<typeof PopoverPrimitive.Trigger>) {
return <PopoverPrimitive.Trigger data-slot="popover-trigger" {...props} />
}
function PopoverContent({
className,
align = "center",
side,
sideOffset = 4,
alignOffset,
collisionAvoidance,
...props
}: React.ComponentProps<typeof PopoverPrimitive.Popup> &
Pick<
React.ComponentProps<typeof PopoverPrimitive.Positioner>,
"align" | "side" | "sideOffset" | "alignOffset" | "collisionAvoidance"
>) {
return (
<PopoverPrimitive.Portal>
{/* z-50 goes on the Positioner: Base UI leaves the Popup
`position: static`, where z-index is ignored, so a z on the Popup is
inert and the popover falls back to `z-index: auto`. Combobox
composes this, so it inherits the fix. */}
<PopoverPrimitive.Positioner
className="z-50"
side={side}
align={align}
sideOffset={sideOffset}
alignOffset={alignOffset}
collisionAvoidance={collisionAvoidance}
>
<PopoverPrimitive.Popup
data-slot="popover-content"
className={cn(
"bg-popover text-popover-foreground transition-[opacity,scale,translate] motion-reduce:transition-[opacity] ease-out duration-200 data-[ending-style]:duration-150 data-[starting-style]:opacity-0 data-[ending-style]:opacity-0 data-[starting-style]:scale-95 data-[ending-style]:scale-95 data-[side=bottom]:data-[starting-style]:-translate-y-2 data-[side=bottom]:data-[ending-style]:-translate-y-2 data-[side=top]:data-[starting-style]:translate-y-2 data-[side=top]:data-[ending-style]:translate-y-2 data-[side=right]:data-[starting-style]:-translate-x-2 data-[side=right]:data-[ending-style]:-translate-x-2 data-[side=left]:data-[starting-style]:translate-x-2 data-[side=left]:data-[ending-style]:translate-x-2 w-72 origin-(--transform-origin) rounded-md p-4 shadow-ring-md outline-hidden break-words",
className
)}
{...props}
/>
</PopoverPrimitive.Positioner>
</PopoverPrimitive.Portal>
)
}
export { Popover, PopoverTrigger, PopoverContent }