# Tooltip

**Maturity:** stable

A short glass label that floats next to a trigger while the pointer hovers it or the trigger holds keyboard focus, describing that trigger — the web analogue of SwiftUI's .help(:) (macOS / iPadOS-with-pointer) and UIKit's UIToolTipInteraction (iPadOS 16+).

## Import

```tsx
import { Tooltip } from "@liquidify/react/tooltip"
```

## Props

- `align`: `TooltipAlign | undefined`; default ``"center"``. Cross-axis alignment of the panel against the trigger.
- `aria-label`: `string | undefined`. Accessible name of the panel itself, if needed beyond `aria-describedby`.
- `aria-labelledby`: `string | undefined`. Id of the element labelling the panel.
- `className`: `string | undefined`. Optional additional CSS class merged into the glass surface class. The supported per-instance customisation seam: override any `--lq-*` custom property from this class's CSS — the token cascade the engine reads (ADR-0004). No raw inline style is involved, so this stays ADR-0003 clean.
- `defaultOpen`: `boolean | undefined`; default ``false``. Uncontrolled seed for the open state.
- `delay`: `number | undefined`; default `{@link DEFAULT_TOOLTIP_DELAY_MS }`. Hover-open delay in milliseconds; keyboard focus opens immediately.
- `label`: `ReactNode` (required). The tooltip's short text body — mirrors `.help`'s single text argument.
- `material`: `"frosted" | "regular" | "clear" | undefined`; default `enclosing `<Material default>`, else `"regular"``. Material of the glass surface — `frosted · regular · clear` (§06). Forwarded to the engine, which resolves the chain `prop ?? <Material default> ?? "regular"`, so a bare surface inherits the enclosing provider default.
- `onOpenChange`: `((open: boolean) => void) | undefined`. Fires with the next boolean on every show/hide path.
- `open`: `boolean | undefined`. Controlled open state.
- `perf`: `"low" | "high" | undefined`; default `derived from `<Backdrop type>`, else `"low"``. Perf budget of the glass surface (ADR-0006/0007). Forwarded to the engine as `data-glass-perf`; `"high"` opts this surface into the edge-lensing filter. When omitted, derives from the enclosing `<Backdrop type>` (§04).
- `placement`: `TooltipPlacement | undefined`; default ``"top"``. Which trigger edge the panel sits on (forwarded to `Popup`).
- `ref`: `Ref<HTMLDivElement> | undefined`. Forwarded ref to the rendered element — the component's native root (or the merged child element on a component that opts into {@link SlottableProps}). Generic over `E` (charter `docs/api-conventions.md` §4 rule 1, default `HTMLElement`) so a component with a polymorphic root (Link's navigation / action mode union, Text's `as`) can instantiate the concrete element per variant instead of leaving every consumer with a widened `Ref<HTMLElement>`. A component that does not narrow simply inherits the `HTMLElement` default — source-compatible with every pre-existing non-generic `extends ControlProps`.
- `trigger`: `ReactNode` (required). The anchored trigger element, merged via `Popup.Trigger asChild`.

## SwiftUI mapping

- ``.help(_ textKey: LocalizedStringKey)` / `.help(_ text: Text)` / `.help<S>(_ string: S)` / `UIToolTipConfiguration.title`` → ``label: ReactNode`` (direct): The tooltip's text body — mirrors `.help`'s single text argument. **Text / inline only, no focusable descendants** (APG); enforcement is a runtime dev warning (Open questions §8). `label` vs `content` naming is Open questions §8.
- `(the modified view)` → ``trigger: ReactNode`` (direct): The anchored element, merged via `Popup.Trigger asChild` (ADR-0016); receives **`aria-describedby`** (only while shown), **not** the disclosure triad.
- `(system-owned placement)` → ``placement?: "top" | "bottom" | "left" | "right"`` (direct): Forwarded to `Popup`. `placement` names the *trigger* side the panel sits on (Popup-native), with collision auto-flip. Apple exposes no placement API → default `"top"` is an inference (Open questions §4).
- ``attachmentAnchor` (no `.help` analogue)` → ``align?: "start" | "center" | "end"` (`"center"` default)` (direct): Popup's cross-axis alignment.
- `(system-owned show delay)` → ``delay?: number` (ms)` (direct): Hover-open delay; keyboard-focus opens immediately (APG). Apple exposes no public value → a token-backed default (`--lq-tooltip-delay`, value TBD) is proposed (Open questions §7). *Inference.*
- ``UIToolTipInteraction` open/close (system)` → ``open?` / `defaultOpen?` / `onOpenChange?`` (direct): Presentation triad (ADR-0015 / ADR-0017) — **optional**; the primary driver is hover/focus, not a controlled click. `open` is controlled iff `open !== undefined` (audit §8). Whether to expose the triad at all is Open questions §5.
- `(presentation chrome)` → ``material?` / `perf?`` (direct): `PresentationalProps` (ADR-0023) — the label's glass surface (default `frosted`, an inference — no sim; Open questions §6). Materials: `frosted` · `regular` · `clear`. The base is tint-free (no `tint` axis).
- ``.help` supplies the a11y help/hint` → ``aria-label` / `aria-labelledby`` (direct): The label text is the accessible **description** of the trigger (`aria-describedby`), not a name; a supplied `aria-label` names the panel itself only if needed.
- `(no SwiftUI analogue)` → ``ref?: Ref<HTMLDivElement>`` (web-only): `TooltipProps extends PresentationalProps<HTMLDivElement>` — forwarded to the semantic root, the portalled `role="tooltip"` glass panel; attached while shown, `null` while hidden.
