KQ-1606 · CAPILLARY/CURSOR

Capillary Cursor

Inside its own box the pointer is a single drop of ink, exactly at the pointer and drawn out a little along fast travel. Touch a button, link or field and the ink wicks along the control's real outline — its border box and its own four corner radii — from the point of contact in both directions, the fronts slowing as capillary flow does, then seeps inward from the wet edge at low strength until the control is filled in its exact shape, while the drop shrinks by the ink it gave; the drop's size eases on a rate as quick as springs.flick and the flood on a glide-like ease. Leave and the flood recedes and the outline drains back toward the exit point through a thread of ink that thins as it pulls and pinches off past its reach, and the drop swells again. Keyboard focus moves the ink from one control to the next, and the system cursor returns over text fields and on any key.

KQ-1606 · CAPILLARY/CURSOR

Fieldline beta

Read the field notes

Trail maps that sync before you lose signal. Forty places left this month.

ink · in the drop · touch a control

Install

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

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

Props

children
ReactNode
default —
The area the drop lives in; its buttons, links and fields keep every click, focus and key.
inkColor
"cobalt" | "iron" | "sepia" | "carmine" | string
default "cobalt"
The ink: a named ink or any CSS colour.
wickSpeed
number
default 520
How fast the ink runs along an outline, px per second.
dotSize
number
default 14
The drop's diameter when it is full, px.
strength
number
default 0.16
How strongly the ink floods the inside of a control, 0 to 1.
lineWidth
number
default 1.75
The wicked outline's thickness, px.
flood
boolean
default true
Fill the inside of a control, not only its outline.
stretch
number
default 0.5
How far the drop draws out when it moves fast, 0 to 1.
cling
number
default 0.5
How far the draining thread stretches before it lets go, 0 to 1.
targets
string
default "button, a[href], [role='button'], input, select, textarea, [data-ink]"
What the ink fills, as a CSS selector.
hideCursor
boolean
default true
The drop replaces the system cursor inside the box (never over text fields, never after a key).
followFocus
boolean
default true
Keyboard focus moves the ink to the focused control.
interactive
boolean
default true
The pointer leads the drop (mouse and pen; a tap inks the tapped control).
onTargetChange
(target: HTMLElement | null) => void
default —
The control holding the ink changed: that control, or null.
className
string
default —
Classes for the box.