import { Button } from "@/components/ui/button";
import {
Popover,
PopoverContent,
PopoverDescription,
PopoverHeader,
PopoverTitle,
PopoverTrigger,
} from "@/components/ui/popover";
export function PopoverDemo() {
return (
<Popover>
<PopoverTrigger render={<Button variant="outline">Open</Button>} />
<PopoverContent className="w-80">
<PopoverHeader>
<PopoverTitle>Event Details</PopoverTitle>
<PopoverDescription>
Join us for an exclusive workshop on modern web development. Click
below to register or learn more.
</PopoverDescription>
</PopoverHeader>
</PopoverContent>
</Popover>
);
}Installation
npx shadcn@latest add @eo-n/popoverUsage
Import all parts and piece them together.
import {
Popover,
PopoverContent,
PopoverDescription,
PopoverTitle,
PopoverTrigger,
} from "@/components/ui/popover";<Popover>
<PopoverTrigger>Open</PopoverTrigger>
<PopoverContent>
<PopoverTitle>Popover Title</PopoverTitle>
<PopoverDescription>
This is some content inside the popover.
</PopoverDescription>
</PopoverContent>
</Popover>Examples
Open On Hover
import { Dot } from "lucide-react";
import { Button } from "@/components/ui/button";
import {
Popover,
PopoverContent,
PopoverDescription,
PopoverHeader,
PopoverTitle,
PopoverTrigger,
} from "@/components/ui/popover";
export function PopoverHover() {
return (
<Popover>
<PopoverTrigger
openOnHover
render={<Button variant="outline">Event Details</Button>}
/>
<PopoverContent className="w-[325px] space-y-3">
<PopoverHeader>
<PopoverTitle>React Summit 2025</PopoverTitle>
<PopoverDescription>
Join us for the biggest React conference of the year featuring
workshops, keynotes, and networking opportunities.
</PopoverDescription>
</PopoverHeader>
<div className="mb-3 space-y-2">
<div className="flex items-start">
<Dot className="mt-0.5 h-4 w-4 flex-shrink-0" />
<p className="ml-2 text-sm">20+ speakers from top tech companies</p>
</div>
<div className="flex items-start">
<Dot className="mt-0.5 h-4 w-4 flex-shrink-0" />
<p className="ml-2 text-sm">Hands-on workshops on React 20</p>
</div>
<div className="flex items-start">
<Dot className="mt-0.5 h-4 w-4 flex-shrink-0" />
<p className="ml-2 text-sm">
Early bird pricing available until Feb 15
</p>
</div>
</div>
<Button className="w-full">View Full Schedule</Button>
</PopoverContent>
</Popover>
);
}Animated Popovers
import * as React from "react";
import { Bell, Settings2 } from "lucide-react";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import {
Popover,
PopoverContent,
PopoverCreateHandle,
PopoverDescription,
PopoverHeader,
PopoverTitle,
PopoverTrigger,
} from "@/components/ui/popover";
const demoPopover = PopoverCreateHandle<React.ComponentType>();
function NotificationsContent() {
return (
<div className="w-60">
<PopoverHeader>
<PopoverTitle>Notifications</PopoverTitle>
<PopoverDescription>You have no new notifications.</PopoverDescription>
</PopoverHeader>
<div className="text-muted-foreground mt-4 grid place-items-center rounded-md border border-dashed py-12 text-sm">
No new notifications
</div>
</div>
);
}
function SettingsContent() {
return (
<div className="w-80">
<PopoverHeader>
<PopoverTitle>Settings</PopoverTitle>
<PopoverDescription>Manage your account settings.</PopoverDescription>
</PopoverHeader>
<div className="mt-4 grid gap-4">
<div className="grid gap-2">
<Label htmlFor="username">Username</Label>
<Input
id="username"
autoFocus
defaultValue="@aeonzz"
className="col-span-2 h-8"
/>
</div>
<div className="grid gap-2">
<Label htmlFor="domain">Domain</Label>
<Input
id="domain"
defaultValue="aeonz.dev"
className="col-span-2 h-8"
/>
</div>
</div>
</div>
);
}
export function PopoverAnimated() {
return (
<div className="flex gap-2">
<PopoverTrigger
handle={demoPopover}
payload={NotificationsContent}
render={(props, state) => (
<Button variant="outline" size="icon" active={state.open} {...props}>
<Bell />
<span className="sr-only">Notifications</span>
</Button>
)}
/>
<PopoverTrigger
handle={demoPopover}
payload={SettingsContent}
render={(props, state) => (
<Button variant="outline" active={state.open} size="icon" {...props}>
<Settings2 />
<span className="sr-only">Settings</span>
</Button>
)}
/>
<Popover handle={demoPopover}>
{({ payload: Payload }) => (
<PopoverContent>
{Payload !== undefined && <Payload />}
</PopoverContent>
)}
</Popover>
</div>
);
}