---
id: "packages/active-ui/tooltip"
title: "Tooltip"
description: "A short label shown on hover and keyboard focus, for an icon button or a truncated text."
url: "/packages/active-ui/tooltip"
locale: "en"
revision: "53df4467a446df91"
---

# Tooltip

A tooltip shows a few words next to an element while the pointer rests on it or it has keyboard
focus: the name of an icon button, the full text of a truncated label. It holds no interactive
content and nothing the reader cannot do without; on a touch screen it is never seen. For content
the reader works with, use a [popover](/packages/active-ui/popover).

**Example: Labels for icon buttons**

Client: Runs entirely in your browser. Source: `examples/ui/tooltip.tsx`.

```tsx
// apps/docs/examples/ui/tooltip.tsx
'use client';

import {useState} from 'react';
import {CopyIcon, DownloadIcon, PrinterIcon} from 'lucide-react';

import {Button} from '@workspace/active-ui/components/primitives/button';
import {
  Tooltip,
  TooltipContent,
  TooltipProvider,
  TooltipTrigger,
} from '@workspace/active-ui/components/primitives/tooltip';

const ACTIONS = [
  {label: 'Copy the statement', icon: CopyIcon},
  {label: 'Download as PDF', icon: DownloadIcon},
  {label: 'Print', icon: PrinterIcon},
];

/**
 * A short label for an icon button, shown on pointer hover and on keyboard
 * focus. The tooltip repeats the button's accessible name for sighted
 * readers; it is not the name. One `TooltipProvider` makes the next tooltip
 * open at once while the pointer moves along a row of buttons.
 */
export default function TooltipExample() {
  const [last, setLast] = useState<string | null>(null);
  return (
    <div className="flex flex-col items-center gap-3">
      <TooltipProvider>
        <div className="flex gap-1" role="group" aria-label="Statement">
          {ACTIONS.map(({label, icon: Icon}) => (
            <Tooltip key={label}>
              <TooltipTrigger
                render={
                  <Button
                    variant="ghost"
                    size="icon"
                    aria-label={label}
                    onClick={() => setLast(label)}
                  />
                }
              >
                <Icon aria-hidden />
              </TooltipTrigger>
              <TooltipContent side="bottom">{label}</TooltipContent>
            </Tooltip>
          ))}
        </div>
      </TooltipProvider>
      <p className="text-muted-foreground text-sm" aria-live="polite">
        {last ? `Chosen: ${last}` : 'Hover or focus a button.'}
      </p>
    </div>
  );
}
```

## Usage

```tsx
import {
  Tooltip,
  TooltipContent,
  TooltipTrigger,
} from '@workspace/active-ui/components/primitives/tooltip';

<Tooltip>
  <TooltipTrigger
    render={<Button variant="ghost" size="icon" aria-label="Print" />}
  >
    <PrinterIcon aria-hidden />
  </TooltipTrigger>
  <TooltipContent>Print</TooltipContent>
</Tooltip>;
```

## Delays and the provider

- A tooltip opens after the pointer has rested on the trigger for `delay` (default `600` ms, on
  `TooltipTrigger`) and closes after `closeDelay` (default `0`).
- `TooltipProvider` groups tooltips. In this package its `delay` is `0`: every tooltip inside it
  opens at once. Put one provider around a row of icon buttons, or around the application, when
  readers move from one button to the next; leave it out where an immediate tooltip would get in
  the way.
- `TooltipContent` is placed by `side` (default `top`) and `align`, with an arrow.

## What your application provides

- **The accessible name of the trigger**, as `aria-label` or visible text. The tooltip is not the
  name: it repeats it for sighted readers.
- The tooltip text, in your reader's language.

## Accessibility and keyboard

- Keyboard focus on the trigger opens the tooltip as hover does; `Escape` closes it.
- The trigger stays an ordinary button or link: the tooltip adds no tab stop.

## API

### TooltipContent

| Prop | Type | Required | Description |
| --- | --- | --- | --- |
| `align` | `Align` | no | How to align the popup relative to the specified side. |
| `alignOffset` | `number \| OffsetFunction` | no | Additional offset along the alignment axis in pixels. Also accepts a function that returns the offset to read the dimensions of the anchor and positioner elements, along with its side and alignment.  The function takes a `data` object parameter with the following properties: - `data.anchor`: the dimensions of the anchor element with properties `width` and `height`. - `data.positioner`: the dimensions of the positioner element with properties `width` and `height`. - `data.side`: which side of the anchor element the positioner is aligned against. - `data.align`: how the positioner is aligned relative to the specified side. |
| `render` | `ComponentRenderFn<HTMLProps, TooltipPopupState> \| ReactElement<unknown, string \| JSXElementConstructor<any>>` | no | Allows you to replace the component's HTML element with a different tag, or compose it with another component.  Accepts a `ReactElement` or a function that returns the element to render. |
| `side` | `Side` | no | Which side of the anchor element to align the popup against. May automatically change to avoid collisions. |
| `sideOffset` | `number \| OffsetFunction` | no | Distance between the anchor and the popup in pixels. Also accepts a function that returns the distance to read the dimensions of the anchor and positioner elements, along with its side and alignment.  The function takes a `data` object parameter with the following properties: - `data.anchor`: the dimensions of the anchor element with properties `width` and `height`. - `data.positioner`: the dimensions of the positioner element with properties `width` and `height`. - `data.side`: which side of the anchor element the positioner is aligned against. - `data.align`: how the positioner is aligned relative to the specified side. |

### TooltipProvider

| Prop | Type | Required | Description |
| --- | --- | --- | --- |
| `children` | `ReactNode` | no |  |
| `closeDelay` | `number` | no | How long to wait before closing a tooltip. Specified in milliseconds. |
| `delay` | `number` | no | How long to wait before opening the tooltip on hover. Specified in milliseconds. |
| `timeout` | `number` | no | Another tooltip will open instantly if the previous tooltip is closed within this timeout. Specified in milliseconds. |

### Other parts

**Tooltip**

| Prop | Type | Required | Description |
| --- | --- | --- | --- |
| `actionsRef` | `RefObject<TooltipRootActions \| null>` | no | A ref to imperative actions. - `unmount`: Ends the closing phase of the tooltip after an externally controlled closing animation finishes. Call `preventUnmountOnClose()` in `onOpenChange` first, otherwise the tooltip completes closing on its own. Whether it leaves the DOM is decided by `keepMounted` on the portal. - `close`: Closes the tooltip imperatively when called. |
| `children` | `PayloadChildRenderFunction<unknown> \| ReactNode` | no | The content of the tooltip. This can be a regular React node or a render function that receives the `payload` of the active trigger. |
| `defaultOpen` | `boolean` | no | Whether the tooltip is initially open.  To render a controlled tooltip, use the `open` prop instead. |
| `defaultTriggerId` | `string \| null` | no | ID of the trigger that the tooltip is associated with. This is useful in conjunction with the `defaultOpen` prop to create an initially open tooltip. |
| `disabled` | `boolean` | no | Whether the tooltip is disabled. |
| `disableHoverablePopup` | `boolean` | no | Whether the tooltip contents can be hovered without closing the tooltip. |
| `handle` | `TooltipHandle<unknown>` | no | A handle to associate the tooltip with a trigger. If specified, allows external triggers to control the tooltip's open state. Can be created with the Tooltip.createHandle() method. |
| `onOpenChange` | `((open: boolean, eventDetails: TooltipRoot.ChangeEventDetails) => void)` | no | Event handler called when the tooltip is opened or closed. |
| `onOpenChangeComplete` | `((open: boolean) => void)` | no | Event handler called after any animations complete when the tooltip is opened or closed. |
| `open` | `boolean` | no | Whether the tooltip is currently open. |
| `trackCursorAxis` | `"both" \| "none" \| "x" \| "y"` | no | Determines which axis the tooltip should track the cursor on. |
| `triggerId` | `string \| null` | no | ID of the trigger that the tooltip is associated with. This is useful in conjunction with the `open` prop to create a controlled tooltip. There's no need to specify this prop when the tooltip is uncontrolled (that is, when the `open` prop is not set). |

**TooltipTrigger**

| Prop | Type | Required | Description |
| --- | --- | --- | --- |
| `closeDelay` | `number` | no | How long to wait before closing the tooltip. Specified in milliseconds. |
| `closeOnClick` | `boolean` | no | Whether the tooltip should close when this trigger is clicked. |
| `delay` | `number` | no | How long to wait before opening the tooltip on hover. Specified in milliseconds. |
| `disabled` | `boolean` | no | If `true`, the tooltip will not open when interacting with this trigger. Note that this doesn't apply the `disabled` attribute to the trigger element. If you want to disable the trigger element itself, you can pass the `disabled` prop to the trigger element via the `render` prop. |
| `handle` | `TooltipHandle<unknown>` | no | A handle to associate the trigger with a tooltip. |
| `payload` | `unknown` | no | A payload to pass to the tooltip when it is opened. |
| `render` | `ComponentRenderFn<HTMLProps, TooltipTriggerState> \| ReactElement<unknown, string \| JSXElementConstructor<any>>` | no | Allows you to replace the component's HTML element with a different tag, or compose it with another component.  Accepts a `ReactElement` or a function that returns the element to render. |

> [!NOTE]
> **Based on shadcn/ui**
>
> This page adapts the Tooltip documentation of shadcn/ui (MIT licence) to this
> package; see [Third-party notices](/third-party-notices).
