enhanced ui

This commit is contained in:
Desktop
2025-11-12 21:37:41 +05:00
parent 9692a5ed2e
commit fa47cfa7ff
12 changed files with 2341 additions and 428 deletions

View File

@@ -0,0 +1,88 @@
import { ReactNode, useState, useRef, useEffect } from "react";
interface EnhancedTooltipProps {
children: ReactNode;
content: ReactNode | string;
placement?: "top" | "bottom" | "left" | "right";
className?: string;
delay?: number;
}
export const EnhancedTooltip: React.FC<EnhancedTooltipProps> = ({
children,
content,
placement = "top",
className = "",
delay = 200,
}) => {
const [isVisible, setIsVisible] = useState(false);
const [position, setPosition] = useState({ top: 0, left: 0 });
const tooltipRef = useRef<HTMLDivElement>(null);
const triggerRef = useRef<HTMLDivElement>(null);
const timeoutRef = useRef<NodeJS.Timeout>();
const placementClasses = {
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",
bottom:
"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",
right:
"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 handleMouseEnter = () => {
if (timeoutRef.current) {
clearTimeout(timeoutRef.current);
}
timeoutRef.current = setTimeout(() => {
setIsVisible(true);
}, delay);
};
const handleMouseLeave = () => {
if (timeoutRef.current) {
clearTimeout(timeoutRef.current);
}
setIsVisible(false);
};
useEffect(() => {
return () => {
if (timeoutRef.current) {
clearTimeout(timeoutRef.current);
}
};
}, []);
return (
<div
ref={triggerRef}
className={`relative inline-flex ${className}`}
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
>
{children}
{isVisible && (
<div
ref={tooltipRef}
className={`
absolute z-50 px-3 py-2 text-xs font-medium text-white bg-gray-900 rounded-lg
opacity-100 pointer-events-none transition-opacity duration-200
whitespace-normal max-w-xs shadow-lg
before:absolute before:border-4 before:border-transparent before:content-['']
${placementClasses[placement]}
`}
onMouseEnter={() => setIsVisible(true)}
onMouseLeave={() => setIsVisible(false)}
>
{typeof content === "string" ? (
<span>{content}</span>
) : (
<div className="text-white">{content}</div>
)}
</div>
)}
</div>
);
};