import React, { ReactNode, useState, useEffect, useRef, createContext, useContext, } from "react"; import { createPortal } from "react-dom"; // Create a context for the tooltip group const TooltipGroupContext = createContext<{ setGroupHovered: React.Dispatch>; groupHovered: boolean; hoverCountRef: React.MutableRefObject; }>({ setGroupHovered: () => {}, groupHovered: false, hoverCountRef: { current: false }, }); export const TooltipGroup: React.FC<{ children: React.ReactNode; gap?: string; }> = ({ children, gap }) => { const [groupHovered, setGroupHovered] = useState(false); const hoverCountRef = useRef(false); return (
{children}
); }; export const CustomTooltip = ({ content, children, large, light, citation, line, medium, wrap, showTick = false, delay = 500, position = "bottom", disabled = false, className, }: { medium?: boolean; content: string | ReactNode; children: JSX.Element; large?: boolean; line?: boolean; light?: boolean; showTick?: boolean; delay?: number; wrap?: boolean; citation?: boolean; position?: "top" | "bottom"; disabled?: boolean; className?: string; }) => { const [isVisible, setIsVisible] = useState(false); const [tooltipPosition, setTooltipPosition] = useState({ top: 0, left: 0 }); const timeoutRef = useRef(null); const triggerRef = useRef(null); const { groupHovered, setGroupHovered, hoverCountRef } = useContext(TooltipGroupContext); const showTooltip = () => { hoverCountRef.current = true; const showDelay = groupHovered ? 0 : delay; timeoutRef.current = setTimeout(() => { setIsVisible(true); setGroupHovered(true); updateTooltipPosition(); }, showDelay); }; const hideTooltip = () => { if (timeoutRef.current) { clearTimeout(timeoutRef.current); } hoverCountRef.current = false; setIsVisible(false); setTimeout(() => { if (!hoverCountRef.current) { setGroupHovered(false); } }, 100); }; const updateTooltipPosition = () => { if (triggerRef.current) { const rect = triggerRef.current.getBoundingClientRect(); const scrollX = window.scrollX || window.pageXOffset; const scrollY = window.scrollY || window.pageYOffset; setTooltipPosition({ top: (position === "top" ? rect.top - 10 : rect.bottom + 10) + scrollY, left: rect.left + rect.width / 2 + scrollX, }); } }; useEffect(() => { return () => { if (timeoutRef.current) { clearTimeout(timeoutRef.current); } }; }, []); return ( <> {children} {isVisible && !disabled && createPortal(
{showTick && (
)}
{content}
, document.body )} ); };