Overlays & Feedback

Cursor Tooltip

An elastic tooltip that follows the cursor, tracking its coordinates with a spring and flipping sides automatically near the edges, with keyboard focus anchoring.

Bring this into your project

Run this command in your project folder. The CLI adds the source and dependencies; then follow the usage example below.

npx webberui@latest add cursor-tooltip.en

New project or installation trouble? Start here →

Playground

Tune the props live — the code snippet updates as you go, so you can dial in the look you want before copying it.

14
0
Active edited usageDefault props
<CursorTooltip/>

The complete example includes the preview layout and data. Install the component first, then paste this file into your project.

Installation

npx webberui@latest add https://webberui.com/r/cursor-tooltip.en.json

Or, once registries are configured in components.json, install it as @webberui/cursor-tooltip.

Usage

import { CursorTooltip } from "@/components/ui/cursor-tooltip";

<CursorTooltip content="Drag to reorder">
  <button>Hover me</button>
</CursorTooltip>

The tooltip is rendered into document.body through a portal and follows the cursor; content accepts any node, so you can build a rich tooltip with an icon:

<CursorTooltip
  variant="smooth"
  content={
    <span className="flex items-center gap-1.5">
      <Sparkles className="size-3.5" /> Done
    </span>
  }
>
  <StatusDot />
</CursorTooltip>

Props

PropTypeDefaultDescription
childrenReact.ReactNode—The trigger area; the tooltip shows when the cursor enters it or it receives keyboard focus
contentReact.ReactNode—Tooltip content, either text or any node
variant"spring" | "smooth" | "instant""spring"Follow feel: elastic spring back / tight tracking / zero-latency lock to the cursor
offsetnumber | { x: number; y: number }14Tooltip offset relative to the cursor (px)
openDelaynumber0Delay before showing (milliseconds)
disabledbooleanfalseDisables the tooltip: the trigger area renders as usual, but no tooltip appears
classNamestring—Appended to the tooltip bubble class
wrapperClassNamestring—Appended to the trigger wrapper class

How it works

  • Coordinates are written straight into useMotionValue, so mousemove never triggers a React re-render; useSpring makes the tooltip track the cursor with a spring, and low damping is what produces the "elastic" spring back.
  • spring has a pronounced spring back, smooth is tight and barely overshoots, and instant binds directly to the raw coordinates for a zero-latency lock.
  • On first show, the spring jumps to the cursor position rather than flying in from a corner of the screen.
  • As the tooltip approaches the right or bottom edge of the viewport it flips to the other side of the cursor automatically and is clamped inside the bounds, so it is never clipped or left covering the cursor.

Accessibility

  • The trigger area supports the keyboard through onFocus / onBlur: on focus the tooltip anchors directly above the trigger area (dropping below it when there is not enough room) instead of at the cursor position.
  • With a single child, aria-describedby is attached to the child itself so assistive technology reads the tooltip content on focus; the tooltip carries role="tooltip".
  • Pressing Esc closes the tooltip immediately.
  • When the user has "reduce motion" enabled at the system level, the spring and the scaling are disabled, degrading to a plain fade in / fade out locked to the cursor.
  • The tooltip is pointer-events-none, so it never intercepts pointer events.