import { Transition } from "@headlessui/react"; import { Placement } from "@popperjs/core"; import clsx from "clsx"; import * as React from "react"; import ReactDOM from "react-dom"; import { usePopper } from "react-popper"; import { useClickAway, useDebounce } from "react-use"; import { preventWidows } from "utils/prevent-widows"; export interface TooltipProps { placement?: Placement; children?: React.ReactNode; content?: React.ReactNode; disabled?: boolean; className?: string; } const Tooltip: React.VoidFunctionComponent = ({ placement, className, children, disabled, content, }) => { const [referenceElement, setReferenceElement] = React.useState(null); const [popperElement, setPopperElement] = React.useState(null); const [arrowElement, setArrowElement] = React.useState(null); const { styles, attributes } = usePopper(referenceElement, popperElement, { placement, modifiers: [ { name: "offset", options: { offset: [0, 14], }, }, { name: "arrow", options: { element: arrowElement, padding: 5 } }, ], }); const [isVisible, setIsVisible] = React.useState(false); const [debouncedValue, setDebouncedValue] = React.useState(false); const [, cancel] = useDebounce( () => { setDebouncedValue(isVisible); }, 300, [isVisible], ); const portal = document.getElementById("portal"); const [key, setKey] = React.useState(0); React.useEffect(() => { setKey((k) => k + 1); }, [content]); const ref = React.useRef(null); useClickAway(ref, () => { setIsVisible(false); }); if (disabled) { return <>{children}; } return ( <>
{ setIsVisible(true); }} onMouseLeave={() => { setIsVisible(false); setDebouncedValue(false); cancel(); }} ref={(el) => { setReferenceElement(el); ref.current = el; }} > {children}
{portal && debouncedValue ? ReactDOM.createPortal(
{typeof content === "string" ? preventWidows(content) : content}
, portal, ) : null} ); }; export default Tooltip;