Overlays/Tooltip

Tooltip

A popup that displays information related to an element.

Themed

When to Use

Use Tooltip when you need to:

  • Label icon-only buttons that lack visible text
  • Show keyboard shortcuts for actions (e.g. "Copy (Ctrl+C)")
  • Provide brief supplementary information for truncated text
  • Explain the purpose of a UI element on hover or focus
  • Display metadata like timestamps or full names on abbreviated content

When Not to Use

  • Rich or interactive content (links, buttons) — use Popover
  • User profile previews on hover — use Hover Card
  • Critical information users must see — display it inline instead
  • Form validation messages — use inline error text with Field

Default

Basic tooltip that appears on hover and focus. Uses asChild on the trigger to forward props to the child element.

Positions

Tooltip can be positioned on any side of the trigger using the side prop. Automatically flips when constrained by viewport edges.

Instant

Tooltip with zero delay for immediate feedback. Set delayDuration={0} on the TooltipProvider.

UX & Design Guidelines

Content Guidelines

Keep tooltip text concise — ideally one line, two at most. Tooltips should provide supplementary context, not essential information. Avoid placing interactive content (links, buttons) inside tooltips. If you need more than a short label, consider using Popover instead.

Timing & Delay

The default delayDuration is 0ms for instant feedback. For toolbar-style interfaces with many icon buttons, use delayDuration={400} to avoid tooltips firing during rapid mouse movement. The skipDelayDuration (300ms default) lets users move between triggers without re-incurring the delay.

Placement & Positioning

Default placement is side="top". Tooltips automatically flip to the opposite side when they would overflow the viewport. Use sideOffset to add breathing room between the trigger and tooltip. Ensure tooltips do not obscure related content the user is trying to read.

Color & Contrast

The tooltip uses bg-foreground with text-background for an inverted high-contrast appearance. The arrow inherits fill-foreground to match the tooltip body. This inverted scheme ensures tooltips are visually distinct from surrounding UI and meet WCAG 2.1 AA contrast requirements in both light and dark modes.

Accessibility

Keyboard Navigation

  • Tab — Move focus to the tooltip trigger; tooltip appears on focus
  • Escape — Dismiss an open tooltip immediately
  • Enter or Space — Activates the trigger element (button behavior preserved)
  • No keyboard shortcut to explicitly open — tooltips appear on focus automatically

Screen Reader Support

  • Tooltip content is announced via aria-describedby on the trigger
  • For icon-only buttons, add an explicit aria-label to the trigger for the primary label
  • The tooltip acts as supplementary description, not a replacement for visible labels
  • Content is announced when the tooltip opens, giving screen reader users the same info as sighted users

Focus Management

Tooltips open on focus and close on blur without stealing focus from the trigger. The tooltip content is not focusable — focus remains on the trigger element. This ensures keyboard users can tab through the interface naturally. Built on Radix UI Tooltip primitive, which manages aria-describedby associations automatically.

Motion & Reduced Motion

Tooltips animate with fade-in/zoom-in on open and reverse on close. When prefers-reduced-motion is active, animations are suppressed and the tooltip appears immediately. Slide-in direction varies by placement side for natural movement.

ARIA Patterns

{/* Basic tooltip - automatically wires aria-describedby */}
<Tooltip>
  <TooltipTrigger asChild>
    <Button variant="outline">Save</Button>
  </TooltipTrigger>
  <TooltipContent>
    <p>Save your changes (Ctrl+S)</p>
  </TooltipContent>
</Tooltip>

{/* Icon-only button with tooltip as accessible label */}
<Tooltip>
  <TooltipTrigger asChild>
    <Button size="icon" variant="outline" aria-label="Add to favorites">
      <HeartIcon className="size-4" />
    </Button>
  </TooltipTrigger>
  <TooltipContent>
    <p>Add to favorites</p>
  </TooltipContent>
</Tooltip>

{/* Disabled trigger - wrap in span for hover events */}
<Tooltip>
  <TooltipTrigger asChild>
    <span tabIndex={0}>
      <Button disabled>Disabled action</Button>
    </span>
  </TooltipTrigger>
  <TooltipContent>
    <p>You need permission to perform this action</p>
  </TooltipContent>
</Tooltip>

API Reference

The Tooltip component is composed of TooltipProvider, Tooltip, TooltipTrigger, and TooltipContent.

TooltipProvider

Wraps your app or a section to provide shared tooltip configuration.

PropTypeDefaultDescription
delayDurationnumber0Delay in milliseconds before the tooltip appears on hover.
skipDelayDurationnumber300Time in ms for the user to enter another trigger without incurring a delay.
disableHoverableContentbooleanfalsePrevents the tooltip from staying open when hovering over its content.

TooltipContent

The floating content rendered inside a portal when the tooltip is open.

PropTypeDefaultDescription
side"top" | "right" | "bottom" | "left""top"The preferred side of the trigger to render against. Flips automatically when constrained.
sideOffsetnumber0Distance in pixels between the tooltip content and the trigger element.
align"start" | "center" | "end""center"Alignment of the tooltip content relative to the trigger.
alignOffsetnumber0Offset in pixels from the aligned edge.
classNamestringAdditional CSS classes to apply to the tooltip content.