Popover UI elements are common in web apps, offering extra info or options when users interact with something. Usually, developers rely on npm libraries for Popovers, but these increase the projectβs bundle size. In this article, Iβll guide you through building a lightweight, reusable Popover component using React and Tailwind CSS β with both click and hover triggers β so you can keep your app fast and flexible without extra dependencies.
The Popover component:
// @flow strict
"use client"
import { useEffect, useRef, useState } from "react";
function ReactPopover({
children,
content,
trigger = "click"
}) {
const [show, setShow] = useState(false);
const wrapperRef = useRef(null);
const handleMouseOver = () => {
if (trigger === "hover") {
setShow(true);
};
};
const handleMouseLeft = () => {
if (trigger === "hover") {
setShow(false);
};
};
useEffect(() => {
function handleClickOutside(event) {
if (wrapperRef.current && !wrapperRef.current.contains(event.target)) {
setShow(false);
}
}
if (show) {
// Bind the event listener
document.addEventListener("mousedown", handleClickOutside);
return () => {
// Unbind the event listener on clean up
document.removeEventListener("mousedown", handleClickOutside);
};
}
}, [show, wrapperRef]);
return (
<div
ref={wrapperRef}
onMouseEnter={handleMouseOver}
onMouseLeave={handleMouseLeft}
className="w-fit h-fit relative flex justify-center">
<div
onClick={() => setShow(!show)
}
>
{children}
</div>
<div
hidden={!show}
className="min-w-fit w-[200px] h-fit absolute bottom-[100%] z-50 transition-all">
<div className="rounded bg-white p-3 shadow-[10px_30px_150px_rgba(46,38,92,0.25)] mb-[10px]">
{content}
</div>
</div>
</div>
);
};
export default ReactPopover;
In this component the trigger default value is click and you can pass hover as an attribute. When you click outside of the Popover, the Popover will be closed.
Use the Popover component:
import ReactPopover from "@/components/common/react-popover";
const Page = () => {
return (
<div className="w-screen h-screen flex justify-center items-center gap-4">
<ReactPopover
content={
<p>This Content Will be render in Popover.</p>
}
>
<button className="bg-indigo-500 px-4 py-1.5 border rounded text-white">
Click me
</button>
</ReactPopover>
<ReactPopover
trigger="hover"
content={
<p>This Content Will be render in Popover.</p>
}
>
<button className="bg-indigo-500 px-4 py-1.5 border rounded text-white">
Hover me
</button>
</ReactPopover>
</div>
);
};
export default Page;
Top comments (0)