Tooltip
Contextual hints that appear on hover or focus.
Playground
<Tooltip
label="Helpful hint"
placement="top"
>
<Button variant="outlined" size="sm">Hover me</Button>
</Tooltip>01 Examples
Wrap the trigger element as the child and pass the hint text in label. The tooltip opens on hover or focus after showDelay (200 ms) and follows placement (default top, auto-flipping when clipped). Set disabled to suppress it, or turn off the arrow for a plain chip.
Formatting toolbar
<Toolbar aria-label="Text formatting">
<Tooltip label="Bold (⌘B)" size="sm">
<Button variant="ghost" size="sm"><span class="font-bold">B</span></Button>
</Tooltip>
<Tooltip label="Italic (⌘I)" size="sm">
<Button variant="ghost" size="sm"><span class="italic">I</span></Button>
</Tooltip>
<Tooltip label="Underline (⌘U)" size="sm">
<Button variant="ghost" size="sm"><span class="underline">U</span></Button>
</Tooltip>
<Separator orientation="vertical" size="sm" />
<Tooltip label="Strikethrough (⌘⇧X)" size="sm">
<Button variant="ghost" size="sm"><span class="line-through">S</span></Button>
</Tooltip>
</Toolbar>Severity-matched tooltips
intent tints the tooltip to the state it reports, so the colour reinforces the message.{#each services as row (row.service)}
<Tooltip label={row.detail} intent={row.intent} placement="bottom">
<Badge variant="soft" intent={row.intent}>{row.status}</Badge>
</Tooltip>
{/each}Reveal truncated text
- Q4-roadmap-final-with-stakeholder-feedback-v3.pdf Q4-roadmap-final-with-stakeholder-feedback-v3.pdf 2.4 MB
- design-system-token-migration-notes.md design-system-token-migration-notes.md 18 KB
- customer-interview-transcripts-jan-2026.zip customer-interview-transcripts-jan-2026.zip 14.2 MB
<ul class="divide-border-subtle mx-auto w-full max-w-sm divide-y text-sm">
{#each files as file (file.name)}
<li class="flex items-center justify-between gap-3 py-2.5">
<Tooltip label={file.name} placement="top-start" size="sm">
<span class="text-text-primary block max-w-[14rem] truncate">{file.name}</span>
</Tooltip>
<span class="text-text-tertiary shrink-0 text-xs">{file.size}</span>
</li>
{/each}
</ul>02 Customization
Frosted glass
class. It keeps the tooltip's radius tier, fade and layering. The arrow is turned off, since a translucent panel reads cleaner as a plain chip. Raw colours because glass has no token equivalent.<Tooltip
label="Frosted glass tooltip"
arrow={false}
class="border border-white/20 bg-white/15 text-white shadow-[var(--blocks-shadow-lg)] backdrop-blur-xl"
>
<Button
class="border border-white/30 bg-white/10 text-white shadow-none backdrop-blur-sm hover:bg-white/20"
>
Hover for glass
</Button>
</Tooltip>This is one of five ways to restyle a block. See Customization for class, slotClasses, unstyled, preset and provider-level overrides.
03 Accessibility
Built-in ARIA
Renders with role="tooltip" and links the trigger to
it through aria-describedby. Each instance gets a
unique id automatically, so a screen reader reads the tooltip as the trigger's description.
Keyboard
Tooltips open on hover or focus and dismiss with Escape. The panel itself is never focusable. It only supplements the trigger's accessible description.
Timing
A showDelay (default 200 ms) keeps the tooltip from
flashing as the pointer passes over the trigger. A hideDelay (default 100 ms) lets the pointer cross a small
gap without dismissing it.
Reduced motion
The fade runs on the --blocks-tooltip-duration token,
an alias of --blocks-duration-fast. Under prefers-reduced-motion, that token collapses to 1 ms,
so the tooltip appears and hides without a visible fade.
Valid inside a paragraph
Trigger, panel and arrow are all <span>, so a
tooltip is valid inside a paragraph, the position it is built for. Two things stay yours:
the trigger's own content has to be phrasing-level too, and the trigger wrapper is inline-flex, so a multi-word trigger is atomic and
will not wrap across lines the way surrounding text does.
04 API Reference
19 propsProp | Type | Default | Description | |
|---|---|---|---|---|
children required | Snippet | — | The trigger element(s) that activate the tooltip. | |
label required | string | — | Text displayed inside the tooltip bubble. | |
arrow | boolean | true | Whether to show a directional arrow pointing at the trigger. | |
class | string | — | Additional CSS class for the tooltip panel.
One class to avoid: anything that sets display. The panel is a <span>
that CSS blockifies through its position: fixed, and an author-level
display also beats the UA rule [popover]:not(:popover-open) { display:
none } — the closed tooltip then keeps a laid-out box, invisible but
present in the a11y tree and to find-in-page. The same applies to
slotClasses.base, a preset, and BlocksProvider overrides. A unit
test holds this component's own variants to the rule; nothing checks
what you pass in. | |
disabled | boolean | false | Prevent the tooltip from appearing regardless of hover/focus. | |
hideDelay | number | 100 | Milliseconds before the tooltip disappears after leaving the trigger. | |
intent variant | dangerneutralprimarysecondary +2 more | neutral | Controls the color theme and semantic meaning of the Tooltip. Affects the overall appearance and user perception. Available options: danger, neutral, primary, and 3 more. | |
onOpenChange | (open: boolean) => void | — | Fires when the tooltip opens or closes from user interaction (hover
in/out, focus/blur, Escape). Receives the new open state. Not called
when the consumer writes bind:open directly. | |
open | boolean | false | Controls tooltip visibility. Supports bind:open for programmatic
display (e.g. a transient "Copied!" confirmation). Hover/focus keep
driving the state in parallel — the delays apply only to those
interaction paths, a bind:open write takes effect immediately. | |
placement | Placement | 'top' | Where the tooltip appears relative to the trigger. Auto-flips when clipped. | |
preset | string | — | Apply a named preset registered via <BlocksProvider presets={{ Tooltip: {...} }}>.
Prefer this over class overrides when the requested look falls outside the
semantic intent palette — presets keep hover/active/dark-mode logic coherent
and make the custom look reusable across the project. | |
showDelay | number | 200 | Milliseconds before the tooltip appears after hover/focus. Prevents accidental activation. | |
size variant | lgmdsm | md | Controls the dimensions, padding, and text size of the Tooltip. Affects the component's physical footprint. Available options: lg, md, sm. | |
slotClasses | Partial<Record<TooltipSlots, string>> | — | Per-slot class overrides merged with (or replacing, when unstyled) tv styles. | |
transitionDuration | number | — | Override the fade duration in milliseconds. Distinct from showDelay /
hideDelay, which time *when* the tooltip appears — this is how fast the
opacity fade itself runs. Defaults to the tooltip token
--blocks-tooltip-duration (fast, 150ms). Respects prefers-reduced-motion. | |
transitionEasing | string | — | Override the fade easing as a CSS <easing-function> (e.g. 'linear',
'ease-out', 'cubic-bezier(0.4,0,0.2,1)'). Defaults to the tooltip token
--blocks-tooltip-easing. A CSS string, not a JS easing fn, because the
tooltip fade is a pure CSS transition. | |
unstyled | boolean | — | Remove default tv classes; only consumer classes apply. | |
...HTMLAttributes<HTMLSpanElement> inherited | HTMLAttributes | — | HTML attributes (excluding: 'children') | |
...TooltipVariants variant | VariantProps | — | Styling variants from TooltipVariants |
05 Types
Local type definitions used by this component.
Name | Kind | Category | Used by | Description | |
|---|---|---|---|---|---|
TooltipProps | interface | props | 0 | — | |
TooltipVariants | type | variant | 1 | — | |
TooltipSlots | type | variant | 0 | Slot names derived from the tv() config above — single source of truth for slotClasses. | |
Placement | type | helper | 1 | — | |
Side | type | helper | 0 | — | |
Alignment | type | helper | 0 | — |
06 Installation
Import
import { Tooltip } from '@urbicon-ui/blocks';