import {
arrow,
autoUpdate,
flip,
offset,
Placement,
shift,
useFloating,
useHover,
useInteractions,
useRole,
} from '@floating-ui/react-dom-interactions'
import { Transition } from '@headlessui/react'
import { ReactNode, useRef, useState } from 'react'
// See https://floating-ui.com/docs/react-dom
export function Tooltip(props: {
text: string | false | undefined | null
children: ReactNode
className?: string
placement?: Placement
noTap?: boolean
noFade?: boolean
}) {
const { text, children, className, placement = 'top', noTap, noFade } = props
const arrowRef = useRef(null)
const [open, setOpen] = useState(false)
const { x, y, reference, floating, strategy, middlewareData, context } =
useFloating({
open,
onOpenChange: setOpen,
whileElementsMounted: autoUpdate,
placement,
middleware: [
offset(8),
flip(),
shift({ padding: 4 }),
arrow({ element: arrowRef }),
],
})
const { x: arrowX, y: arrowY } = middlewareData.arrow ?? {}
const { getReferenceProps, getFloatingProps } = useInteractions([
useHover(context, { mouseOnly: noTap }),
useRole(context, { role: 'tooltip' }),
])
// which side of tooltip arrow is on. like: if tooltip is top-left, arrow is on bottom of tooltip
const arrowSide = {
top: 'bottom',
right: 'left',
bottom: 'top',
left: 'right ',
}[placement.split('-')[0]] as string
return text ? (
<>
{children}
{/* conditionally render tooltip and fade in/out */}
{text}
>
) : (
<>{children}>
)
}