Tooltip
Contextual hints that appear on hover or focus. Supports placement, intents, sizes, and custom delays.
Playground
<Tooltip
label="Helpful hint"
placement="top"
>
<Button variant="outlined" size="sm">Hover me</Button>
</Tooltip>01 Examples
Formatting Toolbar
<Tooltip label="Bold (⌘B)">
<button class="toolbar-btn">B</button>
</Tooltip>Status Dashboard
<div
class="bg-surface-elevated border-border-subtle divide-border-subtle w-full max-w-sm divide-y rounded-xl border"
>
{#each [{ service: 'API Gateway', status: 'Operational – 99.99 % uptime', intent: 'success', dot: 'bg-success' }, { service: 'Auth Service', status: '⚠ Degraded – elevated latency', intent: 'warning', dot: 'bg-warning' }, { service: 'CDN', status: 'Operational – 34 ms avg', intent: 'success', dot: 'bg-success' }, { service: 'Database', status: '✗ Incident – failover active', intent: 'danger', dot: 'bg-danger' }] as const as row (row.service)}
<div class="flex items-center justify-between px-4 py-2.5">
<span class="text-text-primary text-sm">{row.service}</span>
<Tooltip label={row.status} intent={row.intent} placement="left">
<span class="flex h-5 w-5 items-center justify-center">
<span class="{row.dot} inline-block h-2.5 w-2.5 rounded-full"></span>
</span>
</Tooltip>
</div>
{/each}
</div>Truncated Text Reveal
- Q4-roadmap-final-with-stakeholder-feedback-v3.pdf 2.4 MB
- design-system-token-migration-notes.md 18 KB
- customer-interview-transcripts-jan-2026.zip 14.2 MB
<ul
class="bg-surface-elevated border-border-subtle divide-border-subtle w-full max-w-sm divide-y rounded-xl border"
>
{#each [{ name: 'Q4-roadmap-final-with-stakeholder-feedback-v3.pdf', size: '2.4 MB' }, { name: 'design-system-token-migration-notes.md', size: '18 KB' }, { name: 'customer-interview-transcripts-jan-2026.zip', size: '14.2 MB' }] as file (file.name)}
<li class="flex items-center justify-between gap-3 px-4 py-2.5">
<Tooltip label={file.name} placement="top-start" size="sm">
<span class="text-text-primary block max-w-[14rem] truncate text-sm">{file.name}</span
>
</Tooltip>
<span class="text-text-tertiary shrink-0 text-xs">{file.size}</span>
</li>
{/each}
</ul>02 Customization
Branded Gradient
<Tooltip
label="✨ Premium feature unlocked"
slotClasses={{
base: 'bg-linear-to-r from-violet-600 to-indigo-600 text-white shadow-lg shadow-violet-500/25 font-semibold'
}}
size="md"
>
<Button intent="primary" variant="filled">Upgrade</Button>
</Tooltip>Glass Morphism (unstyled)
<Tooltip
unstyled
label="Frosted glass tooltip"
class="rounded-xl border border-white/20 bg-white/15 px-3 py-1.5 text-sm font-medium text-white shadow-2xl backdrop-blur-xl"
slotClasses={{
arrow: 'h-2 w-2 rotate-45 border border-white/20 bg-white/15 backdrop-blur-xl'
}}
>
<Button
unstyled
class="rounded-full border border-white/30 bg-white/10 px-5 py-2.5 text-sm font-medium text-white backdrop-blur-sm transition-all hover:bg-white/20"
>
Hover for glass
</Button>
</Tooltip>Terminal / Monospace
<Tooltip
label="git commit -m 'fix: resolve race condition'"
slotClasses={{
base: 'font-mono bg-neutral-900 text-emerald-400 border border-emerald-500/30 shadow-lg shadow-emerald-500/10'
}}
size="sm"
>
<Badge variant="outlined" intent="neutral">
<span class="font-mono text-xs">$ git</span>
</Badge>
</Tooltip>A branded tooltip surface belongs in a BlocksProvider preset (presets.Tooltip): registered once, every preset instance matches — see Customization.
03 Accessibility
Built-in ARIA
Uses role="tooltip" with aria-describedby linking the trigger to the tooltip content.
A unique ID is generated automatically for each instance.
Valid inside a paragraph
Trigger, panel and arrow are all <span>, so a
tooltip is valid inside a paragraph — the position it exists for. A <div> would close the enclosing <p> as the parser
repairs the document, and the server-rendered HTML would then stop matching the client tree. Popover needs its inline prop for the same reason; Tooltip
needs no opt-in. Two things stay yours: what you put in the trigger has to be phrasing-level
too, and the trigger wrapper is inline-flex — atomic, so
a multi-word trigger will not wrap across lines the way surrounding text does.
Keyboard
Tooltips appear on Focus and dismiss with Escape. The tooltip itself is never focusable – it supplements the trigger's accessible description.
Timing
A configurable showDelay (default 200 ms) prevents
accidental activation during mouse movement. The hideDelay (default 100 ms) allows users to briefly move
away without the tooltip disappearing.
Reduced Motion
The tooltip uses opacity transitions with the
system's --blocks-duration-fast token. In reduced motion
mode, the transition duration is automatically shortened.
04 API Reference
Prop | 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';