# Tooltip

## Overview

The tooltip component displays a short supplemental message when an element is hovered or focused.

Add `data-tooltip` and `aria-description` to the element that owns the message. `data-tooltip` supplies the CSS-generated visual content, while `aria-description` makes the same message available as an accessible description. Their values must be identical. The component does not require additional tooltip markup.

Use tooltips for concise, nonessential clarification. Put required instructions, validation messages, errors, and other information needed to complete a task directly in the interface.

## When to use

Use a tooltip for concise, nonessential clarification on an element users can hover or focus.

## When not to use

Do not use a tooltip for required instructions, validation, errors, an icon-only control's only accessible name, or content that must satisfy hoverable and dismissible behavior by itself.

## Usage

Attach the tooltip to a naturally focusable element whenever possible. This gives pointer and keyboard users access to the same visual message.

```html
<button
  type="button"
  data-tooltip="Save your changes"
  aria-description="Save your changes"
>
  Save
</button>
```

Keep tooltip text short. Longer messages wrap when they reach the component's maximum width.

## Placement

Tooltips appear above their element by default. Set `data-placement` to `bottom`, `left`, or `right` to choose another side.

```html
<button data-tooltip="Shown above" aria-description="Shown above">Top</button>
<button data-tooltip="Shown below" aria-description="Shown below" data-placement="bottom">Bottom</button>
<button data-tooltip="Shown to the left" aria-description="Shown to the left" data-placement="left">Left</button>
<button data-tooltip="Shown to the right" aria-description="Shown to the right" data-placement="right">Right</button>
```

Placement is explicit. The component does not detect viewport edges or automatically switch sides.

## Behavior

Covered by [Playwright behavior tests](../../tests/e2e/components.spec.js).

- TTP-001: `data-tooltip` supplies the displayed text.
- TTP-002: `aria-description` supplies the accessible description and must contain the same text as `data-tooltip`.
- TTP-003: Hovering the owning element reveals the tooltip.
- TTP-004: Focusing the owning element reveals the tooltip.
- TTP-005: Removing both hover and focus hides the tooltip.
- TTP-006: Tooltip opacity transitions over `0.15s` when its visibility state changes.
- TTP-007: Messages use their natural width up to `20rem` or the available viewport width, whichever is smaller.
- TTP-008: Long messages and unbroken strings wrap within that maximum width.
- TTP-009: The `::before` pseudo-element renders the message box.
- TTP-010: The `::after` pseudo-element renders the pointer.
- TTP-011: `data-placement` changes the position of both pseudo-elements.
- TTP-012: Tooltip content cannot contain links, controls, formatting, or other HTML.
- TTP-013: The tooltip surface uses the shared subtle border without an elevation shadow.

## Accessibility

This component is a supplemental visual enhancement, not an implementation of the unfinished WAI-ARIA tooltip interaction pattern.

- Pair `data-tooltip` with an identical `aria-description` so the message is available as an accessible description instead of relying on CSS-generated content alone.
- Ensure the owning element is keyboard-focusable. Prefer native interactive elements over adding `tabindex` to static elements.
- Preserve a visible focus indicator on the owning element.
- Do not add `role="tooltip"` to the owning element. That role is intended for a separate tooltip container, which this component does not create.
- Do not use `aria-label` for supplemental tooltip text. It replaces the element's accessible name instead of providing an accessible description.
- Do not add `aria-haspopup` or `aria-expanded`; this component does not expose a popup control or expanded state.
- Do not place interactive or essential content in a tooltip.
- Do not use a tooltip as the accessible name of an icon-only control unless the control also provides that name programmatically.

Because the generated tooltip uses `pointer-events: none`, users cannot move the pointer onto it. It also has no independent Escape dismissal behavior. Consequently, this component does not by itself satisfy every requirement of [WCAG 2.2 Success Criterion 1.4.13: Content on Hover or Focus](https://www.w3.org/WAI/WCAG22/Understanding/content-on-hover-or-focus.html) when the tooltip obscures other content.

## Variables

| Variable | Type | Description |
| --- | --- | --- |
| `--tooltip-background` | `<color>` | Sets tooltip bubble background for default and inverted themes; change it when tooltip surfaces need different contrast from the page. |
| `--tooltip-border-color` | `<color>` | Sets tooltip border color; change it when the bubble needs clearer separation from nearby content or inverted surfaces. |
| `--tooltip-border-radius` | `<length>` | Sets tooltip bubble corner radius; change it to align tooltip shape with the rest of the surface system. |
| `--tooltip-border-width` | `<length>` | Sets the tooltip surface border width; change it when the tooltip bubble needs a stronger or subtler edge. |
| `--tooltip-color` | `<color>` | Sets tooltip text color; change it when the tooltip background requires a different accessible foreground. |
| `--tooltip-font-family-sans` | `Any` | Sets --tooltip-font-family-sans so the component can default to shared theme or layout tokens while exposing an overrideable component API. |
| `--tooltip-font-size-caption` | `<length>` | Sets --tooltip-font-size-caption so the component can default to shared theme or layout tokens while exposing an overrideable component API. |
| `--tooltip-line-height` | `<number>` | Sets --tooltip-line-height so the component can default to shared theme or layout tokens while exposing an overrideable component API. |
| `--tooltip-margin` | `<length>` | Sets the gap between the trigger and tooltip for all placements; change it when tooltips should sit closer to or farther from the anchor. |
| `--tooltip-max-size` | `<length>` | Sets the maximum tooltip width while respecting viewport gutters; change it when tooltip copy needs narrower or wider wrapping. |
| `--tooltip-padding` | `<length>` | Sets the internal tooltip padding; change it when tooltip content should feel denser or more spacious. |

## Depends On

- `--color-accent-subtle`
- `--color-border-subtle`
- `--color-border-subtle-inverse`
- `--color-primary-strong`
- `--color-text`
- `--color-text-inverse`
- `--font-family-sans`
- `--font-line-height-body`
- `--font-size-caption`
- `--layout-control-radius`
- `--layout-space-inline`
- `--layout-space-stack`
- `--layout-surface-border-width`
