Light

Tooltip

A popup that displays information related to an element when the element receives keyboard focus or the mouse hovers over it.

Spec · from metadata

When to use

  • Icon-only buttons that need a text label
  • Truncated text that needs to show the full value on hover
  • Abbreviations or jargon that need brief explanations
  • Any element that benefits from a short descriptive label

When not to use

  • Rich content with images, links, or structure -- use HoverCard or Popover
  • Interactive content (forms, buttons) -- use Popover
  • Long descriptions or paragraphs -- use Popover with header/description
  • Content that must be accessible on touch without focus -- tooltips require hover or focus

Anti-patterns

Avoid<Tooltip>
  <TooltipTrigger asChild>
    <Button variant="ghost" size="icon">
      <TrashIcon />
    </Button>
  </TooltipTrigger>
  <TooltipContent>Delete item</TooltipContent>
</Tooltip>
Prefer<TooltipProvider>
  <Tooltip>
    <TooltipTrigger asChild>
      <Button variant="ghost" size="icon">
        <TrashIcon />
      </Button>
    </TooltipTrigger>
    <TooltipContent>Delete item</TooltipContent>
  </Tooltip>
</TooltipProvider>

TooltipProvider is required. Without it, the tooltip won't render. Place it once at the app root to cover all tooltips.

Avoid<Tooltip>
  <TooltipTrigger asChild>
    <span>@johndoe</span>
  </TooltipTrigger>
  <TooltipContent>
    <div className="flex gap-2">
      <Avatar /><span>John Doe - Engineer</span>
    </div>
  </TooltipContent>
</Tooltip>
Prefer<HoverCard>
  <HoverCardTrigger asChild>
    <span>@johndoe</span>
  </HoverCardTrigger>
  <HoverCardContent>
    <div className="flex gap-2">
      <Avatar /><span>John Doe - Engineer</span>
    </div>
  </HoverCardContent>
</HoverCard>

Tooltip is for plain text labels only. Rich content with avatars and structure should use HoverCard (hover-triggered) or Popover (click-triggered).

Accessibility

  • Screen readerTooltip content is associated with the trigger via aria-describedby. Keep content short and descriptive -- it is read as a description of the trigger element.
  • ContrastUses inverted colors (bg-foreground + text-background) for maximum contrast against any surface.

Token bindings

TokenCategoryUsage
bg-foregroundcolorTooltip background (inverted)
text-backgroundcolorTooltip text (inverted)
fill-foregroundcolorArrow fill
rounded-mdradiusTooltip border radius
px-3 py-1.5spacingContent padding
text-xstypographyTooltip text size

Import

import {
  Tooltip,
  TooltipContent,
  TooltipProvider,
  TooltipTrigger,
} from "@timelycare/helix-ui"

Props

interface TooltipContentProps {
  side?: "top" | "bottom" | "left" | "right"
  sideOffset?: number
  className?: string
  children: React.ReactNode
}

Structure

PartTailwind
TooltipContentbg-primary text-primary-foreground px-3 py-1.5 rounded-md text-xs max-w-sm
Arrowsize-2.5 (10px), fill-primary
Texttext-xs font-normal leading-normal text-primary-foreground (12px)

Positions

SideArrow PositionUse For
topBottom center of tooltipDefault, most common
bottomTop center of tooltipWhen space above is limited
leftRight center of tooltipHorizontal layouts
rightLeft center of tooltipHorizontal layouts

Specs

PropertyValue
Backgroundbg-primary
Text colortext-primary-foreground
Font sizetext-xs (12px)
Line heightleading-normal (16px)
Paddingpx-3 py-1.5 (12px × 6px)
Border radiusrounded-md (8px)
Max widthmax-w-sm (384px)
Arrow sizesize-2.5 (10px)

Common Patterns

Basic Tooltip

<TooltipProvider>
  <Tooltip>
    <TooltipTrigger asChild>
      <Button variant="outline">Hover me</Button>
    </TooltipTrigger>
    <TooltipContent>
      <p>This is a tooltip</p>
    </TooltipContent>
  </Tooltip>
</TooltipProvider>

With Position

<TooltipContent side="right">
  <p>Tooltip on the right</p>
</TooltipContent>

Icon Button with Tooltip

<Tooltip>
  <TooltipTrigger asChild>
    <Button variant="ghost" size="icon">
      <Settings className="size-4" />
    </Button>
  </TooltipTrigger>
  <TooltipContent>Settings</TooltipContent>
</Tooltip>

Accessibility

  • Built on Radix Tooltip — handles keyboard accessibility automatically
  • Appears on hover and focus (keyboard accessible)
  • Keyboard: Escape to dismiss
  • Screen reader: content announced via aria-describedby on trigger
  • Not for critical information — may be missed by some assistive technologies

Gotchas

ProblemSolution
Tooltip not showingWrap with <TooltipProvider> at app root
Arrow not visibleEnsure sideOffset has default value (usually 4)
Tooltip clippedAdjust side prop or use avoidCollisions
Text too longTooltip respects max-w-sm, text will wrap

See Also


Last updated: February 9, 2026