Skip to content
Components

Tooltip

A delayed, non-interactive label or hint for a focused or hovered control.

Playground

scheme

Sets the tooltip foreground and background colors.

side

Preferred side of the trigger before collision handling.

delayDuration

Milliseconds to wait before opening the first tooltip.

Usage

tsx
import {
  Tooltip,
  TooltipArrow,
  TooltipContent,
  TooltipProvider,
  TooltipTrigger,
} from "earthling-ui/tooltip";

export function Example() {
  return (
    <>
      <TooltipProvider>
        <Tooltip>
          <TooltipTrigger aria-label="Copy project link">Copy</TooltipTrigger>
          <TooltipContent>
            Copy project link
            <TooltipArrow />
          </TooltipContent>
        </Tooltip>
      </TooltipProvider>
    </>
  );
}
  • Give icon-only controls an accessible name; the tooltip is supplementary.
  • The provider waits 500ms for the first tooltip and uses a 300ms skip window for nearby tooltips.
  • Keep tooltip content short and avoid interactive elements inside it.

Installation

Start with the project setup for React and Tailwind CSS 4. Both paths use the same component and theme.

bash
npm install earthling-ui

Use the component import shown above. Package updates keep the implementation current.

API reference

Declarations from the current library build, including inherited primitive props. Playground controls above show selected options; they are not the complete API.

tsx
// Generated by dts-bundle-generator v9.5.1

import * as TooltipPrimitive from '@radix-ui/react-tooltip';
import { VariantProps } from 'class-variance-authority';
import { ComponentPropsWithoutRef } from 'react';

export declare const TooltipProvider: ({ delayDuration, skipDelayDuration, ...props }: ComponentPropsWithoutRef<typeof TooltipPrimitive.Provider>) => import("react").JSX.Element;
export declare const Tooltip: import("react").FC<TooltipPrimitive.TooltipProps>;
export declare const TooltipTrigger: import("react").ForwardRefExoticComponent<TooltipPrimitive.TooltipTriggerProps & import("react").RefAttributes<HTMLButtonElement>>;
export declare const tooltipVariants: (props?: ({
	scheme?: "default" | "primary" | "secondary" | "tertiary" | "neutral" | "muted" | "good" | "caution" | "bad" | null | undefined;
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
export interface TooltipContentProps extends ComponentPropsWithoutRef<typeof TooltipPrimitive.Content>, VariantProps<typeof tooltipVariants> {
}
export declare const TooltipContent: import("react").ForwardRefExoticComponent<TooltipContentProps & import("react").RefAttributes<HTMLDivElement>>;
export declare const TooltipArrow: import("react").ForwardRefExoticComponent<Omit<TooltipPrimitive.TooltipArrowProps & import("react").RefAttributes<SVGSVGElement>, "ref"> & import("react").RefAttributes<SVGSVGElement>>;

export {};

Runtime dependencies: @radix-ui/react-tooltip, class-variance-authority, cnfast.

Source

Use the eject command to copy this implementation with its required helpers and project-specific imports.

View Tooltip implementation
tsx
"use client";

import {
  forwardRef,
  type ComponentPropsWithoutRef,
  type ComponentRef,
} from "react";
import * as TooltipPrimitive from "@radix-ui/react-tooltip";
import { cva, type VariantProps } from "class-variance-authority";
import { cn } from "@/utils/cn";
import { schemes } from "@/utils/variants";

const TooltipProvider = ({
  delayDuration = 500,
  skipDelayDuration = 300,
  ...props
}: ComponentPropsWithoutRef<typeof TooltipPrimitive.Provider>) => (
  <TooltipPrimitive.Provider
    delayDuration={delayDuration}
    skipDelayDuration={skipDelayDuration}
    {...props}
  />
);

const Tooltip = TooltipPrimitive.Root;

const TooltipTrigger = TooltipPrimitive.Trigger;

const tooltipVariants = cva(
  "z-50 max-w-(--radix-tooltip-content-available-width) origin-(--radix-tooltip-content-transform-origin) overflow-hidden rounded-lg bg-(--scheme-tint) px-3 py-1.5 text-xs text-(--scheme-foreground) duration-150 ease-out animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 motion-reduce:animate-none",
  {
    variants: {
      scheme: schemes,
    },
    defaultVariants: { scheme: "primary" },
  },
);

export interface TooltipContentProps
  extends
    ComponentPropsWithoutRef<typeof TooltipPrimitive.Content>,
    VariantProps<typeof tooltipVariants> {}

const TooltipContent = forwardRef<
  ComponentRef<typeof TooltipPrimitive.Content>,
  TooltipContentProps
>(({ className, sideOffset = 4, scheme, ...props }, ref) => (
  <TooltipPrimitive.Portal>
    <TooltipPrimitive.Content
      ref={ref}
      sideOffset={sideOffset}
      className={cn(tooltipVariants({ scheme }), className)}
      {...props}
    />
  </TooltipPrimitive.Portal>
));
TooltipContent.displayName = TooltipPrimitive.Content.displayName;

const TooltipArrow = forwardRef<
  ComponentRef<typeof TooltipPrimitive.Arrow>,
  ComponentPropsWithoutRef<typeof TooltipPrimitive.Arrow>
>(({ className, ...props }, ref) => (
  <TooltipPrimitive.Arrow
    ref={ref}
    className={cn("fill-(--scheme-tint)", className)}
    {...props}
  />
));
TooltipArrow.displayName = TooltipPrimitive.Arrow.displayName;

export {
  Tooltip,
  TooltipTrigger,
  TooltipContent,
  TooltipProvider,
  TooltipArrow,
  tooltipVariants,
};