# Tooltip

An accessible React tooltip for Next.js and Tailwind CSS: a short hint on hover and keyboard focus, fast across a toolbar, built on Radix Tooltip.

Source: https://ui.fewtone.com/components/tooltip

## Installation

```bash
npx shadcn@latest add https://ui.fewtone.com/r/tooltip.json
```

## Usage

```tsx
import { Button } from "@/components/ui/button"
import {
  Tooltip,
  TooltipContent,
  TooltipProvider,
  TooltipTrigger,
} from "@/components/ui/tooltip"
import { Undo2Icon } from "lucide-react"

export function UndoButton() {
  return (
    <TooltipProvider>
      <Tooltip>
        <TooltipTrigger asChild>
          <Button variant="ghost" size="icon" aria-label="Undo">
            <Undo2Icon />
          </Button>
        </TooltipTrigger>
        <TooltipContent>Undo</TooltipContent>
      </Tooltip>
    </TooltipProvider>
  )
}
```

## API reference

### TooltipProvider

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `delayDuration` | `number` | `300` | Milliseconds the pointer rests on a trigger before its tooltip opens. |
| `skipDelayDuration` | `number` | `300` | Milliseconds after a tooltip closes during which the next one opens at once, without the delay or the opening animation. |
| `disableHoverableContent` | `boolean` | `false` | Closes the tooltip as soon as the pointer leaves the trigger, even towards the tooltip. |

### Tooltip

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `open` | `boolean` | – | Whether it's open, when you control it. |
| `defaultOpen` | `boolean` | `false` | Whether it starts open. |
| `onOpenChange` | `(open: boolean) => void` | – | Called when it opens or closes. |
| `delayDuration` | `number` | – | Overrides the provider's delay for this tooltip. |

### TooltipTrigger

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `asChild` | `boolean` | `false` | Render the single child (for example a Button) as the trigger. |

### TooltipContent

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `side` | `"top" \| "right" \| "bottom" \| "left"` | `"top"` | The side of the trigger it shows on. It flips when there's no room. |
| `align` | `"start" \| "center" \| "end"` | `"center"` | How it lines up with the trigger along that side. |
| `sideOffset` | `number` | `4` | Gap between the trigger and the tooltip, in px. |

**When to use it:** Use Tooltip for a short text hint on a control, most often the name of an icon button, shown on hover and focus. Keep anything interactive or long out of it: use Popover for that, and Hover Card for a preview of a link.
**Built on:** Radix Tooltip.
**Accessibility pattern:** https://www.w3.org/WAI/ARIA/apg/patterns/tooltip/
**npm packages (installed by the CLI):** radix-ui@^1.7.0.

## Examples

### A toolbar

Hover a button, or reach it with Tab: after a moment its tooltip opens out of it. Then move along the row and the next tooltips appear at once, each taking the last one's place. Escape closes it.

```tsx
"use client";

import { Button } from "@/components/ui/button";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import {
  Tooltip,
  TooltipContent,
  TooltipProvider,
  TooltipTrigger,
} from "@/components/ui/tooltip";
import {
  DownloadIcon,
  type LucideIcon,
  MessageSquarePlusIcon,
  Redo2Icon,
  Share2Icon,
  Undo2Icon,
} from "lucide-react";
import { Fragment, useId, useState } from "react";

type Side = "top" | "right" | "bottom" | "left";

const groups: { label: string; icon: LucideIcon }[][] = [
  [
    { label: "Undo", icon: Undo2Icon },
    { label: "Redo", icon: Redo2Icon },
  ],
  [
    { label: "Add a comment", icon: MessageSquarePlusIcon },
    { label: "Share", icon: Share2Icon },
    { label: "Download", icon: DownloadIcon },
  ],
];

/*
 * A toolbar of icon buttons, each with a tooltip, and the side in the top-right corner. Hover one, then move
 * along the row: the next tooltips appear at once. An empty row at the bottom, as tall as the setting's
 * row, keeps the toolbar centred.
 */
export default function TooltipToolbar() {
  const id = useId();
  const [side, setSide] = useState<Side>("top");

  return (
    <div className="flex w-full flex-col gap-6 self-stretch">
      <div className="-mt-6 -mr-6 flex items-center justify-end gap-2">
        <label htmlFor={`${id}-side`} className="text-sm text-muted-foreground">
          Side
        </label>
        <Select value={side} onValueChange={(value) => setSide(value as Side)}>
          <SelectTrigger id={`${id}-side`} size="sm" className="w-28">
            <SelectValue />
          </SelectTrigger>
          <SelectContent>
            <SelectItem value="top">Top</SelectItem>
            <SelectItem value="right">Right</SelectItem>
            <SelectItem value="bottom">Bottom</SelectItem>
            <SelectItem value="left">Left</SelectItem>
          </SelectContent>
        </Select>
      </div>

      <div className="flex flex-1 items-center justify-center">
        {/* One provider for the row, so its tooltips share the delay and hand over to each other */}
        <TooltipProvider>
          <div className="flex items-center gap-1">
            {groups.map((group, index) => (
              <Fragment key={group[0]?.label}>
                {index > 0 ? <div aria-hidden className="mx-1 h-5 w-px bg-border" /> : null}
                {group.map(({ label, icon: Icon }) => (
                  <Tooltip key={label}>
                    <TooltipTrigger asChild>
                      <Button variant="ghost" size="icon" aria-label={label}>
                        <Icon aria-hidden />
                      </Button>
                    </TooltipTrigger>
                    <TooltipContent side={side}>{label}</TooltipContent>
                  </Tooltip>
                ))}
              </Fragment>
            ))}
          </div>
        </TooltipProvider>
      </div>

      <div aria-hidden className="-mb-6 h-(--size-control-sm)" />
    </div>
  );
}
```

## Related

- [Popover](https://ui.fewtone.com/components/popover.md): An accessible React popover for Next.js and Tailwind CSS: forms, settings and other rich content anchored to a button, built on Radix Popover.
- [Hover Card](https://ui.fewtone.com/components/hover-card.md): An accessible React hover card for Next.js and Tailwind CSS: a preview card for a link, like a profile on an @mention, built on Radix Hover Card.
- [Button](https://ui.fewtone.com/components/button.md): An accessible React button for Next.js and Tailwind CSS with six variants, three sizes, icons and a soft tint on hover and press, built on a native button.
