MenuChevron Down
Tooltip - Docs - Artefact

Tooltip

Overlays
Auto-interactive

Introduction

A component for displaying contextual information on hover or focus.

Usage

High-level wrapper

import { Tooltip } from "../components/ui/tooltip";
import { Button } from "../components/ui/button";

export default function MyPage() {
  return (
    <Tooltip content="This is the tooltip content" placement="bottom" showArrow asChild>
      <Button>Hover me</Button>
    </Tooltip>
  );
}

Prefer asChild when the trigger is already a focusable element (a Button, a link, …): it merges the tooltip's aria-describedby, hover/focus listeners, and data-* attributes directly onto that element. Without asChild, the trigger is wrapped in an extra <div tabindex="0"> — useful for wrapping inert content (plain text, an icon) that isn't itself focusable, but it adds a second, redundant tab stop when the child is already interactive.

CMS Page Builder

This component is available as a tooltip block in the Page Builder (content/pages/*.json). The CMS trigger is a plain triggerText string, auto-wrapped in an outline Button with asChild (the same pattern Popover/HoverCard use):

{
  "type": "tooltip",
  "content": "Free cancellation up to 24 hours before check-in.",
  "triggerText": "Cancellation Policy",
  "placement": "top",
  "showArrow": true
}

Props

Tooltip (High-level wrapper)

PropTypeDescription
childrenanyThe element that triggers the tooltip.
contentanyThe content to display within the tooltip.
showArrowbooleanWhether to show an arrow pointing to the trigger.

| placement | `"top" \ | "bottom" \ | "left" \ | "right"` | Which side of the trigger the content opens on. Default "top". Flips to the opposite side automatically if there isn't enough viewport room. |

| open | boolean | Whether the tooltip is open (controlled). | | defaultOpen | boolean | Initial open state (uncontrolled). Default false. | | onOpenChange | (details: { open: boolean }) => void | Called when the tooltip opens or closes. | | openDelay | number | Delay (ms) before showing on hover. Default 100. | | closeDelay | number | Delay (ms) before hiding on mouse-out. Default 100. | | closeOnEscape | boolean | Close when Escape is pressed. Default true. | | disabled | boolean | Whether the tooltip is disabled. | | interactive | boolean | Forces hydration as an island. Defaults to true. | | id | string | Unique identifier for the tooltip. | | asChild | boolean | Whether to merge props onto the immediate child element instead of wrapping in a div. |

Hovering onto or focusing the trigger opens the tooltip; moving the pointer onto the tooltip's own content (e.g. a link inside it) keeps it open, per WCAG 1.4.13. Focusing the trigger (keyboard navigation) opens it immediately, and blurring closes it immediately — the openDelay/closeDelay only apply to hover.

Limitations

The interactive island positions and sizes the tooltip relative to its trigger: it flips to the opposite side (e.g. topbottom) when the requested placement would overflow the viewport, and clamps the cross axis so the content never renders off-screen. It does not track scroll containers or resize observers the way Floating UI does — repositioning only re-runs when the tooltip opens and on window resize.