Skip to content

Tooltip

A small text hint shown on hover or focus to clarify a control.

Stablev0.4.2added in v0.1.0@garn/ui/tooltip
On this page

Installation

garn is copy-in — the garn CLI writes this component's source into your project, so you own and can edit it. It resolves any base files and installs the npm dependencies below for you.

terminal
npx garn-ui add tooltip
First time? Set up garn in your project
Registry
tooltip
Deps
@radix-ui/react-tooltip
Registry deps
utils

Import

import { TooltipProvider, Tooltip, TooltipTrigger, TooltipContent } from "@garn/ui/tooltip";

Anatomy

The parts this component is built from — compose them to assemble it.

TooltipProviderRequired

Wraps the app (or a subtree) once; shares delay/skip config across tooltips.

TooltipRequired

Root — owns the open state for one tooltip.

TooltipTriggerRequired[data-slot="tooltip-trigger"]

The element the hint describes (asChild to wrap your control).

TooltipContentRequired[data-slot="tooltip-content"]

The hint bubble (portaled, non-interactive).

Props

The component's public props and their types.

No component-specific props — this is a thin wrapper over its native element.

Styling

Target these data-slots and states, and remap these tokens, to restyle without forking the component.

[data-slot="tooltip-content"]

States

SelectorState
[data-state=delayed-open]delayed-open
[data-state=instant-open]instant-open
[data-state=closed]closed
PropertyTokenTier
fill--garn-brand-solidbrandablesemantic
motion--garn-motion-fastsemantic

When to use

Add a brief, supplementary text hint to a control — clarify an icon button, abbreviate a label, surface a shortcut.

Reach for something else when

  • Essential information the user must read (put it inline)
  • interactive content like links/buttons (use a popover)
  • a control's primary label (use a real label / aria-label).

Overview

Tooltip adds a brief, supplementary text hint to a control — naming an icon button, spelling out an abbreviation, surfacing a shortcut. Wrap the app (or a subtree) once in a TooltipProvider to share delay/skip timing, then each Tooltip pairs a TooltipTrigger with a non-interactive TooltipContent. It's a passive label, not a surface you can click into — for interactive content use Popover, for a profile/link preview use HoverCard.

Guidelines

Never put essential or interactive content in a tooltip. It's keyboard- and touch-hostile by nature — no clicks, no links, and it can be missed entirely. Anything required to complete the task belongs in the visible UI; the tooltip only supplements.

A tooltip supplements a name, it doesn't replace one. An icon-only button still needs its own aria-label — the tooltip is a hover convenience, not the accessible name. Keep the text to a few words, no rich formatting.

Use one Provider and lean on its timing. A single TooltipProvider keeps delays consistent and the skip-delay snappy when moving between controls. Don't trigger tooltips on disabled elements that can't receive focus — wrap an enabled element instead.

Best practices

Do
  • Keep it to a few words; mount one TooltipProvider near the app root.
  • Still give icon-only triggers an aria-label — the tooltip is extra, not the name.
Don't
  • Don't put interactive elements in a tooltip — it can't be focused/clicked reliably.
  • Don't hide critical information behind hover only.

Content guidelines

  • Keep it to a short, supplementary phrase — a name or a shortcut, not a sentence.
  • Don't put essential information in a tooltip, and don't just restate the visible label.

Troubleshooting

The tooltip never appears, or only on the first one.

Cause. No TooltipProvider ancestor wrapping the Tooltip(s).

Fix. Mount a single <TooltipProvider> near the app root (or wrap the subtree).

Accessibility

Role
tooltip
ARIA APG
tooltip
Focus
Appears on trigger focus, not just hover; dismissible with Escape.

Accessibility requirements

warn

Give the trigger its own accessible name (aria-label); the tooltip is supplementary, not a label.

when the trigger is an icon-only control that relies on the tooltip for its only accessible name

warn

Wrap the app (or subtree) in a single TooltipProvider.

when a Tooltip is rendered without a TooltipProvider ancestor

Keyboard

TabFocusing the trigger shows the tooltip.
EscapeDismiss the tooltip while the trigger stays focused.
AA1.4.13Content on Hover or FocusA4.1.2Name, Role, Value
  • Trigger is described by the tooltip (aria-describedby); shows on hover AND keyboard focus.
  • Content is non-interactive — never put links/buttons inside a tooltip (use a popover).