Skip to content

Tooltip

Show a short visual label on hover or keyboard focus.

import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@youj/react'

Installation & usage

npm i @youj/react

For an app already set up with npx @youj/cli init, which installs the peers (@youj/core, @youj/motion, motion and Base UI) and wires the provider. New app? Start at Installation.

Use Tooltip to show an icon-only control’s name or keyboard shortcut. It is visual only: it does not open on touch (unless you turn on longPress) and screen readers do not read it. Give the control its own accessible name and keep essential information visible. For an explanation people can open, use a Popover with openOnHover. For a link preview, use a Hover Card.

import { Button, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@youj/react'
import { ArchiveIcon } from '@youj/icons'

export function ArchiveButton() {
  return (
    <TooltipProvider>
      <Tooltip>
        <TooltipTrigger render={<Button variant="ghost" size="icon" aria-label="Archive" />}>
          <ArchiveIcon />
        </TooltipTrigger>
        <TooltipContent>Archive</TooltipContent>
      </Tooltip>
    </TooltipProvider>
  )
}

Give an icon-only trigger an aria-label that matches the tooltip text. The tooltip doesn't name or describe its trigger, so the label is what assistive technology reads.

Reference

PropsTooltipProvider passes through to Base UI's provider (delay, which…

Props

TooltipContent

TooltipContent adds no props of its own. They pass through to TooltipPrimitive.Popup.Props, Pick<TooltipPrimitive.Positioner.Props, 'align' | 'alignOffset' | 'side' | 'sideOffset' | 'collisionPadding'>.

TooltipProvider passes through to Base UI's provider (delay, which defaults to 500 here, closeDelay and timeout). Tooltip takes the root props (open, defaultOpen, onOpenChange, disabled) and longPress, and TooltipTrigger takes the trigger's (delay, closeDelay, closeOnClick, render).

TouchTouch has no hover, so a tooltip doesn't open there

Touch

Touch has no hover, so a tooltip doesn't open there. A tap is a press, and Base UI opens a tooltip on focus only when the focus comes from a keyboard, so a tap never leaves one stuck on screen. Anything a tooltip says must therefore reach people another way: an icon-only control needs an aria-label, and anything people need in order to act (why a control is disabled, a limit, a warning) belongs in visible text next to the control. On a phone, prefer a visible label under an icon when there's room for one.

longPress on Tooltip adds what Android does for icon buttons: holding the trigger for half a second shows the tooltip, and that press doesn't activate the control. The tooltip hides 1.5 seconds after the finger lifts or at the next touch anywhere, and a finger that moves, as in a scroll, cancels it. Keyboard shortcuts inside it are left out on touch. It helps someone who wonders what an icon means; it doesn't replace the label.

<Tooltip longPress>
  <TooltipTrigger render={<Button variant="ghost" size="icon" aria-label="Archive" />}>
    <ArchiveIcon />
  </TooltipTrigger>
  <TooltipContent>Archive</TooltipContent>
</Tooltip>
MotionShow, hide, neighbor in a group, keyboard focus, Escape… · reduced motion

Motion

Motion tokens
MomentTokens
Show3px drift from the trigger, scale .97 → 1, fade (yj-tooltip)
duration.fastease.enter

140ms · cubic-bezier(0.16, 1, 0.3, 1)

140mscubic-bezier(0.16, 1, 0.3, 1)
Hide
duration.instantease.exit

80ms · cubic-bezier(0.4, 0, 1, 1)

80mscubic-bezier(0.4, 0, 1, 1)
Neighbor in a group, keyboard focus, EscapeBase UI sets data-instant
no token

0ms

0ms
Open delayhover intent, not motion: Speed leaves it alone
no token

500ms in a provider

500ms in a provider
Long press (touch, `longPress`)how long to hold, then how long it stays after the finger lifts
no token

500ms, 1.5s

500ms, 1.5s

Reduced motion

Tooltips appear and disappear at once, with no drift. Delays are unchanged.

Reduced motion

Tooltips appear in place, without the drift or the fade, and hide at once. Hover delays stay the same, because they measure intent rather than animate anything.

AccessibilityKeyboard, ARIA, focus

Accessibility

  • Tooltips are visual only. Base UI doesn't describe the trigger with them, so the trigger's own name (its text or aria-label) must carry the meaning.
  • Keyboard focus opens the tooltip without waiting for the delay. Hover opens it after the delay.
  • They don't open on touch, since there's no way to reveal them before tapping. With longPress, holding the trigger shows one, and that press doesn't activate the control.
KeyAction
TabFocusing a trigger shows its tooltip.
EscapeHides the tooltip and leaves focus on the trigger.