Rich Tooltip
InteractiveA Vercel-style rich tooltip that springs open from its trigger with a scale + fade and a real arrow, holding arbitrary ReactNode content rather than a bare string. Placement is computed by hand (no positioning lib) — measuring trigger and tooltip to auto-flip top⇄bottom / left⇄right on viewport overflow and clamp the cross axis — and it renders through a portal to document.body so ancestor overflow never clips it. Hover and focus open it with small delays, moving into the tooltip keeps it open, and Escape closes; under prefers-reduced-motion the show/hide is instant with no scale.
Inspired by Skiper UI — Vercel-style tooltip (pattern) — independently built, not affiliated. Attribution policy
Installation
npx shadcn@latest add https://parable-three.vercel.app/r/rich-tooltip.jsonRuns the shadcn CLI — the component source is copied intocomponents/parable/rich-tooltip.tsx. You own it from there.
Usage
The exact code rendering the preview above.
<div className="flex min-h-[280px] w-full items-center justify-center">
<RichTooltip
side="top"
content={
<div className="flex gap-3">
<div className="mt-0.5 grid size-9 shrink-0 place-items-center rounded-lg bg-gradient-to-br from-violet-500 to-fuchsia-500 text-white">
<Sparkles className="size-4" />
</div>
<div>
<div className="font-semibold text-white">Deploy preview</div>
<p className="mt-0.5 text-white/60">
Every push ships an isolated URL with logs, metrics, and instant rollback.
</p>
<div className="mt-2 flex items-center gap-1.5 text-[11px] text-white/45">
<kbd className="rounded border border-white/15 bg-white/5 px-1.5 py-0.5">⌘</kbd>
<kbd className="rounded border border-white/15 bg-white/5 px-1.5 py-0.5">K</kbd>
<span>to open</span>
</div>
</div>
</div>
}
>
<button className="inline-flex items-center gap-2 rounded-full border border-white/15 bg-white/5 px-4 py-2 text-sm font-medium text-white outline-none transition-colors hover:bg-white/10 focus-visible:ring-2 focus-visible:ring-violet-400">
<GitBranch className="size-4 text-violet-300" />
Hover or focus me
</button>
</RichTooltip>
</div>Props
RichTooltipProps
| Prop | Type | Default | Description |
|---|---|---|---|
| content* | React.ReactNode | — | Rich tooltip body — any node, not just a string. |
| children* | React.ReactElement | — | The single element that opens the tooltip on hover / focus. |
| side | Side | "top" | Preferred side; auto-flips to the opposite side on overflow. |
| delay | number | 150 | Open delay in ms after hover / focus begins. |
| closeDelay | number | 120 | Close delay in ms — the grace window to cross into the tooltip. |
| offset | number | 8 | Distance in px between the trigger and the tooltip box. |
| maxWidth | number | 264 | Max tooltip width in px. |
| background | string | "#0f0f10" | Surface colour. Mirrors the site `--pb-ink` token. |
| accent | string | "#8b5cf6" | Accent for the hairline edge glow. Mirrors the site `--pb-violet` token. |
| className | string | — | Extra classes on the tooltip surface. |
npm dependencies
- motion