All files / src/components/common Tooltip.tsx

93.1% Statements 54/58
75% Branches 12/16
100% Functions 5/5
93.1% Lines 54/58

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 791x                   1x 10x 10x 10x 10x 10x 10x 10x   10x 10x     10x 4x 4x 1x 4x   4x   4x 4x 3x 4x 4x     10x 4x 4x 1x 4x   4x   4x 4x 3x 4x 4x   10x 10x 10x 10x 10x 10x   10x 10x 4x 4x 4x 4x 4x   4x 4x 4x 4x 4x   10x   10x   1x  
import React, { ReactNode, useState } from "react";
 
interface TooltipProps {
  content: ReactNode;
  children: ReactNode;
  placement?: "top" | "right" | "bottom" | "left";
  className?: string;
  [x: string]: any; // For spreading additional props
}
 
const Tooltip: React.FC<TooltipProps> = ({
  content,
  children,
  placement = "top",
  className = "",
  ...rest
}) => {
  const [isVisible, setIsVisible] = useState(false);
 
  const showTooltip = () => setIsVisible(true);
  const hideTooltip = () => setIsVisible(false);
 
  // Calculate the position classes based on placement
  const getPositionClasses = () => {
    switch (placement) {
      case "right":
        return "left-full ml-2";
      case "bottom":
        return "top-full left-1/2 transform -translate-x-1/2 mt-2";
      case "left":
        return "right-full mr-2";
      case "top":
      default:
        return "bottom-full left-1/2 transform -translate-x-1/2 mb-2";
    }
  };
 
  // Calculate arrow classes based on placement
  const getArrowClasses = () => {
    switch (placement) {
      case "right":
        return "left-0 top-1/2 transform -translate-x-1/2 -translate-y-1/2";
      case "bottom":
        return "bottom-full left-1/2 -ml-1 -mb-1";
      case "left":
        return "right-0 top-1/2 transform translate-x-1/2 -translate-y-1/2";
      case "top":
      default:
        return "top-full left-1/2 -ml-1 -mt-1";
    }
  };
 
  return (
    <div
      className={`relative inline-block ${className}`}
      onMouseEnter={showTooltip}
      onMouseLeave={hideTooltip}
      {...rest}
    >
      {children}
      {isVisible && (
        <div
          role="tooltip"
          className={`absolute z-10 px-3 py-2 text-sm font-medium text-white bg-gray-900 rounded-md shadow-sm whitespace-nowrap ${getPositionClasses()} `}
          data-testid="tooltip-content"
          data-popper-placement={placement}
        >
          {content}
          <div
            className={`absolute w-2 h-2 bg-gray-900 transform rotate-45 ${getArrowClasses()}`}
          />
        </div>
      )}
    </div>
  );
};
 
export default Tooltip;