import React, { CSSProperties, ReactNode, RefObject, useState } from 'react' import { usePopper } from 'react-popper' import classNames from 'classnames' import { createPortal } from 'react-dom' export function Tooltip({ children, info, className, onClick, boundary, containerRef }: { info: ReactNode children: ReactNode className?: string onClick?: () => void /** if provided, the tooltip is confined to the particular element */ boundary?: HTMLElement | null /** if defined, the tooltip is rendered in a portal to this element */ containerRef?: RefObject }) { const [visible, setVisible] = useState(false) const [referenceElement, setReferenceElement] = useState(null) const [popperElement, setPopperElement] = useState( null ) const [arrowElement, setArrowElement] = useState(null) const { styles, attributes } = usePopper(referenceElement, popperElement, { placement: 'top', modifiers: [ { name: 'arrow', options: { element: arrowElement } }, { name: 'offset', options: { offset: [0, 4] } }, ...(boundary ? [ { name: 'preventOverflow', options: { boundary: boundary } } ] : []) ] }) return (
setVisible(true)} onMouseLeave={() => setVisible(false)} onClick={onClick} > {children}
{info && visible && ( {info} )}
) } function TooltipMessage({ containerRef, popperStyle, popperAttributes, setPopperElement, setArrowElement, arrowStyle, children }: { containerRef?: RefObject popperStyle: CSSProperties arrowStyle: CSSProperties popperAttributes?: Record setPopperElement: (element: HTMLDivElement) => void setArrowElement: (element: HTMLDivElement) => void children: ReactNode }) { const messageElement = (
{children}
) if (containerRef) { if (containerRef.current) { return createPortal(messageElement, containerRef.current) } else { return null } } return messageElement }