Based on the Tooltip Radix component.

Component Structure

Tooltip.Provider
Root-level provider to avoid regressions and enable consistent behavior across the app.
Place it near the top of your component tree.

Tooltip
Parent wrapper for Trigger and Content.
Handles positioning, accessibility, and visibility state.

Tooltip.Trigger
Element that, when hovered or focused, shows the tooltip.
Requires a React component child (or asChild prop) that accepts a ref to allow event bindings and accessibility props to be cloned.
Example: buttons, icons, links.

Tooltip.Content
The tooltip box itself.
Holds the text or elements you want displayed.
Handles positioning relative to the Trigger.

<Tooltip.Provider>
  <Tooltip>
    <Tooltip.Trigger>
      <Text>Hover on me</Text>
    </Tooltip.Trigger>
    <Tooltip.Content>This is the tooltip content, hello</Tooltip.Content>
  </Tooltip>
</Tooltip.Provider>

Default to open state

<Tooltip.Provider>
  <Tooltip defaultOpen>
    <Tooltip.Trigger>
      <Text>Hover on me</Text>
    </Tooltip.Trigger>
    <Tooltip.Content>This is the tooltip content, hello</Tooltip.Content>
  </Tooltip>
</Tooltip.Provider>

Custom delay on hover

<Tooltip.Provider>
  <Tooltip delayDuration={1500}>
    <Tooltip.Trigger>
      <Text>Hover on me</Text>
    </Tooltip.Trigger>
    <Tooltip.Content>This is the tooltip content, hello</Tooltip.Content>
  </Tooltip>
</Tooltip.Provider>

Prevent the user from being able to hover and potentially select content from Tooltip.Content

<Tooltip.Provider>
  <Tooltip disableHoverableContent>
    <Tooltip.Trigger>
      <Text>Hover on me</Text>
    </Tooltip.Trigger>
    <Tooltip.Content>This is the tooltip content, hello</Tooltip.Content>
  </Tooltip>
</Tooltip.Provider>

Custom Trigger

Use asChild on the Trigger component

Note: this is not standard behaviour, so check the usage tab, and make sure the designers are aware if you need to use this.

<Tooltip.Provider>
  <Tooltip>
    <Tooltip.Trigger asChild>
      <Button>
        <Text>Custom trigger</Text>
      </Button>
    </Tooltip.Trigger>
    <Tooltip.Content>This is the tooltip content, hello</Tooltip.Content>
  </Tooltip>
</Tooltip.Provider>

size

Controls the max width of the content box.

<Tooltip.Provider>
  <Tooltip>
    <Tooltip.Trigger>
      <Text>Custom trigger</Text>
    </Tooltip.Trigger>
    <Tooltip.Content size='sm'>This is the tooltip content, hello. It should have limited width, so the text spans on many, many lines.</Tooltip.Content>
  </Tooltip>
</Tooltip.Provider>

sticky

The sticky behavior on the align axis. "partial" will keep the content in the boundary as long as the trigger is at least partially in the boundary whilst "always" will keep the content in the boundary regardless.

<Tooltip.Provider>
  <Tooltip>
    <Tooltip.Trigger>
      <Text>Custom trigger</Text>
    </Tooltip.Trigger>
    <Tooltip.Content sticky="always">This is the tooltip content, hello</Tooltip.Content>
  </Tooltip>
</Tooltip.Provider>

side

The preferred side of the trigger to render against when open. Will be reversed when collisions occur and avoidCollisions is enabled.

<Tooltip.Provider>
  <Tooltip>
    <Tooltip.Trigger>
      <Text>Custom trigger</Text>
    </Tooltip.Trigger>
    <Tooltip.Content side="left">This is the tooltip content, hello</Tooltip.Content>
  </Tooltip>
</Tooltip.Provider>

sideOffset

The distance in pixels from the trigger.

<Tooltip.Provider>
  <Tooltip>
    <Tooltip.Trigger>
      <Text>Custom trigger</Text>
    </Tooltip.Trigger>
    <Tooltip.Content side="left" sideOffset={10}>This is the tooltip content, hello</Tooltip.Content>
  </Tooltip>
</Tooltip.Provider>

align

The preferred alignment against the trigger. May change when collisions occur.

<Tooltip.Provider>
  <Tooltip>
    <Tooltip.Trigger>
      <Text>Custom trigger</Text>
    </Tooltip.Trigger>
    <Tooltip.Content side="left" align="start">This is the tooltip content, hello</Tooltip.Content>
  </Tooltip>
</Tooltip.Provider>

alignOffset

An offset in pixels from the "start" or "end" alignment options.

<Tooltip.Provider>
  <Tooltip>
    <Tooltip.Trigger>
      <Text>Custom trigger</Text>
    </Tooltip.Trigger>
    <Tooltip.Content side="left" align="start" alignOffset={25}>This is the tooltip content, hello</Tooltip.Content>
  </Tooltip>
</Tooltip.Provider>

arrowPadding

The padding between the arrow and the edges of the content. If your content has border-radius, this will prevent it from overflowing the corners.

<Tooltip.Provider>
  <Tooltip>
    <Tooltip.Trigger>
      <Text>Custom trigger</Text>
    </Tooltip.Trigger>
    <Tooltip.Content side="left" align="start" alignOffset={25} arrowPadding={12}>This is the tooltip content, hello</Tooltip.Content>
  </Tooltip>
</Tooltip.Provider>

avoidCollisions

When true, overrides the side and align preferences to prevent collisions with boundary edges.

<Tooltip.Provider>
  <Tooltip>
    <Tooltip.Trigger>
      <Text>Custom trigger</Text>
    </Tooltip.Trigger>
    <Tooltip.Content avoidCollisions side="left" align="start" alignOffset={25} arrowPadding={12}>This is the tooltip content, hello</Tooltip.Content>
  </Tooltip>
</Tooltip.Provider>

collisionBoundary

The element used as the collision boundary. By default this is the viewport, though you can provide additional element(s) to be included in this check.

<div
  id="tooltip-boundary"
  className="w-[500px] h-[200px] border-2 border-dashed border-red-500 p-5 overflow-hidden relative"
>
  <Tooltip.Provider>
    <Tooltip>
      <Tooltip.Trigger asChild>
        <Button className="absolute bottom-2.5 right-12">
          Hover me
        </Button>
      </Tooltip.Trigger>
      <Tooltip.Content
        side="right"
        align="center"
        avoidCollisions
        collisionBoundary={document.getElementById("tooltip-boundary")}
      >
        Tooltip text
      </Tooltip.Content>
    </Tooltip>
  </Tooltip.Provider>
</div>

collisionPadding

The distance in pixels from the boundary edges where collision detection should occur. Accepts a number (same for all sides), or a partial padding object, for example: { top: 20, left: 20 }.

<div
  id="tooltip-boundary"
  className="w-[500px] h-[200px] border-2 border-dashed border-red-500 p-5 overflow-hidden relative"
>
  <Tooltip.Provider>
    <Tooltip>
      <Tooltip.Trigger asChild>
        <Button className="absolute bottom-2.5 right-12">
          Hover me
        </Button>
      </Tooltip.Trigger>
      <Tooltip.Content
        side="right"
        align="center"
        collisionBoundary={document.getElementById("tooltip-boundary")}
        collisionPadding={20}
        avoidCollisions
       >
        Tooltip text
      </Tooltip.Content>
    </Tooltip>
  </Tooltip.Provider>
</div>

hideWhenDetached

Whether to hide the content when the trigger becomes fully occluded.

<Tooltip.Provider>
  <Tooltip>
     <Tooltip.Trigger id='trigger' onClick={() => document.getElementById('trigger').style.display = 'none'}>
      Hover me
    </Tooltip.Trigger>
    <Tooltip.Content hideWhenDetached>
      Tooltip text
    </Tooltip.Content>
  </Tooltip>
</Tooltip.Provider>


onEscapeKeyDown

Event handler called when the Escape key is pressed while the tooltip is open.

<Tooltip.Provider>
  <Tooltip>
     <Tooltip.Trigger id='trigger'>
      Hover me
    </Tooltip.Trigger>
    <Tooltip.Content onEscapeKeyDown={() => alert("Pressed Escape")}>
      Tooltip text
    </Tooltip.Content>
  </Tooltip>
</Tooltip.Provider>


onPointerDownOutside

Event handler called when a pointer event occurs outside the bounds of the component. It can be prevented by calling event.preventDefault.

<Tooltip.Provider>
  <Tooltip>
     <Tooltip.Trigger id='trigger'>
      Hover me
    </Tooltip.Trigger>
    <Tooltip.Content onPointerDownOutside={(e) => {alert("Clicked outside"); e.preventDefault()} }>
      Tooltip text
    </Tooltip.Content>
  </Tooltip>
</Tooltip.Provider>