Tooltip
Props
| Prop | Type | Default | Options | Description |
|---|---|---|---|---|
| trigger | string | "hover" | hover, click | Open on hover (and on anchor focus when showOnFocus is true) or toggle on click |
| showOnFocus | boolean | true | — | When trigger is hover, keep the tooltip open while the anchor is focused. Set false for hover-only visibility (mouse leave hides it even if the field stays focused) |
| isSubtle | boolean | false | — | Subtle color scheme (light bg) vs high-contrast (dark bg) |
| size | string | "m" | s, m, l | Controls padding, border-radius, typography, and arrow dimensions |
| position | string | "top" | top, right, bottom, left | Preferred tooltip position (auto-flips if not enough space) |
| alignment | string | "center" | start, center, end | Cross-axis placement of the bubble vs the anchor; the arrow still targets the anchor center and may sit off-center on the bubble when the viewport clamps position |
| offset | number | 4 | — | Distance (px) between anchor and tooltip |
| maxWidth | string | "320px" | — | Max width of the tooltip body (CSS value). Use an empty string to remove the cap |
| disabled | boolean | false | — | Prevents the tooltip from showing |
| open | boolean | null | null | null, true, false | Manual override: null = use trigger (hover/focus or click), true = always open, false = always closed |
| showDelay | number | 100 | — | Delay (ms) before showing on hover |
| hideDelay | number | 100 | — | Delay (ms) before hiding after mouse leaves |
| testSelectors | object | See Test Selectors | Override data-test attributes for testing |
Controlling open from Vue
The open prop is intentionally tri-state (null = follow hover/click, true / false = forced open or closed).
If you bind :open="someRef" in a Vue 3 template and toggle someRef from false back to null, the tooltip can stay forced closed even though you intended uncontrolled mode. That behaviour comes from Vue’s runtime DOM patching, not from Catnip: for custom-element hosts, patchDOMProp can coerce null / undefined to false once the host property is already typed as a boolean (for example after false was applied once). This is tracked upstream as vuejs/core#14209. A related change proposal is vuejs/core#14459 — check whether it is merged in the Vue version you ship before assuming reactive :open can express null again.
What works today
- Set
openon the host element from script (for example a templaterefandwatch) so you assigntooltipRef.value.open = null(ortrue/false) directly. That path reaches the Vue custom-element setter without the same coercion, sonullcorrectly restores hover/click behaviour. - Plain attributes (
setAttribute/removeAttribute) on<catnip-tooltip>are fine for HTML-only apps; with automatic type conversion enabled, Catnip avoids stripping those attributes when coercing string values to booleans.
For the broader pattern (any catnip-* prop that needs null on a boolean-typed host property), see Usage — Vue 3: nullish values on custom elements.
Slots
| Name | Description |
|---|---|
| anchor | Trigger (defaults to info icon). With a custom anchor, use a focusable control (<button>, <a href>, etc.); the wrapper does not add tabindex, so focus stays on that control. |
| default | The tooltip content. |
Methods
| Method | Description |
|---|---|
reposition() | Manually recalculate tooltip position. Call after dynamic content changes (for example anchor resizes). |
<template>
<catnip-tooltip ref="tooltipRef">…</catnip-tooltip>
</template>
<script setup>
const tooltipRef = ref(null);
onMounted(() => {
// After layout change
tooltipRef.value?.reposition?.();
});
</script>Test Selectors
| Attribute | Default Value |
|---|---|
root | catnip-tooltip |
anchor | catnip-tooltip-anchor |
content | catnip-tooltip-content |