import React, { forwardRef, useContext, useLayoutEffect, useState } from 'react' import { Tooltip as RACTooltip, TooltipContext, TooltipTriggerStateContext, useContextProps, type TooltipProps as RACTooltipProps, } from 'react-aria-components' import { VisuallyHidden } from '~components/VisuallyHidden' import { useReversedColors } from '~components/utils' import { mergeClassNames } from '~components/utils/mergeClassNames' import { OverlayArrow } from './OverlayArrow' import styles from './Tooltip.module.css' export { TooltipContext } export type TooltipProps = Omit & { /** * The additional offset applied along the main axis between the element and its * anchor element. * @default 8 */ offset?: number /** * The placement of the tooltip relative to the trigger. * + we're intentionally limiting the placement options to rtl friendly ones (start, end, top, bottom) */ placement?: | 'bottom' | 'bottom start' | 'bottom end' | 'top' | 'top start' | 'top end' | 'start' | 'start top' | 'start bottom' | 'end' | 'end top' | 'end bottom' } /** * A tooltip displays a description of an element on hover or focus. */ export const Tooltip = forwardRef( ({ children, className, ...props }, ref): JSX.Element => { const [{ triggerRef }] = useContextProps({ children, className, ...props }, ref, TooltipContext) const contextState = useContext(TooltipTriggerStateContext) const reverseColors = useReversedColors() const [shouldInlineHiddenContent, setShouldInlineHiddenContent] = useState(false) useLayoutEffect(() => { setShouldInlineHiddenContent( !!triggerRef?.current?.getAttribute('data-inline-hidden-content'), ) }, [triggerRef]) return ( <> {(renderProps) => ( <> {typeof children === 'function' ? children(renderProps) : children} )} {shouldInlineHiddenContent ? ( {typeof children === 'function' ? contextState && children({ placement: 'center', isEntering: false, isExiting: false, state: contextState, defaultChildren: undefined, }) : children} ) : null} ) }, ) Tooltip.displayName = 'Tooltip'