Live Playground
Open the surface to test the controlled root state, anchor positioning, and the animated content wrapper.
Open the popover to inspect the controlled open state, portal-based panel, and origin-aware spring animation.
Install And Iterate
Install the component directly into your codebase, then branch into v0 if you want to iterate on variations.
Install
Build with v0
Send the registry bundle into v0 when you want to explore new colorways, copy, or layout directions quickly.
Usage
Control open state from React and pass the same open boolean into PopoverContent so AnimatePresence can run entry and exit motion.
tsx
import { Bell, BellRing } from "lucide-react";
import { useState } from "react";
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/components/ui/popover";
export function UpdatesPopover() {
const [open, setOpen] = useState(false);
return (
<Popover onOpenChange={setOpen} open={open}>
<PopoverTrigger asChild>
<button
className="inline-flex size-10 items-center justify-center text-foreground transition-colors hover:text-neutral-600 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 dark:hover:text-neutral-300"
type="button"
>
<Bell className="size-4.5" />
</button>
</PopoverTrigger>
<PopoverContent className="w-80" open={open}>
<div className="space-y-3">
<div className="flex items-start gap-3">
<span className="mt-0.5 inline-flex size-9 items-center justify-center rounded-full bg-neutral-100 text-neutral-900 dark:bg-neutral-900 dark:text-neutral-100">
<BellRing className="size-4" />
</span>
<div className="space-y-1">
<p className="font-medium">Release reminder</p>
<p className="text-sm text-muted-foreground">
Design review starts in 20 minutes. Final pass on motion and copy is still open.
</p>
</div>
</div>
</div>
</PopoverContent>
</Popover>
);
}API Details
Each item below covers the documented props and the behavior that matters during implementation.