Presentation
Tooltip
Name a control or add a short hint when the pointer rests on it.
"use client"
import { Button } from "macbetter/button"
import { Tooltip, TooltipContent, TooltipShortcut, TooltipTrigger } from "macbetter/tooltip"
import { BoldIcon, ItalicIcon, UnderlineIcon } from "lucide-react"
const styles = [
{ label: "Bold", shortcut: "mod+b", Icon: BoldIcon },
{ label: "Italic", shortcut: "mod+i", Icon: ItalicIcon },
{ label: "Underline", shortcut: "mod+u", Icon: UnderlineIcon },
]
export default function Example() {
return (
<div style={{ display: "flex", gap: 4 }}>
{styles.map(({ label, shortcut, Icon }) => (
<Tooltip key={label} shortcut={shortcut}>
<TooltipTrigger render={<Button variant="plain" tone="neutral" shape="circle" aria-label={label} />}>
<Icon aria-hidden="true" />
</TooltipTrigger>
<TooltipContent>
{label}
<TooltipShortcut />
</TooltipContent>
</Tooltip>
))}
</div>
)
}When to use it
On the Mac, a help tag names an icon-only button or says briefly what a control does. Keep it to a few words, and describe the action, not the icon (“Bold”, not “B button”). Never put anything in a tooltip that people need: it only appears for someone who pauses with a pointer.
Touch screens have no hover, so on iPhone and iPad tooltips don’t appear at all. Label controls there with text, or use a Popover for a longer explanation.
Usage
import { Tooltip, TooltipContent, TooltipShortcut, TooltipTrigger } from "macbetter/tooltip"The help tag waits 400ms before it appears and appears at once on keyboard focus. Set delay for a longer pause, such as the Mac's own 800ms, or a shorter one. Once one is showing, moving to the next control shows its tag straight away, without the delay or the fade, so moving along a toolbar reads as one tag following the pointer.
Keyboard shortcuts
Give the root a shortcut and put TooltipShortcut in the content to show it, formatted for the platform (⌘B on Apple devices).
Info buttons on touch
For a button whose only job is the hint, toggleable opens and closes the tooltip on press, so it works with a finger too.
"use client"
import { Button } from "macbetter/button"
import { Tooltip, TooltipContent, TooltipTrigger } from "macbetter/tooltip"
import { InfoIcon } from "lucide-react"
export default function Example() {
return (
<div style={{ display: "flex", alignItems: "center", gap: 6 }}>
<span>Storage</span>
<Tooltip toggleable>
<TooltipTrigger render={<Button variant="plain" size="sm" shape="circle" aria-label="About storage" />}>
<InfoIcon aria-hidden="true" />
</TooltipTrigger>
<TooltipContent>Files in the Trash still use storage.</TooltipContent>
</Tooltip>
<span style={{ color: "var(--mb-label-secondary)" }}>12.4 of 15 GB used</span>
</div>
)
}Platform behavior
- macOS. A small rectangle of thick material with 6pt corners and 11pt text, below the control, with no arrow. It fades in quickly and out faster.
- iOS and iPadOS. No hover, so a plain tooltip never opens. A
toggleableone opens on tap with 13pt text.
Accessibility
- The tooltip names a trigger that has no name of its own, like an icon button, and describes any other. Set
typeto choose. - It opens when keyboard focus reaches the trigger and Escape closes it without moving focus.
- It can’t be focused, so never put links or buttons in it.
API
Tooltip
Takes every ui-sdk Tooltip root prop.
| Prop | Type | Default | Description |
|---|---|---|---|
delay | number | 400 | Milliseconds the pointer rests before it opens. |
closeDelay | number | 0 | Milliseconds it stays after the pointer leaves. |
shortcut | string | — | The trigger's keyboard shortcut, like mod+b, shown by TooltipShortcut. |
toggleable | boolean | false | Pressing the trigger opens and closes it, for touch. |
type | "label" | "description" | — | Whether it names or describes its trigger. |
TooltipContent
| Prop | Type | Default | Description |
|---|---|---|---|
side | "top" | "right" | "bottom" | "left" | "bottom" | Below the control, as macOS places help tags. |
sideOffset | number | 6 | The gap to the trigger. |
collisionPadding | number | 8 | Space kept from the window edges. |
TooltipTrigger and TooltipShortcut take ui-sdk’s props. createTooltipController is re-exported.
| Data attribute | On | Meaning |
|---|---|---|
data-side, data-align | .mb-tooltip | Where it landed |
data-instant | .mb-tooltip | Opened at once after another tag; skips the fade |
data-starting-style, data-ending-style | .mb-tooltip | Entering and leaving |
| CSS variable | Default |
|---|---|
--mb-tooltip-font | 11px on macOS, 13px on touch |
--mb-tooltip-padding | 3px 7px on macOS |