Tooltip
A small popup that describes the element it is attached to, shown on hover or focus.
Show codeHide code
Installation
import { Tooltip } from "@makeplane/propel/components/tooltip";Usage
import { Button } from "@makeplane/propel/components/button";
import { Tooltip } from "@makeplane/propel/components/tooltip";
export default function BasicDemo() {
return (
<Tooltip label="Create a new project">
<Button label="New project" variant="secondary" size="sm" stretch="auto" />
</Tooltip>
);
}Examples
Placement
The side prop chooses which edge the popup attaches to. It may flip automatically to stay in view.
Show codeHide code
With arrow
The default tooltip is a flat surface (no caret). Pass showArrow when you need a caret pointing back at the trigger.
Show codeHide code
With shortcut
Show codeHide code
Stacked layout
The default layout="single" is a compact chip that wraps long labels within 500px and the available viewport width. Use layout="stacked" for short descriptions (Figma multiline); its shortcut sits under the label. Prefer a popover if the copy runs longer than about two lines.
Show codeHide code
Grouped
Wrapping triggers in a TooltipProvider shares open/close timing, so moving between adjacent triggers shows the next tooltip immediately instead of restarting the hover delay.
Show codeHide code
Controlled
Own open state in React with open / onOpenChange. The secondary action calls setOpen(true); Escape and blur still flow through onOpenChange, so the tooltip cannot stick open. The live “React state” label shows that ownership.
Show codeHide code
Conditional tooltip
disabled unmounts the tooltip for a boolean condition (disabled={!isCollapsed} — no tip once the sidebar expands). label unmounts on its own when copy may be missing (label={email}, no ?? "" needed) — an empty or whitespace-only string leaves the trigger with no tooltip instead of an empty popup.
Show codeHide code
Imperative handle
Use when you do not want to lift useState. createTooltipHandle() lives outside the tree; pass it as handle, put a stable id on the trigger child, then call handle.open(id) (here, “Open tip via handle.open”). No React open state — the handle talks to Base UI directly. Calling open while the tooltip is gated off by disabled or a missing label is a no-op. Multiple detached triggers still need Base UI Tooltip.Trigger composition; the ready-made only mounts one trigger from children.
Show codeHide code
API Reference
createTooltipHandle() (from the same entry) returns a handle for imperative open(triggerId) /
close() — see Imperative handle. It is a factory, not a component, so it has
no props table. TooltipPopup and TooltipArrow are the styled parts for hand-assembled tooltips
(graft Base UI behavior onto them via render).
Tooltip
A small popup that describes the element it is attached to. Appears on hover or keyboard focus of
the trigger and is dismissed on blur, pointer-leave, or Esc.
Built on Base UI's tooltip, so it's accessible by default: the popup is exposed as
role="tooltip" and wired to the trigger. Pass the trigger as children, the popup copy as
label, and an optional shortcut for a dimmed visual keyboard hint.
Grafts Base UI's tooltip behavior onto propel's styled parts: Tooltip.Root + Tooltip.Trigger
+ Tooltip.Portal → Tooltip.Positioner (shared internal/positioner) → TooltipPopup, with
an optional TooltipArrow when showArrow is set. Colors come from propel's adaptive surface
tokens (bg-layer-2 / text-primary / border-subtle-1), so the tooltip is light on light
themes and dark on dark themes, matching the Figma "Tooltip" component.
TooltipProvider
Shares one open/close delay across every tooltip beneath it, so moving between nearby triggers can show adjacent tooltips immediately.
TooltipPopup
The styled tooltip surface — adaptive popup with caption/body text, radius, shadow, and the gap
to the shortcut. layout switches Figma singleline vs multiline chrome. Base-UI-agnostic; graft
in components via <BaseTooltip.Popup render={<TooltipPopup/>} />.
TooltipArrow
The styled tooltip caret — a rotated square clipped per data-side so it points back at the
trigger. Base-UI-agnostic; graft in components via <BaseTooltip.Arrow render={<TooltipArrow/>}
/>.