KQ-1370 · PIGMENT/FLOW

Pigment Flow

Gradient text that behaves like pigment let into water: soft clouds of each colour wander seeded paths through the letters over a thinner wash of them all, every gradient mixed in oklab, all of it pure CSS on clipped text with motion values driving the stops. On arrival a drop blooms from the middle of the plain ink on a critically damped spring sized by duration (springs.drift at the default), and the pointer stirs a swirl of the pigments around a centre that trails it on springs.glide — circling winds it up, and it unwinds and fades as the water stills while the clouds it pushed drift home. Keyboard focus on, inside or around the element stirs the middle once, and with focusable the Left and Right keys stir the ink round either way.

KQ-1370 · PIGMENT/FLOW

Fernworks Inks · studio set 04

Pigment you can stirLeft and Right stir the ink.

Twelve water inks, ground by hand.

drifting · 4 pigments · move across to stir

Install

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

$ pnpm dlx shadcn@latest add @kinetiq/pigment-flow

Props

text
string
default —
The words the pigments drift through. Real text: it wraps, selects and copies.
as
"p" | "h1" | "h2" | "h3" | "span" | "div"
default "p"
The element the text lives in.
colors
"ink" | "tide" | "ember" | "moss" | string[]
default "ink"
The pigments: a named palette of tokens, or 2 to 6 CSS colours of your own.
speed
number
default 1
How fast the pigments drift, 0 (still) to 3.
stir
number
default 0.6
How strongly the pointer stirs the flow, 0 (not at all) to 1.
radius
number
default 2.2
Reach of the stir's swirl, em.
diffusion
number
default 0.5
How soft and wide each pigment cloud spreads, 0 (tight) to 1 (diffuse).
angle
number
default 100
Direction of the underlying wash, degrees.
seed
number
default 3
Seed for the clouds' paths, so two lines never drift in step.
trigger
"mount" | "inView" | "hover" | "manual"
default "inView"
When the drop of pigment blooms into the ink.
active
boolean
default true
With trigger="manual", the pigment blooms when this turns true.
once
boolean
default true
Bloom once, or again whenever the trigger fires anew.
delay
number
default 0
Wait before the bloom, ms.
duration
number
default 900
How long the bloom takes to spread, ms.
onComplete
() => void
default —
The bloom has spread and settled.
onStirChange
(stirring: boolean) => void
default —
Fires when the pointer starts stirring (true) and when the water stills (false).
paused
boolean
default false
Hold the drift. Stirring still works.
interactive
boolean
default true
The pointer, touch and focus stir the flow.
focusable
boolean
default false
Put the words in the tab order: focused, Left and Right stir the ink.
className
string
default —
Classes for the element; set the type here (size, weight, leading).