Skip to main content

Tooltip

  • Component overview: Dark tooltip bubble that appears on hover to convey brief contextual information.
  • Component group: Tips
  • Figma page: ↳ Tips > Tooltip
  • Implementation note: TooltipContent retains the Radix overlay structure and animation skeleton; the design layer owns the color, border radius, shadow, and arrow visuals.
  • Default interaction: children is the trigger element by default.

Basic Usage

Result
Loading...
Live Editor
render(
  <div style={{ display: 'flex', gap: 32, alignItems: 'center', padding: '40px 0' }}>
    <Tooltip content="Prompt Text" side="top" defaultOpen>
      <Button variant="secondary" size="sm">
        Tooltip above
      </Button>
    </Tooltip>

    <Tooltip content="Hover tooltip">
      <Button variant="secondary" size="sm">
        Hover me
      </Button>
    </Tooltip>
  </div>,
)

Direction Variants

Tooltip supports 8 directions controlled by combining side and align.

Result
Loading...
Live Editor
render(
  <div
    style={{
      display: 'flex',
      flexDirection: 'column',
      alignItems: 'center',
      gap: 8,
      padding: '48px 0',
    }}
  >
    <div style={{ display: 'flex', gap: 8 }}>
      {[
        { side: 'top', align: 'start', label: 'Top-Start' },
        { side: 'top', align: 'center', label: 'Top' },
        { side: 'top', align: 'end', label: 'Top-End' },
      ].map(({ side, align, label }) => (
        <Tooltip key={label} content={label} side={side} align={align}>
          <Button variant="tertiary" size="sm" style={{ width: 72 }}>
            {label}
          </Button>
        </Tooltip>
      ))}
    </div>
    {[
      {
        l: { side: 'left', align: 'start', label: 'Left-Start' },
        r: { side: 'right', align: 'start', label: 'Right-Start' },
      },
      {
        l: { side: 'left', align: 'center', label: 'Left' },
        r: { side: 'right', align: 'center', label: 'Right' },
      },
      {
        l: { side: 'left', align: 'end', label: 'Left-End' },
        r: { side: 'right', align: 'end', label: 'Right-End' },
      },
    ].map(({ l, r }) => (
      <div key={l.label} style={{ display: 'flex', justifyContent: 'space-between', width: 400 }}>
        <Tooltip content={l.label} side={l.side} align={l.align}>
          <Button variant="tertiary" size="sm" style={{ width: 72 }}>
            {l.label}
          </Button>
        </Tooltip>
        <Tooltip content={r.label} side={r.side} align={r.align}>
          <Button variant="tertiary" size="sm" style={{ width: 72 }}>
            {r.label}
          </Button>
        </Tooltip>
      </div>
    ))}
    <div style={{ display: 'flex', gap: 8 }}>
      {[
        { side: 'bottom', align: 'start', label: 'Bottom-Start' },
        { side: 'bottom', align: 'center', label: 'Bottom' },
        { side: 'bottom', align: 'end', label: 'Bottom-End' },
      ].map(({ side, align, label }) => (
        <Tooltip key={label} content={label} side={side} align={align}>
          <Button variant="tertiary" size="sm" style={{ width: 72 }}>
            {label}
          </Button>
        </Tooltip>
      ))}
    </div>
  </div>,
)

Keyboard Shortcut Hint

Result
Loading...
Live Editor
render(
  <div style={{ display: 'flex', gap: 32, alignItems: 'center', padding: '40px 0' }}>
    <Tooltip content="Select All" shortcut={['⇧', '⌘', 'A']} defaultOpen>
      <Button variant="secondary" size="sm">
        Select All
      </Button>
    </Tooltip>

    <Tooltip content="Save" shortcut={['⌘', 'S']}>
      <Button variant="secondary" size="sm">
        Save
      </Button>
    </Tooltip>
  </div>,
)

Tooltip Props

PropTypeDefaultDescription
childrenReactNodeTrigger element. By default the tooltip uses children as the trigger.
contentReactNodeTooltip content
titleReactNodeAlias for tooltip content
shortcutReactNode[]Keyboard shortcut label array, e.g. ['⇧', '⌘', 'A']
side'top' | 'bottom' | 'left' | 'right''top'Popup direction
align'start' | 'center' | 'end''center'Alignment
sideOffsetnumber8Distance from the trigger element (px)
classNamestringCustom style class
asChildbooleantrueWhether to use children as the trigger itself