Popover
Overlay & FeedbackFloating content panel anchored to a trigger.
Preview
Usage
example.jsx
import { Popover } from "@/components/ui/popover";
export default function Example() {
return <Popover />;
}Source Code
Copy this file into components/ui/popover.jsx in your project.
popover.jsx
"use client";
import { forwardRef, useState, useRef, useEffect } from "react";
import { cn } from "@/lib/utils";
const Popover = forwardRef(({ className, trigger, children, align = "center", ...props }, ref) => {
const [open, setOpen] = useState(false);
const popoverRef = useRef(null);
useEffect(() => {
const handler = (e) => { if (popoverRef.current && !popoverRef.current.contains(e.target)) setOpen(false); };
document.addEventListener("mousedown", handler);
return () => document.removeEventListener("mousedown", handler);
}, []);
return (
<div ref={(el) => { popoverRef.current = el; if (typeof ref === "function") ref(el); else if (ref) ref.current = el; }} className={cn("relative inline-block", className)} {...props}>
<div onClick={() => setOpen(!open)}>{trigger}</div>
{open && (
<div className={cn("absolute z-50 mt-2 w-72 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none animate-in fade-in-0 zoom-in-95",
align === "start" && "left-0",
align === "center" && "left-1/2 -translate-x-1/2",
align === "end" && "right-0"
)}>
{children}
</div>
)}
</div>
);
});
Popover.displayName = "Popover";
export { Popover };
Quick Install
Make sure you have the cn() utility set up. It requires clsx and tailwind-merge.
npm install clsx tailwind-merge