Update Tooltip.tsx

This commit is contained in:
Desktop
2025-11-12 22:34:28 +05:00
parent d254ac3b94
commit 676ac098da

View File

@@ -1,4 +1,5 @@
import { ReactNode } from "react"; import { ReactNode, useState, useRef, useEffect } from "react";
import { createPortal } from "react-dom";
interface TooltipProps { interface TooltipProps {
children: ReactNode; children: ReactNode;
@@ -13,24 +14,95 @@ export const Tooltip: React.FC<TooltipProps> = ({
placement = "top", placement = "top",
className = "", className = "",
}) => { }) => {
const placementClasses = { const [isVisible, setIsVisible] = useState(false);
top: "bottom-full left-1/2 mb-2 -translate-x-1/2 before:top-full before:left-1/2 before:-translate-x-1/2 before:-mt-1 before:border-t-gray-900", const triggerRef = useRef<HTMLDivElement>(null);
bottom: const tooltipRef = useRef<HTMLSpanElement>(null);
"top-full left-1/2 mt-2 -translate-x-1/2 before:bottom-full before:left-1/2 before:-translate-x-1/2 before:-mb-1 before:border-b-gray-900",
left: "right-full top-1/2 mr-2 -translate-y-1/2 before:left-full before:top-1/2 before:-translate-y-1/2 before:-ml-1 before:border-l-gray-900", const getPositionStyle = () => {
right: if (!triggerRef.current) return {};
"left-full top-1/2 ml-2 -translate-y-1/2 before:right-full before:top-1/2 before:-translate-y-1/2 before:-mr-1 before:border-r-gray-900",
const triggerRect = triggerRef.current.getBoundingClientRect();
let top = 0;
let left = 0;
let transform = "";
switch (placement) {
case "top":
top = triggerRect.top - 8; // Will be adjusted by transform
left = triggerRect.left + triggerRect.width / 2;
transform = "translate(-50%, -100%)";
break;
case "bottom":
top = triggerRect.bottom + 8;
left = triggerRect.left + triggerRect.width / 2;
transform = "translateX(-50%)";
break;
case "left":
top = triggerRect.top + triggerRect.height / 2;
left = triggerRect.left - 8;
transform = "translate(-100%, -50%)";
break;
case "right":
top = triggerRect.top + triggerRect.height / 2;
left = triggerRect.right + 8;
transform = "translateY(-50%)";
break;
}
return {
top: `${top}px`,
left: `${left}px`,
transform,
};
}; };
useEffect(() => {
if (isVisible && tooltipRef.current) {
// Force a re-render to update position after tooltip is mounted
const timeout = setTimeout(() => {
if (tooltipRef.current) {
tooltipRef.current.style.visibility = 'visible';
}
}, 0);
return () => clearTimeout(timeout);
}
}, [isVisible]);
return ( return (
<div className={`relative group inline-flex ${className}`} style={{ zIndex: 1 }}> <>
{children} <div
<span ref={triggerRef}
className={`absolute z-[99999] px-3 py-1.5 text-xs font-medium text-white bg-gray-900 rounded-lg opacity-0 pointer-events-none group-hover:opacity-100 transition-opacity whitespace-nowrap before:absolute before:border-4 before:border-transparent before:content-[''] ${placementClasses[placement]}`} className={`relative inline-flex ${className}`}
onMouseEnter={() => setIsVisible(true)}
onMouseLeave={() => setIsVisible(false)}
> >
{text} {children}
</span> </div>
</div> {isVisible &&
createPortal(
<span
ref={tooltipRef}
className="fixed z-[999999] px-3 py-1.5 text-xs font-medium text-white bg-gray-900 rounded-lg pointer-events-none whitespace-nowrap"
style={getPositionStyle()}
>
{text}
{/* Arrow */}
<span
className={`absolute ${
placement === "top"
? "top-full left-1/2 -translate-x-1/2 -mt-1 w-0 h-0 border-l-[6px] border-l-transparent border-r-[6px] border-r-transparent border-t-[6px] border-t-gray-900"
: placement === "bottom"
? "bottom-full left-1/2 -translate-x-1/2 -mb-1 w-0 h-0 border-l-[6px] border-l-transparent border-r-[6px] border-r-transparent border-b-[6px] border-b-gray-900"
: placement === "left"
? "left-full top-1/2 -translate-y-1/2 -ml-1 w-0 h-0 border-t-[6px] border-t-transparent border-b-[6px] border-b-transparent border-l-[6px] border-l-gray-900"
: "right-full top-1/2 -translate-y-1/2 -mr-1 w-0 h-0 border-t-[6px] border-t-transparent border-b-[6px] border-b-transparent border-r-[6px] border-r-gray-900"
}`}
/>
</span>,
document.body
)}
</>
); );
}; };