Tooltip
A transient text label that appears on hover or focus. Composes the `popup.tooltip` member — a new member of the `popup` family, not a variant of `popup.content`.
npx shadcn@latest add @fragiola/tooltipShow code
"use client";
import type { ReactNode } from "react";
import { Clickable } from "#/atoms/clickable";
import { Tooltip } from "#/ui/tooltip";
// The floor is palette-surface. The tooltip content travels through a portal
// but inherits the palette from the owning subtree. The provider coordinates
// the delay between the two triggers — moving from one to the next opens the
// second tooltip without waiting for the delay again.
export default function TooltipDemo() {
return (
<div className="palette-surface flex flex-col gap-6 rounded-lg border border-palette-line bg-palette-base p-6">
<Row label="provider coordinates delay">
<Tooltip.Provider>
<Tooltip.Root>
<Tooltip.Trigger
render={<Clickable.Button variant="outline" />}
>
Hover me
</Tooltip.Trigger>
<Tooltip.Content>
This is a tooltip — a transient text label.
</Tooltip.Content>
</Tooltip.Root>
{/* Moving from one trigger to the next opens the second
tooltip without waiting for the delay again. */}
<Tooltip.Root>
<Tooltip.Trigger
render={<Clickable.Button variant="outline" />}
>
Then me
</Tooltip.Trigger>
<Tooltip.Content>
The provider coordinates the delay — no wait.
</Tooltip.Content>
</Tooltip.Root>
</Tooltip.Provider>
</Row>
</div>
);
}
function Row({ label, children }: { label: string; children: ReactNode }) {
return (
<div className="flex flex-col gap-2">
<span className="text-xs font-mono text-palette-accent/85">
{label}
</span>
<div className="flex flex-wrap items-center gap-4">{children}</div>
</div>
);
}
Two members, not two variants
popup.content is the menu/popover floating box: raised surface, border, shadow, zoom animation. popup.tooltip is a transient text label: inverted palette, no border, no shadow, fade-only animation. These are genuinely different things — a menu list and a text label — so they are named members, not variants. The zero-variant rule is preserved.
Inverted palette
The tooltip uses bg-palette-accent text-palette-base — the accent role (normally the foreground) becomes the background, and the base role (normally the background) becomes the text. This is a natural inversion that follows the 6-role contract: no new role, no new palette. In a light theme the tooltip is dark with light text; in a dark theme it inverts automatically.
Provider and delay
Tooltip.Provider wraps a group of tooltips and coordinates their delay: when you move from one trigger to another, the first tooltip closes and the second opens without waiting for the delay again. This is behaviour from the primitive, not a style concern.
Parts
| Part | Source |
|---|---|
Provider / Root / Trigger | Base UI Tooltip |
Content | popup.tooltip() + Portal + Positioner |
Popover
A floating surface positioned against a trigger. Composes `popup.content` — the same floating box dropdown-menu uses — and adds Title, Description and Close through `render`.
Accordion
A group of expand/collapse items with coordination. Composes the `disclosure` family (trigger, panel, content). The only things this component declares for itself are Root, Item and Header — the coordination points.