bx

Tooltip

A popup that displays information related to an element on focus or hover.

tsx
<Tooltip>
  <TooltipTrigger>
    <Button variant="outline">Hover</Button>
  </TooltipTrigger>
  <TooltipContent>Add to library</TooltipContent>
</Tooltip>

Tooltip is a contextual hint that appears when the trigger is hovered or focused. Keep the content short (name of an icon button, keyboard shortcut, brief description). For rich content, use HoverCard.

PRISM pattern: the trigger and the content are siblings inside a Tooltip wrapper. The content is rendered with the hidden attribute; the ui.js island removes it when the pointer enters the wrapper or when focus moves inside it, and restores it on leave, on blur and on Escape.

Shorthand: <Tooltip trigger={…} content="…" /> builds the TooltipTrigger and TooltipContent for you.

Installation

Terminal
$ bext ui add tooltip

Usage

tsx
import { Tooltip, TooltipTrigger, TooltipContent, Button } from "@bext-stack/ui/primitives"

<Tooltip>
  <TooltipTrigger>
    <Button variant="outline">Hover</Button>
  </TooltipTrigger>
  <TooltipContent>Add to library</TooltipContent>
</Tooltip>

Anatomy

<Tooltip>
  ├── <TooltipTrigger>
  │   └── <Button>Hover me</Button>
  └── <TooltipContent>Add to library</TooltipContent>

API Reference

Tooltip

Prop Type Default Description
children ReactNode — Composed form: a TooltipTrigger and a TooltipContent.
trigger ReactNode — Shorthand: the trigger element. Used with content instead of children.
content ReactNode — Shorthand: the tooltip text.
id string — Shorthand: id given to the TooltipContent.
className string — Extra classes on the wrapper, a with relative inline-flex.

TooltipTrigger

Prop Type Default Description
children ReactNode — Trigger element. Use a focusable one (button, link) so the tooltip also shows on keyboard focus.

TooltipContent

Prop Type Default Description
id string — Optional id. Without it the island generates one to build aria-describedby on the trigger.
children ReactNode — Tooltip text.
className string — Extra classes. Default: absolute, above the trigger and centered, bg-primary text-primary-foreground text-xs px-3 py-1.5 rounded-md, single line.

Data Attributes

Attributes you can target in custom CSS to override the style for each state.

Attribute On Values Description
data-ui="tooltip" Tooltip — The island listens for pointer and focus events on this wrapper.
data-ui="tooltip-trigger" TooltipTrigger — Marks the trigger wrapper. The island sets aria-describedby on the focusable element inside it.
data-ui="tooltip-content" TooltipContent hidden attribute present or absent The island shows it by removing hidden and hides it by restoring it.

Keyboard

Key Action
Tab Focusing the trigger shows the tooltip; moving focus away hides it.
Escape Hides the tooltip. Focus stays on the trigger.

Accessibility

TooltipContent has role="tooltip". The island gives it an id when it has none and sets aria-describedby on the focusable element inside TooltipTrigger, so the text is announced as the description of that element. A description is not a name: an icon-only button still needs its own aria-label.

The tooltip shows on hover and on keyboard focus, provided the trigger is focusable (a <button> or a link). It stays visible while the pointer is over it, and Escape hides it without moving focus.

Content must stay short (≤ 60 characters). For more, use HoverCard or Popover.

Examples

On an icon button

tsx
<Tooltip>
  <TooltipTrigger>
    <Button variant="outline" size="icon" aria-label="Copy"><CopyIcon /></Button>
  </TooltipTrigger>
  <TooltipContent>Copy to clipboard</TooltipContent>
</Tooltip>
Try it live
Open in play

Edit this component live in the bext playground. The PRISM + signals version is the bext-native idiom: fine-grained reactivity, no virtual DOM.

src/app/page.tsx 2 files · signals · runs in your browser
Pure PRISM + real bext signals: fine-grained, no re-render.