Search

Ctrl + K

Tooltip

This document outlines the steps to create Tooltip component styled withTailwind CSS and using some npm dependency libraries.

Prerequisites

  • Node.js and npm installed on your machine.
  • Tailwind CSS installed in your project.
  • CVA(class-variance-authority) is a utility for managing CSS class names based on various conditions.
  • clsx is a tiny utility for constructing className strings conditionally.
Step 1: Create variant styles
1// tooltip.helpers.ts
2import { cva } from "class-variance-authority";
3
4export const tooltipVariants = cva(
5  [
6    "invisible opacity-0 text-sm absolute whitespace-nowrap bg-neutral-700 text-white text-center rounded-sm px-2 py-1 z-10",
7    "transition-opacity duration-150 group-hover:visible group-hover:opacity-100",
8    "after:content-[''] after:absolute after:border-[5px] after:border-solid",
9  ],
10  {
11    variants: {
12      position: {
13        top: [
14          "bottom-[calc(100%+6px)] left-1/2",
15          "after:top-full after:left-1/2 after:-ml-[5px] after:border-t-neutral-700 after:border-b-transparent after:border-x-transparent",
16        ],
17        right: [
18          "left-[calc(100%+6px)] top-1/2",
19          "after:right-full after:top-1/2 after:-mt-[5px] after:border-r-neutral-700 after:border-l-transparent after:border-y-transparent",
20        ],
21        bottom: [
22          "top-[calc(100%+6px)] left-1/2",
23          "after:bottom-full after:left-1/2 after:-ml-[5px] after:border-b-neutral-700 after:border-t-transparent after:border-x-transparent",
24        ],
25        left: [
26          "right-[calc(100%+6px)] top-1/2",
27          "after:left-full after:top-1/2 after:-mt-[5px] after:border-l-neutral-700 after:border-r-transparent after:border-y-transparent",
28        ],
29      },
30    },
31  },
32);
33
Step 2: Create Tooltip component
1// tooltip.component.tsx
2import clsx from "clsx";
3import { useCallback } from "react";
4import { tooltipVariants } from "./tooltip.helpers";
5
6export interface TooltipProps {
7  title: string;
8  position?: "top" | "right" | "bottom" | "left";
9  tooltipClassName?: string;
10  className?: string;
11  width?: string | number;
12  children: React.ReactNode;
13}
14
15const Tooltip: React.FC<TooltipProps> = ({
16  title,
17  position = "top",
18  tooltipClassName,
19  className,
20  width,
21  children,
22}) => {
23  const refCallback = useCallback(
24    (el: HTMLDivElement | null) => {
25      if (!el) return;
26
27      switch (position) {
28        case "top":
29        case "bottom":
30          el.style.marginTop = "0px";
31          el.style.marginLeft = `-${el.clientWidth / 2}px`;
32          break;
33        case "left":
34        case "right":
35          el.style.marginLeft = "0px";
36          el.style.marginTop = `-${el.clientHeight / 2}px`;
37          break;
38        default:
39          break;
40      }
41    },
42    [position, title],
43  );
44
45  return (
46    <div className={cn("group relative w-fit", className)}>
47      {children}
48      <div
49        ref={refCallback}
50        style={{ width: width || "auto" }}
51        className={cn(tooltipVariants({ position }), tooltipClassName)}
52      >
53        {title}
54      </div>
55    </div>
56  );
57};
58
59export default Tooltip;
60