Tooltip

A small floating label shown on hover or focus, from @clerk/headless. It is a headless primitive: it supplies open state, hover/focus delays, portalling, floating-ui positioning, optional shared delay groups, and ARIA wiring, but ships no styles — you bring your own CSS by targeting the data-* attributes each part emits. A tooltip never receives or traps focus.

Example

The demo below is intentionally unstyled — it renders the raw primitive so you can see its behavior and ARIA wiring. Hover or focus the trigger; the tooltip appears after a short delay and dismisses on blur or Escape.

Usage

import { Tooltip } from '@clerk/headless/tooltip';

<Tooltip.Root>
  <Tooltip.Trigger>Hover me</Tooltip.Trigger>
  <Tooltip.Portal>
    <Tooltip.Positioner>
      <Tooltip.Popup>
        Helpful description
        <Tooltip.Arrow />
      </Tooltip.Popup>
    </Tooltip.Positioner>
  </Tooltip.Portal>
</Tooltip.Root>;

Shared delay group

Wrap related tooltips in Tooltip.Group so that, once one is open, moving to a sibling trigger shows its tooltip instantly (skipping the open delay):

<Tooltip.Group>
  <Tooltip.Root>{/* … */}</Tooltip.Root>
  <Tooltip.Root>{/* … */}</Tooltip.Root>
</Tooltip.Group>;

Parts

PartDefault ElementDescription
Tooltip.Rootnone (context)Owns open state, delays, and positioning
Tooltip.Groupnone (context)Shares open/close delay across grouped tooltips
Tooltip.Trigger<button>The reference element that opens the tooltip on hover/focus
Tooltip.Portalnone (portal)Portals its children; renders nothing until mounted
Tooltip.Positioner<div>Floating-positioned container
Tooltip.Popup<div>The visible tooltip surface (role="tooltip")
Tooltip.Arrow<svg>Optional arrow pointing at the trigger

All rendered parts accept a render prop for polymorphic rendering and standard HTML attributes for their default element. Tooltip.Arrow accepts floating-ui FloatingArrow props. Tooltip.Portal is optional.

Props

Tooltip.Root

PropTypeDefaultDescription
openbooleanControlled open state
defaultOpenbooleanfalseInitial open state (uncontrolled)
onOpenChange(open: boolean) => voidCalled when the open state changes
placementPlacement'top'Placement relative to the trigger
sideOffsetnumber4Gap in px between the trigger and the tooltip
delaynumber200Delay in ms before opening on hover
closeDelaynumber0Delay in ms before closing on hover out

Tooltip.Group

PropTypeDefaultDescription
delaynumber | { open?: number; close?: number }{ open: 200, close: 100 }Shared delay config for grouped tooltips
timeoutMsnumber300Time in ms before the group leaves instant mode

Tooltip.Trigger, Tooltip.Positioner, and Tooltip.Popup take no additional props beyond standard HTML attributes for their default element.

Styling

Each part emits data-* attributes you can target with any CSS solution:

AttributeApplies ToDescription
data-openTrigger, PopupPresent when the tooltip is open
data-closedTrigger, PopupPresent when closed (Popup stays mounted to exit)
data-sidePositioner, ArrowResolved side: top / bottom / left / right
data-starting-stylePopupPresent on the entering frame
data-ending-stylePopupPresent during the exit animation

The positioner exposes anchor/viewport geometry as CSS variables:

VariableDescription
--cl-anchor-widthTrigger width
--cl-anchor-heightTrigger height
--cl-available-widthAvailable width between the anchor and viewport edge
--cl-available-heightAvailable height between the anchor and viewport edge
--cl-transform-origintransform-origin pointing back toward the anchor