"use client";
import React, { useState, useRef, useEffect } from "react";
import { Info } from "lucide-react";
import { cn } from "@/lib/utils/cn";
interface InfoButtonProps {
content: string | React.ReactNode;
title?: string;
position?: "top" | "bottom" | "left" | "right";
className?: string;
/** Smaller, more subtle variant for inline use next to labels */
variant?: "default" | "subtle";
}
export const InfoButton: React.FC<InfoButtonProps> = ({
content,
title,
position = "top",
className = "",
variant = "subtle",
}) => {
const [isOpen, setIsOpen] = useState(false);
const buttonRef = useRef<HTMLButtonElement>(null);
const tooltipRef = useRef<HTMLDivElement>(null);
useEffect(() => {
const handleClickOutside = (event: MouseEvent) => {
if (
tooltipRef.current &&
buttonRef.current &&
!tooltipRef.current.contains(event.target as Node) &&
!buttonRef.current.contains(event.target as Node)
) {
setIsOpen(false);
}
};
if (isOpen) {
document.addEventListener("mousedown", handleClickOutside);
}
return () => {
document.removeEventListener("mousedown", handleClickOutside);
};
}, [isOpen]);
const positionClasses = {
top: "bottom-full left-1/2 -translate-x-1/2 mb-2",
bottom: "top-full left-1/2 -translate-x-1/2 mt-2",
left: "right-full top-1/2 -translate-y-1/2 mr-2",
right: "left-full top-1/2 -translate-y-1/2 ml-2",
};
const isBottom = position === "bottom";
const isTop = position === "top";
return (
<span className={cn("relative inline-flex", className)}>
<button
ref={buttonRef}
type="button"
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
setIsOpen(!isOpen);
}}
className={cn(
"inline-flex items-center justify-center rounded-full transition-all duration-200 focus:outline-none focus:ring-2 focus:ring-blue-400/50 focus:ring-offset-1",
variant === "subtle"
? "w-4 h-4 text-gray-400 hover:text-gray-600 hover:bg-gray-100"
: "w-5 h-5 bg-gray-100 text-gray-500 hover:bg-gray-200 hover:text-gray-700"
)}
aria-label="Show information"
>
<Info className="w-3 h-3" strokeWidth={2.25} />
</button>
{isOpen && (
<div
ref={tooltipRef}
className={cn(
"absolute z-[100] w-72 sm:w-80 max-w-[calc(100vw-2rem)]",
positionClasses[position]
)}
>
<div
className={cn(
"relative rounded-xl border border-gray-200/90 bg-white/95 shadow-lg backdrop-blur-sm",
"info-tooltip-enter"
)}
>
<div className="max-h-[70vh] overflow-y-auto rounded-xl p-4">
{title && (
<h3 className="text-sm font-semibold text-gray-900 mb-2 pr-6">
{title}
</h3>
)}
<div className="text-sm leading-relaxed text-gray-600">
{typeof content === "string" ? (
<p className="whitespace-pre-line">{content}</p>
) : (
content
)}
</div>
</div>
{/* Arrow */}
<div
className={cn(
"absolute w-2 h-2 rotate-45 border border-gray-200/90 bg-white/95",
isBottom && "top-0 left-1/2 -translate-x-1/2 -translate-y-px border-t-transparent border-l-transparent",
isTop && "bottom-0 left-1/2 -translate-x-1/2 translate-y-px border-b-transparent border-r-transparent",
position === "left" && "right-0 top-1/2 -translate-y-1/2 translate-x-px border-r-transparent border-b-transparent",
position === "right" && "left-0 top-1/2 -translate-y-1/2 -translate-x-px border-l-transparent border-t-transparent"
)}
/>
</div>
</div>
)}
</span>
);
}