Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 | 17x 17x 17x 6x 6x 17x 3x 17x 9x 9x 17x 3x | import { useState, useRef, useEffect, type ReactNode } from "react";
import { Info } from "lucide-react";
import { cn } from "../../lib/utils";
interface TooltipProps {
content: string;
children?: ReactNode;
className?: string;
}
export function Tooltip({ content, children, className }: TooltipProps) {
const [isVisible, setIsVisible] = useState(false);
const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);
const show = () => {
if (timeoutRef.current) clearTimeout(timeoutRef.current);
setIsVisible(true);
};
const hide = () => {
timeoutRef.current = setTimeout(() => setIsVisible(false), 150);
};
useEffect(() => {
return () => {
if (timeoutRef.current) clearTimeout(timeoutRef.current);
};
}, []);
return (
<span className={cn("relative inline-flex items-center", className)}>
<button
type="button"
onMouseEnter={show}
onMouseLeave={hide}
onFocus={show}
onBlur={hide}
aria-label="More info"
className="inline-flex cursor-help"
>
{children || (
<Info className="h-4 w-4 text-foreground-subtle hover:text-foreground-muted transition-colors" />
)}
</button>
{isVisible && (
<span
role="tooltip"
className="absolute bottom-full left-1/2 -translate-x-1/2 mb-2 px-3 py-2 text-xs text-foreground-inverse bg-foreground-default rounded-md shadow-lg whitespace-normal max-w-[240px] z-50 pointer-events-none"
>
{content}
<span className="absolute top-full left-1/2 -translate-x-1/2 -mt-px border-4 border-transparent border-t-foreground-default" />
</span>
)}
</span>
);
}
interface HelpTextProps {
children: ReactNode;
className?: string;
}
export function HelpText({ children, className }: HelpTextProps) {
return (
<p className={cn("mt-1 text-xs text-foreground-subtle", className)}>
{children}
</p>
);
}
|