Tooltip
A popup that displays information related to an element.
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-describedbyon the trigger - For icon-only buttons, add an explicit
aria-labelto 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>Related Components
Hover Card
Rich content preview on hover, ideal for user profiles and link previews.
Popover
Floating panel for interactive or complex content triggered by a button.
Badge
Inline status labels for persistent metadata that doesn't need a hover trigger.
Kbd
Keyboard shortcut display for inline use when a tooltip is not appropriate.
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.
| Prop | Type | Default | Description |
|---|---|---|---|
| delayDuration | number | 0 | Delay in milliseconds before the tooltip appears on hover. |
| skipDelayDuration | number | 300 | Time in ms for the user to enter another trigger without incurring a delay. |
| disableHoverableContent | boolean | false | Prevents the tooltip from staying open when hovering over its content. |
TooltipContent
The floating content rendered inside a portal when the tooltip is open.
| Prop | Type | Default | Description |
|---|---|---|---|
| side | "top" | "right" | "bottom" | "left" | "top" | The preferred side of the trigger to render against. Flips automatically when constrained. |
| sideOffset | number | 0 | Distance in pixels between the tooltip content and the trigger element. |
| align | "start" | "center" | "end" | "center" | Alignment of the tooltip content relative to the trigger. |
| alignOffset | number | 0 | Offset in pixels from the aligned edge. |
| className | string | — | Additional CSS classes to apply to the tooltip content. |