"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;
};
export const Tooltip = ({
open,
defaultOpen,
side = "bottom",
delayDuration = 200,
sideOffset,
align,
onOpenChange,
title,
tooltipClassName,
tooltipStyle,
children,
asChild = false,
container,
className,
style
}: TooltipProps) => {
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);
}
}`;