Skip to content

Pickers and overlays

Tooltip

A short description revealed from an existing control.

When to use it: Use it for brief help, never for essential instructions.

On this page

Example

Loading example…
Tooltip.tsxtsx
import { Tooltip, TooltipArrow, TooltipPopover, TooltipTrigger } from "@comp0/react";

export function Example() {
  return (
    <Tooltip>
      <TooltipTrigger className="rounded border border-zinc-950/10 px-3 py-2.5 text-base text-zinc-800 sm:py-2 sm:text-sm dark:border-white/10 dark:text-zinc-100">
        Hover or focus
      </TooltipTrigger>
      <TooltipPopover
        placement="top"
        offset={6}
        className="w-max translate-y-0 overflow-visible rounded border-0 bg-zinc-900 px-2 py-1 text-base text-white opacity-100 transition-[opacity,translate] duration-150 ease-out starting:translate-y-1 starting:opacity-0 motion-reduce:transition-none sm:text-sm dark:bg-zinc-100 dark:text-zinc-900"
      >
        Helpful context
        <TooltipArrow className="absolute -bottom-1 left-1/2 size-2 -translate-x-1/2 rotate-45 bg-zinc-900 dark:bg-zinc-100" />
      </TooltipPopover>
    </Tooltip>
  );
}

Type information

Merge the trigger onto a focusable inline code symbol and position a brief type description beside it.

Loading example…
tooltip.type-info.tsxtsx
import { Tooltip, TooltipArrow, TooltipPopover, TooltipTrigger } from "@comp0/react";

export function Example() {
  return (
    <div className="flex flex-col gap-2">
      <p className="text-sm text-zinc-600 dark:text-zinc-400">
        Hover or focus the underlined symbol.
      </p>
      <pre className="mt-5 overflow-auto rounded bg-zinc-950 p-4 font-mono text-sm/6 text-zinc-100">
        const{" "}
        <Tooltip>
          <TooltipTrigger className="cursor-help rounded-sm border-0 bg-transparent p-0 font-mono text-sky-300 underline decoration-sky-400 decoration-dashed underline-offset-4 outline-teal-400 focus-visible:outline-2 focus-visible:outline-offset-2">
            message
          </TooltipTrigger>
          <TooltipPopover
            as="span"
            placement="top"
            offset={6}
            className="w-max translate-y-0 overflow-visible rounded border-0 bg-zinc-800 px-2 py-1 text-sm text-zinc-100 opacity-100 shadow-lg transition-[opacity,translate] duration-100 starting:translate-y-1 starting:opacity-0 motion-reduce:transition-none"
          >
            const message: string
            <TooltipArrow
              as="span"
              className="absolute -bottom-1 left-1/2 size-2 -translate-x-1/2 rotate-45 bg-zinc-800"
            />
          </TooltipPopover>
        </Tooltip>
        {" = getGreeting();"}
      </pre>
    </div>
  );
}

Anatomy

Dashed frames are invisible state providers; shaded shapes own real DOM. Numbered pins match the list below.

A wireframe sketch of the assembled component. Each numbered marker matches a part in the list that follows.

  1. Tooltip

    Open-state provider. Does not add a DOM element.

  2. TooltipTrigger

    Element that reveals help on focus or hover. Owns a DOM element.

  3. TooltipPopover

    Short descriptive text. Owns a DOM element.

  4. TooltipArrowOptional

    Optional decorative caret inside TooltipPopover; style it to point at the trigger. Owns a DOM element.

Step by step

  1. 1

    Add the main part

    Start Tooltip with the control people already use.

  2. 2

    Add the supporting parts

    Add TooltipPopover with one short explanation, placed on the side you want, and a TooltipArrow caret styled to point back at the trigger.

  3. 3

    Make the behavior clear

    Give an icon-only trigger its own aria-label too.

    Exampletsx
    <Tooltip>
      <TooltipTrigger aria-label="More information">i</TooltipTrigger>
      <TooltipPopover placement="top" offset={6}>
        Helpful detail
        <TooltipArrow />
      </TooltipPopover>
    </Tooltip>;

Keyboard

Esc
Closes the tooltip.
Focus reveals the tooltip on its trigger.

Forms and accessibility

No native form behavior.

Accessibility checklist

  • Give the trigger its own accessible name.
  • Keep tooltip text brief and descriptive.
  • Do not put required interactive content inside a tooltip.
  • When the trigger is inline text, merge TooltipTrigger onto a focusable element so keyboard users can reveal the same description as pointer users.

API reference

Importtsx
import { Tooltip, TooltipArrow, TooltipPopover, TooltipTrigger } from "@comp0/react";

Tooltip

Context only

Open-state provider.

PropTypeDescription
openbooleanControlled open state.
defaultOpenbooleanInitial open state.
onToggle(open: boolean) => voidReceives the next open state.

TooltipTrigger

DOM element

Element that reveals help on focus or hover.

PropTypeDescription
asElementType | FragmentFragment merges the trigger onto your own element child.

TooltipPopover

DOM element

Short descriptive text.

PropTypeDescription
placementPopoverPlacementTrigger side to open on, such as "top" or "bottom start"; flips when there is no room.
offsetnumberPixel gap between the trigger and the tooltip.

TooltipArrow

OptionalDOM element

Optional decorative caret inside TooltipPopover; style it to point at the trigger.

Style hooks

Attributes that appear while a state is true. Target them with Tailwind data variants such as data-open:bg-zinc-100, or with any CSS selector.

TooltipTrigger

Style hookMeaning
[data-open]The tooltip is visible.

TooltipPopover

Style hookMeaning
[data-open]The tooltip is visible.
:popover-openNative pseudo-class equivalent.

Keep exploring