---
title: Tooltip
description: Show supplemental, non-interactive information on hover or focus.
package: moraine
version: 0.6.0
repository: https://github.com/subframe7536/moraine
---

# Tooltip

> Show supplemental, non-interactive information on hover or focus.

Use Tooltip for supplemental information on hover or focus. The trigger must still have its own accessible name when the control needs one.

## Basic usage

```tsx
import { Button, Tooltip } from 'moraine'

export function Example() {
  return (
    <Tooltip>
      <Tooltip.Trigger as={Button}>Save</Tooltip.Trigger>
      <Tooltip.Content>Save changes</Tooltip.Content>
    </Tooltip>
  )
}
```

## Anatomy

```text
Tooltip [component; no DOM]
├── Tooltip.Trigger [part; slot=trigger]
└── positioner [internal]
    └── Tooltip.Content [part; slot=content]
        └── kbds [slot]
            └── item [internal]
```

Content is portaled inside an internal positioning wrapper. String content uses the text slot; JSX content renders directly inside Content.

## Usage

### Supplemental information

Use tooltips for non-interactive hints that supplement an already labeled trigger. Do not use tooltip text as the sole accessible name of an icon-only control.

```tsx
import { Button, Tooltip } from 'moraine'

export function HintsUsage() {
  return (
    <div class="flex gap-4 items-center">
      <Tooltip>
        <Tooltip.Trigger as={Button} variant="outline">
          Deploy History
        </Tooltip.Trigger>
        <Tooltip.Content text="View project deployment history and logs" />
      </Tooltip>
    </div>
  )
}
```

### Triggering and shortcuts

Tooltip opens from pointer hover and focus. `kbds` displays shortcut notation alongside the hint; it does not register that shortcut. Set `kbdVariant` on `Tooltip.Content` to `default`, `outline`, or `invert`. When omitted, keycaps follow the content's `invert` setting.

```tsx
import { Button, Tooltip } from 'moraine'

export function ShortcutsUsage() {
  return (
    <div class="flex gap-4 items-center">
      <Tooltip>
        <Tooltip.Trigger as={Button} leading="i-lucide:save">
          Save
        </Tooltip.Trigger>
        <Tooltip.Content text="Save changes" kbds={['command', 's']} kbdVariant="outline" />
      </Tooltip>
    </div>
  )
}
```

### Keyboard interaction

Focusing a focusable trigger can display the tooltip. Escape dismisses an open tooltip according to the shared tooltip overlay behavior; focus remains on the trigger rather than moving into the tooltip content.

## Examples

### Keyboard shortcuts

```tsx
import { Button, Tooltip } from 'moraine'

export function KeyboardShortcuts() {
  return (
    <div class="p-2 b-1 b-border rounded-xl bg-card flex flex-wrap gap-2 items-center">
      <Tooltip>
        <Tooltip.Trigger as={Button} variant="outline" size="sm" leading="i-lucide:save">
          Save
        </Tooltip.Trigger>
        <Tooltip.Content text="Save changes" kbds={['⌘', 'S']} />
      </Tooltip>

      <Tooltip>
        <Tooltip.Trigger
          as={Button}
          variant="ghost"
          size="sm"
          leading="i-lucide:bold"
          aria-label="Bold"
        />
        <Tooltip.Content text="Bold formatting" kbds={['⌘', 'B']} />
      </Tooltip>

      <Tooltip>
        <Tooltip.Trigger
          as={Button}
          variant="ghost"
          size="sm"
          leading="i-lucide:italic"
          aria-label="Italic"
        />
        <Tooltip.Content text="Italic formatting" kbds={['⌘', 'I']} />
      </Tooltip>

      <Tooltip>
        <Tooltip.Trigger
          as={Button}
          variant="ghost"
          size="sm"
          leading="i-lucide:code"
          aria-label="Code"
        />
        <Tooltip.Content text="Insert Code Block" kbds={['⌘', 'E']} />
      </Tooltip>

      <Tooltip>
        <Tooltip.Trigger
          as={Button}
          variant="ghost"
          size="sm"
          leading="i-lucide:search"
          aria-label="Search"
        />
        <Tooltip.Content text="Quick Search" kbds={['⌘', 'K']} />
      </Tooltip>
    </div>
  )
}
```

## Attributes

| Attributes | Slot | Description |
| --- | --- | --- |
| `data-closed` | `tooltip-trigger`, `tooltip-content` | Present when disclosure or transition content is closed. |
| `data-disabled` | `tooltip-trigger` | Present when the component, slot, or item is disabled. |
| `data-expanded` | `tooltip-trigger`, `tooltip-content` | Present when the panel, accordion, or menu is expanded. |
| `data-align` | `tooltip-content` | Stores the resolved alignment of positioned content. |
| `data-instant-motion` | `tooltip-content` | Present when enter and exit motion should complete immediately. |
| `data-side` | `tooltip-content` | Stores the resolved floating or drawer content side. |

## Props

### Tooltip

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| align | 'start' \| 'center' \| 'end' \| undefined | 'center' | Alignment along the cross axis. |
| closeDelay | number \| undefined | 200 | Delay in milliseconds before closing after leaving trigger or content. |
| defaultOpen | boolean \| undefined | false | Initial open state when uncontrolled. |
| disabled | boolean \| undefined | false | Whether trigger interactions and content rendering are disabled. |
| forceMount | boolean \| undefined | false | Whether content remains mounted while closed. |
| id | string \| undefined | — | Unique identifier used to derive the content id. |
| instantOpenDelay | number \| undefined | 300 | Delay in milliseconds to skip the open delay for the next trigger after closing. |
| onOpenChange | ((open: boolean) => void) \| undefined | — | Called whenever the open state changes. |
| open | boolean \| undefined | — | Controlled open state. |
| openDelay | number \| undefined | 600 | Delay in milliseconds before opening on hover or focus. |
| placement | 'top' \| 'right' \| 'bottom' \| 'left' \| undefined | 'top' | Preferred content placement relative to the trigger. |
| children | JSX.Element \| undefined | — | Composed trigger and content primitives. |
| classes | Classes \| undefined | — | Family slot class defaults for this Tooltip instance. |
| styles | Styles \| undefined | — | Family slot style defaults for this Tooltip instance. |

### Tooltip.Trigger

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| disabled | boolean \| undefined | — | Whether this trigger is disabled. |
| as | T \| undefined | 'button' | Element or component to render as. |
| children | JSX.Element \| undefined | — | Trigger label and visual content. |
| class | SlotClassValue \| undefined | — | Class applied to the component root or trigger element. |
| style | SlotStyleValue \| undefined | — | Style applied to the component root or trigger element. |

### Tooltip.Content

Props for the Tooltip component.

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| invert | boolean \| undefined | false | Visual invert of the component. |
| kbds | string[] \| undefined | — | Keyboard shortcuts to display next to the text. |
| kbdVariant | 'default' \| 'outline' \| 'invert' \| undefined | — | Visual variant for the shortcut keycaps. Overrides the variant inferred from invert. |
| text | JSX.Element \| undefined | — | Primary text content or element to display. |
| children | JSX.Element \| undefined | — | Text content when text is undefined. |
| class | SlotClassValue \| undefined | — | Class applied to the component root or trigger element. |
| classes | ContentClasses \| undefined | — | Family slot class defaults for this instance. |
| style | SlotStyleValue \| undefined | — | Style applied to the component root or trigger element. |
| styles | ContentStyles \| undefined | — | Family slot style defaults for this instance. |
