70 lines
2.4 KiB
React
70 lines
2.4 KiB
React
import React, { useState, useRef, useEffect } from 'react';
|
|
import { createPortal } from 'react-dom';
|
|
import { Info } from 'lucide-react';
|
|
|
|
export const InfoTooltip = ({ text }) => {
|
|
const [isVisible, setIsVisible] = useState(false);
|
|
const [coords, setCoords] = useState({ top: 0, left: 0 });
|
|
const triggerRef = useRef(null);
|
|
|
|
const updatePosition = () => {
|
|
if (triggerRef.current) {
|
|
const rect = triggerRef.current.getBoundingClientRect();
|
|
setCoords({
|
|
top: rect.top - 10, // Default to slightly above
|
|
left: rect.left + rect.width / 2
|
|
});
|
|
}
|
|
};
|
|
|
|
const handleMouseEnter = () => {
|
|
updatePosition();
|
|
setIsVisible(true);
|
|
};
|
|
|
|
const handleMouseLeave = () => {
|
|
setIsVisible(false);
|
|
};
|
|
|
|
useEffect(() => {
|
|
if (isVisible) {
|
|
window.addEventListener('scroll', updatePosition);
|
|
window.addEventListener('resize', updatePosition);
|
|
}
|
|
return () => {
|
|
window.removeEventListener('scroll', updatePosition);
|
|
window.removeEventListener('resize', updatePosition);
|
|
};
|
|
}, [isVisible]);
|
|
|
|
return (
|
|
<>
|
|
<div
|
|
ref={triggerRef}
|
|
onMouseEnter={handleMouseEnter}
|
|
onMouseLeave={handleMouseLeave}
|
|
className="cursor-help inline-flex items-center justify-center ml-2"
|
|
>
|
|
<Info size={14} className="text-zinc-400" />
|
|
</div>
|
|
|
|
{isVisible && createPortal(
|
|
<div
|
|
className="fixed z-[9999] w-48 p-2 bg-zinc-900 text-xs text-zinc-100 rounded-lg shadow-xl border border-zinc-700 text-center pointer-events-none transition-opacity duration-200"
|
|
style={{
|
|
top: coords.top,
|
|
left: coords.left,
|
|
transform: 'translate(-50%, -100%)', // Centered and above
|
|
opacity: 1
|
|
}}
|
|
>
|
|
{text}
|
|
{/* Tiny triangle pointer */}
|
|
<div className="absolute left-1/2 -translate-x-1/2 top-full w-0 h-0 border-l-[6px] border-l-transparent border-r-[6px] border-r-transparent border-t-[6px] border-t-zinc-900"></div>
|
|
</div>,
|
|
document.body
|
|
)}
|
|
</>
|
|
);
|
|
};
|