import { useEffect, useRef, useState, type ReactElement } from 'react' import { createPortal } from 'react-dom' import styles from './Tooltip.module.css' interface TooltipProps { label: string children: ReactElement } export function Tooltip({ label, children }: TooltipProps) { const wrapRef = useRef(null) const [visible, setVisible] = useState(false) const [coords, setCoords] = useState({ top: 0, left: 0 }) function updatePosition() { const el = wrapRef.current if (!el) return const rect = el.getBoundingClientRect() setCoords({ top: rect.top - 8, left: rect.left + rect.width / 2, }) } function show() { updatePosition() setVisible(true) } function hide() { setVisible(false) } useEffect(() => { if (!visible) return function onReposition() { updatePosition() } window.addEventListener('scroll', onReposition, true) window.addEventListener('resize', onReposition) return () => { window.removeEventListener('scroll', onReposition, true) window.removeEventListener('resize', onReposition) } }, [visible]) return ( { if (!wrapRef.current?.contains(e.relatedTarget as Node | null)) { hide() } }} > {children} {visible ? createPortal( {label} , document.body, ) : null} ) }