"use client"; import React from "react"; import * as TooltipPrimitive from "@radix-ui/react-tooltip"; import { cls } from "../util"; import { useInjectStyles } from "../hooks"; import { usePortalContainer } from "../hooks/PortalContainerContext"; export type TooltipProps = { open?: boolean, defaultOpen?: boolean, onOpenChange?: (open: boolean) => void, side?: "top" | "bottom" | "left" | "right", align?: "start" | "center" | "end", sideOffset?: number, title?: string | React.ReactNode, delayDuration?: number; asChild?: boolean; tooltipClassName?: string, tooltipStyle?: React.CSSProperties; children: React.ReactNode, className?: string, container?: HTMLElement, style?: React.CSSProperties; } & Omit, "title">; export const Tooltip = React.forwardRef(({ open, defaultOpen, side = "bottom", delayDuration = 200, sideOffset, align, onOpenChange, title, tooltipClassName, tooltipStyle, children, asChild = false, container, className, style, ...props }, ref) => { useInjectStyles("Tooltip", styles); // Get the portal container from context const contextContainer = usePortalContainer(); // Prioritize manual prop, fallback to context container const finalContainer = (container ?? contextContainer ?? undefined) as HTMLElement | undefined; if (!title) return <>{children}; const trigger = asChild ? {children} :
{children}
; return ( {trigger} {title} ); }); const styles = ` .TooltipContent { animation-duration: 220ms; animation-timing-function: cubic-bezier(0.16, 1, 0.3, 1); will-change: transform, opacity; } .TooltipContent[data-state='delayed-open'][data-side='top'] { animation-name: slideDownAndFade; } .TooltipContent[data-state='delayed-open'][data-side='right'] { animation-name: slideLeftAndFade; } .TooltipContent[data-state='delayed-open'][data-side='bottom'] { animation-name: slideUpAndFade; } .TooltipContent[data-state='delayed-open'][data-side='left'] { animation-name: slideRightAndFade; } @keyframes slideUpAndFade { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: translateY(0); } } @keyframes slideRightAndFade { from { opacity: 0; transform: translateX(-4px); } to { opacity: 1; transform: translateX(0); } } @keyframes slideDownAndFade { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: translateY(0); } } @keyframes slideLeftAndFade { from { opacity: 0; transform: translateX(4px); } to { opacity: 1; transform: translateX(0); } }`;