/** * Tooltip live animation preview for the extension admin settings UI. */ import React from "react"; import type { ExtensionTooltipPosition } from "./presentationTypes"; import { coerceInt } from "../constants"; import { getExtensionTooltipAnimationDuration } from "./presentationConstants"; export type TooltipAnimationLivePreviewProps = { animation: string; tooltipPosition: ExtensionTooltipPosition; tooltipBgColor: string; tooltipTextColor: string; tooltipFontSize: number | string; tooltipFontFamily: string; fadeInEnabled: boolean; fadeOutEnabled: boolean; }; /** * Live tooltip preview with full positioning support. */ export function TooltipAnimationLivePreview({ animation, tooltipPosition, tooltipBgColor, tooltipTextColor, tooltipFontSize, tooltipFontFamily, fadeInEnabled, fadeOutEnabled, }: TooltipAnimationLivePreviewProps): React.ReactElement { const [tooltipKey, setTooltipKey] = React.useState(0); const [isHovered, setIsHovered] = React.useState(false); const [isHiding, setIsHiding] = React.useState(false); const hideTimeoutRef = React.useRef(null); React.useEffect(() => { return () => { if (hideTimeoutRef.current) { clearTimeout(hideTimeoutRef.current); } }; }, []); const handleMouseLeave = () => { if (fadeOutEnabled) { setIsHiding(true); hideTimeoutRef.current = window.setTimeout(() => { setIsHovered(false); setIsHiding(false); }, getExtensionTooltipAnimationDuration(animation)); } else { setIsHovered(false); setIsHiding(false); } }; const handleMouseEnter = () => { if (hideTimeoutRef.current) { clearTimeout(hideTimeoutRef.current); hideTimeoutRef.current = null; } setIsHiding(false); setIsHovered(true); setTooltipKey((prev) => prev + 1); }; const tooltipStyles: React.CSSProperties = { backgroundColor: tooltipBgColor, color: tooltipTextColor, fontSize: `${coerceInt(tooltipFontSize, 12)}px`, fontFamily: tooltipFontFamily && tooltipFontFamily !== "inherit" ? tooltipFontFamily : undefined, }; const tooltipPositionClasses = tooltipPosition === "bottom" ? "bwvs:top-full bwvs:left-1/2 bwvs:mt-2" : tooltipPosition === "left" ? "bwvs:right-full bwvs:top-1/2 bwvs:mr-2" : tooltipPosition === "right" ? "bwvs:left-full bwvs:top-1/2 bwvs:ml-2" : "bwvs:bottom-full bwvs:left-1/2 bwvs:mb-2"; const tooltipTransform = tooltipPosition === "left" || tooltipPosition === "right" ? "translateY(-50%)" : "translateX(-50%)"; const arrowBaseClass = tooltipPosition === "bottom" ? "bwvs:absolute bwvs:bottom-full bwvs:left-1/2 bwvs:w-0 bwvs:h-0" : tooltipPosition === "left" ? "bwvs:absolute bwvs:left-full bwvs:top-1/2 bwvs:w-0 bwvs:h-0" : tooltipPosition === "right" ? "bwvs:absolute bwvs:right-full bwvs:top-1/2 bwvs:w-0 bwvs:h-0" : "bwvs:absolute bwvs:top-full bwvs:left-1/2 bwvs:w-0 bwvs:h-0"; const arrowStyle: React.CSSProperties = tooltipPosition === "bottom" ? { transform: "translateX(-50%)", borderLeft: "6px solid transparent", borderRight: "6px solid transparent", borderBottom: `6px solid ${tooltipBgColor}`, } : tooltipPosition === "left" ? { transform: "translateY(-50%)", borderTop: "6px solid transparent", borderBottom: "6px solid transparent", borderLeft: `6px solid ${tooltipBgColor}`, } : tooltipPosition === "right" ? { transform: "translateY(-50%)", borderTop: "6px solid transparent", borderBottom: "6px solid transparent", borderRight: `6px solid ${tooltipBgColor}`, } : { transform: "translateX(-50%)", borderLeft: "6px solid transparent", borderRight: "6px solid transparent", borderTop: `6px solid ${tooltipBgColor}`, }; return (
{isHovered && (() => { const animateClass = animation !== "none" && fadeInEnabled && !isHiding ? `b3-wvs-animate-tooltip-${animation}` : ""; const animateOutClass = animation !== "none" && isHiding && fadeOutEnabled ? `b3-wvs-animate-tooltip-${animation}-out` : ""; return (
Animated Tooltip
); })()}
); }