KQ-1582 · MAGPIE/CURSOR

Magpie Cursor

A cursor that collects: point at anything marked data-magpie and its label lifts off the item as a small paper tag, starting at the item's own box and rising toward you, then flies to the head of a string of tags hanging off the cursor in 3D. Each tag follows the one in front on its own spring with the snap character, softer down the string by lag and further back by depth, tilting with its own speed; pointing at a label already held brings it to the front, and past maxTags the oldest lets go and falls away. A click deals the stack out where you stand in a shallow arc that lands on springs.recoil, holds for a beat so you can read it, then gathers up on springs.glide and clears; keyboard focus collects, Enter or Space drops, and Escape gathers the stack away.

KQ-1582 · MAGPIE/CURSOR

Fernworks · Nursery

Point at what you like.

stack empty · point at a plant, click to drop

Install

One command — the source lands in your repo. Or copy it from the Code tab.

$ pnpm dlx shadcn@latest add @kinetiq/magpie-cursor

Props

children
React.ReactNode
default —
The area the magpie works in. Mark anything collectable with attribute (default data-magpie).
depth
number
default 22
How far apart the tags hang in depth, px: 0 is a flat pile, 60 a long string into the page.
lag
number
default 0.5
How loosely the stack trails the cursor, 0 (tight) to 1 (loose and swinging).
maxTags
number
default 5
The most tags it carries, 1 to 8; past that the oldest lets go and falls away.
value / defaultValue
string[]
default []
The collected labels, newest first: controlled, or the labels it starts with.
onValueChange
(labels: string[]) => void
default —
Fires from the hover, focus, click or key that changed the stack, with the new labels.
attribute
string
default "data-magpie"
The attribute that marks a collectable item; its value is the label, or the item's text when empty.
offset
[number, number]
default [14, 18]
Where the stack hangs from the pointer, px.
spread
number
default 11
How far the ends of a dropped arc tip, degrees.
hold
number
default 1400
How long a dropped arc rests before it gathers up, ms.
dropOnClick
boolean
default true
A click drops the stack where you stand.
followFocus
boolean
default true
Keyboard focus on a tagged item collects it; Enter or Space there drops the stack.
interactive
boolean
default true
The pointer collects.
onPick
(label: string) => void
default —
A label was picked up, or brought back to the front.
onDrop
(labels: string[]) => void
default —
The stack was dropped, with the labels it held, newest first.
className
string
default —
Classes for the box.