Skip to the object
Tactile UI

Cursor Puck

A weighted puck on a short spring, under the pointer. It never sits where the pointer is: it lags behind, then catches up, with a coiled spring, not a dotted line, showing the stretch and compression.

What it is for

Give a hero, a cursor trail or a playful corner of a page a pointer that behaves like it has real weight on the end of a leash: a disc on a 2D mass-spring-damper, tied to wherever the pointer is, that lags when the pointer moves fast and settles once it stops.

Installnpx shadcn add https://tactileui.dev/r/cursor-puck.jsonWith a Pass: how

Controls

The diameter of the weighted disc.

How quickly the spring pulls the puck toward the pointer. Low is a slow, heavy puck; high is quick and light.

Below 1 the puck overshoots and swings before it settles; 1 catches up with no overshoot; above 1 is slow and heavy.

A coiled spring drawn between the pointer's own mark and the puck, so its stretch and compression are visible, not a dotted line.

Read by a screen reader before the keyboard instructions. Empty uses the default.

Everything you set here is what the Code and Prompt tabs give you.

Datasheet

Mechanism
Mass spring damper, Fixed substep integration, Pointer or keyboard target, Rest position recentre, Sleeping loop, Reduced motion snap
Stack
Vanilla ES modules, CSS, SVG
Needs
Nothing, no dependencies
States
6 documented
Version
0.1.0
Licence
With a Pass

States

  1. At restThe puck sits still at the centre of its stage; the loop is asleep and costs nothing.
  2. Following the pointerThe pointer's own mark jumps to the cursor at once; the puck is pulled toward it by the spring and lags behind, closing the gap as the pointer slows or stops. How quickly it catches up and whether it overshoots on the way are both controls.
  3. Pointer leavesThe free end returns to the stage's centre; the puck catches up there over the same spring, and the loop sleeps once it is still.
  4. KeyboardThe stage takes focus. Arrow keys move the free end 14px at a time (Shift for 48px steps), clamped to the stage, so the lag and the catch-up are reachable without a pointer.
  5. Off screen or hidden tabThe loop stops requesting frames; a returning tab cannot fling the spring with a long frame, because the frame gap is clamped before it is sub-stepped.
  6. Reduced motionThe puck sits on the free end at every change; nothing is stepped and no frame is requested.

Notes

A coiled spring between the pointer's own mark and the puck makes the stretch and compression visible rather than implied, and the puck itself is turned, with lathe rings, a knurled rim and a cast shadow, so it reads as a real weight, not a flat disc. The same free end is reachable from the keyboard, so the lag is never pointer-only.

Original. A fixed 1/120 s sub-stepped 2D mass-spring-damper; no canvas or WebGL, the puck and its coiled spring are plain DOM (an SVG path) moved with transform. No colour of its own: the stage is the page's own panel tokens (--tui-face), the puck's turned face, lathe rings and knurled rim are the page's own object tokens (--tui-obj-body, --tui-obj-lite, --tui-obj-dark, --tui-obj-spec, --tui-obj-edge, --tui-obj-frame), the pointer's own mark is --tui-ink-3 and the coil and the cast shadow are --tui-sh, so all four finishes are correct for free.

Anatomy

Mass spring damper, Fixed substep integration, Pointer or keyboard target, Rest position recentre, Sleeping loop, Reduced motion snap

Usage notes

Give a hero, a cursor trail or a playful corner of a page a pointer that behaves like it has real weight on the end of a leash: a disc on a 2D mass-spring-damper, tied to wherever the pointer is, that lags when the pointer moves fast and settles once it stops. A coiled spring between the pointer's own mark and the puck makes the stretch and compression visible rather than implied, and the puck itself is turned, with lathe rings, a knurled rim and a cast shadow, so it reads as a real weight, not a flat disc. The same free end is reachable from the keyboard, so the lag is never pointer-only.

Options

OptionTypeDescription
sizenumberThe diameter of the weighted disc.
stiffnessnumberHow quickly the spring pulls the puck toward the pointer. Low is a slow, heavy puck; high is quick and light.
dampingnumberBelow 1 the puck overshoots and swings before it settles; 1 catches up with no overshoot; above 1 is slow and heavy.
tetherbooleanA coiled spring drawn between the pointer's own mark and the puck, so its stretch and compression are visible, not a dotted line.
labeltextRead by a screen reader before the keyboard instructions. Empty uses the default.

Methods

  • update
  • state
  • stats
  • destroy

How it works

Original. No colour of its own.