"use client"; import cx from "classnames"; import React from "react"; import { useHydrationSafeId, useStatic } from "../../utils/hooks"; import TooltipStatic from "./Tooltip.static"; const CLASS_ROOT = "tooltip"; export type TooltipPlacement = | "auto" | "top" | "top-start" | "top-end" | "bottom" | "bottom-start" | "bottom-end" | "right" | "right-start" | "right-end" | "left" | "left-start" | "left-end"; export interface TooltipProps extends React.HTMLAttributes { /** Tooltip dialog content */ dialog?: React.ReactNode; /** Tooltip ID */ id?: string; /** Preferred placement, if there is enough room. Defaults to top. */ placement?: TooltipPlacement; /** Custom trigger renderer. Passes required aria attributes and children in an object as argument. */ renderTrigger?: (props: { "data-tooltip-trigger": true; "aria-describedby": string; "aria-owns": string; children: React.ReactNode; }) => React.ReactNode; /** Render dialog as */ tag?: "span"; // restrict tag to "span" for ref compatibility /** Additional CSS classes */ className?: string; children?: React.ReactNode; } const Tooltip: React.FC = ({ dialog, id, placement, tag = "span", // default and only allowed tag is "span" className, renderTrigger, children, ...other }) => { const currentId = useHydrationSafeId(id); const classes = cx(CLASS_ROOT, className); const Tag = tag; const [dialogRef] = useStatic(TooltipStatic as any, { removeDialogOnDestroy: true, }); const triggerProps = { "data-tooltip-trigger": true, "aria-describedby": currentId, "aria-owns": currentId, children, } as const; return ( <> {renderTrigger ? ( renderTrigger(triggerProps) ) : ( )}