---
type: doc
title: Tooltip
description: Displays contextual information when a user hovers or focuses a trigger.
---

> Fulldev UI for Astro. The `@fulldev` registry in `components.json` points at `https://ui.full.dev/r/styles/{style}/{name}.json`; see [installation](/astro/docs/installation.md).

```astro title="src/components/examples/tooltip/tooltip-demo.astro"
---
import { buttonVariants } from "@/components/ui/button"
import {
  Tooltip,
  TooltipContent,
  TooltipTrigger,
} from "@/components/ui/tooltip"
---

<Tooltip>
  <TooltipTrigger class={buttonVariants({ variant: "outline" })}>
    Hover
  </TooltipTrigger>
  <TooltipContent>
    <p>Add to library</p>
  </TooltipContent>
</Tooltip>
```

## Installation

```bash
npx shadcn@latest add @fulldev/tooltip
```

## Usage

```ts
import {
  Tooltip,
  TooltipContent,
  TooltipTrigger,
} from "@/components/ui/tooltip"
```

```astro
<Tooltip>
  <TooltipTrigger>Hover</TooltipTrigger>
  <TooltipContent>
    <p>Add to library</p>
  </TooltipContent>
</Tooltip>
```

`TooltipTrigger` renders an unstyled `button`, or an `a` with `href`. Pass
`as="span"` or `as="div"` for another element, and
`class={buttonVariants({ variant: "outline" })}` for button styles.

## Composition

```text
Tooltip
├── TooltipTrigger
└── TooltipContent
```

## Side

Use the `side` prop on `TooltipContent` or `Tooltip` to change the position of
the tooltip. Logical sides `inline-start` and `inline-end` follow the text
direction.

```astro title="src/components/examples/tooltip/tooltip-sides.astro"
---
import { buttonVariants } from "@/components/ui/button"
import {
  Tooltip,
  TooltipContent,
  TooltipTrigger,
} from "@/components/ui/tooltip"
---

<div class="flex flex-wrap gap-2">
  {(["left", "top", "bottom", "right"] as const).map((side) => (
    <Tooltip>
      <TooltipTrigger
        class={buttonVariants({
          variant: "outline",
          class: "w-fit capitalize",
        })}
      >
        {side}
      </TooltipTrigger>
      <TooltipContent side={side}>
        <p>Add to library</p>
      </TooltipContent>
    </Tooltip>
  ))}
</div>
```

## With Keyboard Shortcut

```astro title="src/components/examples/tooltip/tooltip-keyboard.astro"
---
import SaveIcon from "@lucide/astro/icons/save"

import { buttonVariants } from "@/components/ui/button"
import { Kbd } from "@/components/ui/kbd"
import {
  Tooltip,
  TooltipContent,
  TooltipTrigger,
} from "@/components/ui/tooltip"
---

<Tooltip>
  <TooltipTrigger
    class={buttonVariants({ variant: "outline", size: "icon-sm" })}
  >
    <SaveIcon />
  </TooltipTrigger>
  <TooltipContent>
    Save Changes <Kbd>S</Kbd>
  </TooltipContent>
</Tooltip>
```

## Disabled Button

Show a tooltip on a disabled button by wrapping it with
`<TooltipTrigger as="span">`.

```astro title="src/components/examples/tooltip/tooltip-disabled.astro"
---
import { Button } from "@/components/ui/button"
import {
  Tooltip,
  TooltipContent,
  TooltipTrigger,
} from "@/components/ui/tooltip"
---

<Tooltip>
  <TooltipTrigger as="span" class="inline-block w-fit">
    <Button variant="outline" disabled>
      Disabled
    </Button>
  </TooltipTrigger>
  <TooltipContent>
    <p>This feature is currently unavailable</p>
  </TooltipContent>
</Tooltip>
```

## RTL

```astro title="src/components/examples/tooltip/tooltip-rtl.astro"
---
import { buttonVariants } from "@/components/ui/button"
import {
  Tooltip,
  TooltipContent,
  TooltipTrigger,
} from "@/components/ui/tooltip"

const translations = {
  en: {
    dir: "ltr",
    values: {
      content: "Add to library",
      "inline-start": "Inline Start",
      left: "Left",
      top: "Top",
      bottom: "Bottom",
      right: "Right",
      "inline-end": "Inline End",
    },
  },
  ar: {
    dir: "rtl",
    values: {
      content: "إضافة إلى المكتبة",
      "inline-start": "بداية السطر",
      left: "يسار",
      top: "أعلى",
      bottom: "أسفل",
      right: "يمين",
      "inline-end": "نهاية السطر",
    },
  },
  he: {
    dir: "rtl",
    values: {
      content: "הוסף לספרייה",
      "inline-start": "תחילת השורה",
      left: "שמאל",
      top: "למעלה",
      bottom: "למטה",
      right: "ימין",
      "inline-end": "סוף השורה",
    },
  },
}

const physicalSides = ["left", "top", "bottom", "right"] as const
const logicalSides = ["inline-start", "inline-end"] as const

const { dir, values: t } = translations.ar
---

<div class="grid gap-4">
  <div class="flex flex-wrap justify-center gap-2">
    {physicalSides.map((side) => (
      <Tooltip>
        <TooltipTrigger class={buttonVariants({ variant: "outline" })}>
          {t[side]}
        </TooltipTrigger>
        <TooltipContent side={side} dir={dir}>
          {t.content}
        </TooltipContent>
      </Tooltip>
    ))}
  </div>
  <div class="flex flex-wrap justify-center gap-2">
    {logicalSides.map((side) => (
      <Tooltip>
        <TooltipTrigger class={buttonVariants({ variant: "outline" })}>
          {t[side]}
        </TooltipTrigger>
        <TooltipContent side={side} dir={dir}>
          {t.content}
        </TooltipContent>
      </Tooltip>
    ))}
  </div>
</div>
```

## Content mounting

Data Slot's recommended `"lazy"` strategy is the default: closed content is
retained but detached from the document. Fulldev initializes nested Data Slot
components inside that retained content too.

Use `mountStrategy="eager"` when an integration needs to query closed content
through the document. Both strategies include content in server-rendered HTML;
neither adds a no-JavaScript fallback.

## API Reference

Source: [`src/components/ui/tooltip`](https://github.com/fulldotdev/ui/tree/main/src/components/ui/tooltip)

### Tooltip

| Prop                | Type                                                                       | Default    |
| ------------------- | -------------------------------------------------------------------------- | ---------- |
| `delay`             | `number`                                                                   | `300`      |
| `skipDelayDuration` | `number`                                                                   | `300`      |
| `side`              | `"top" \| "right" \| "bottom" \| "left" \| "inline-start" \| "inline-end"` | `"top"`    |
| `align`             | `"start" \| "center" \| "end"`                                             | `"center"` |
| `sideOffset`        | `number`                                                                   | `4`        |
| `alignOffset`       | `number`                                                                   | `0`        |
| `avoidCollisions`   | `boolean`                                                                  | `true`     |
| `collisionPadding`  | `number`                                                                   | `8`        |
| `mountStrategy`     | `"lazy" \| "eager"`                                                        | `"lazy"`   |

`TooltipContent` takes the same placement props and overrides the root.

See the [Data Slot tooltip docs](https://github.com/bejamas/data-slot/blob/main/packages/tooltip/README.md)
for events and programmatic control.

## Install what this page shows

```bash
npx shadcn@latest add @fulldev/tooltip-examples
```
