Tooltip

Used internally by IconButton when aria-label is provided. Can also be used directly.

API Reference

PropTypeDefault
labelstring
childrenReactElement
side"top" | "bottom" | "left" | "right""top"
delaynumber

Sides

<IconButton aria-label="Top" tooltipSide="top">...</IconButton>
<IconButton aria-label="Bottom" tooltipSide="bottom">...</IconButton>
<IconButton aria-label="Left" tooltipSide="left">...</IconButton>
<IconButton aria-label="Right" tooltipSide="right">...</IconButton>

Usage Notes

  • This is a pre-styled wrapper around Base UI Tooltip. Refer to their docs for the full API.
  • IconButton automatically wraps in a Tooltip when aria-label is provided. Use tooltipSide to control placement.

Basic Usage

import { Tooltip } from "@/ui";

<Tooltip label="More info">
  <span>Hover me</span>
</Tooltip>

Source

src/ui/Tooltip.tsx
"use client";

import { Tooltip as BaseTooltip } from "@base-ui/react/tooltip";

type Side = "top" | "bottom" | "left" | "right";

interface TooltipProps {
  label: string;
  children: React.ReactElement;
  side?: Side;
  delay?: number;
}

export function Tooltip({ label, children, side = "top", delay }: TooltipProps) {
  return (
    <BaseTooltip.Root>
      <BaseTooltip.Trigger
        render={<span className="inline-flex" />}
        delay={delay}
      >
        {children}
      </BaseTooltip.Trigger>
      <BaseTooltip.Portal>
        <BaseTooltip.Positioner side={side} sideOffset={8} className="z-60">
          <BaseTooltip.Popup className="rounded-md bg-root-contrast px-2 py-1 text-xs text-root transition-opacity data-closed:opacity-0 data-instant:duration-0 data-open:opacity-100">
            {label}
          </BaseTooltip.Popup>
        </BaseTooltip.Positioner>
      </BaseTooltip.Portal>
    </BaseTooltip.Root>
  );
}