KQ-1460 · GRAIN/MESH

Grain Mesh

A background printed rather than rendered, drawn in one WebGL2 pass with the content on top: a mesh gradient of four to six spot inks laid down drum by drum like a risograph, through a stochastic screen fixed to the paper so ink lands as grain where it is thin and solid where it is thick, each drum a little out of register on a stock with fibres and tooth. The points drift on slow orbits while the grain stays put; the nearest ink leans toward a hovering hand on springs.glide, a drag picks it up on springs.flick and follows the finger 1:1 with its drum slipping out of register, and a release throws it home with the release velocity, landing on springs.recoil. It is decoration and never takes focus; keyboard focus landing on a control inside draws the nearest ink to it, and blur lets it land home.

KQ-1460 · GRAIN/MESH

Basinworks Press

Prints in small, uneven runs

Two drums, six inks, one paper stock

poster · grain 0.55 · drifting

Install

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

$ pnpm dlx shadcn@latest add @kinetiq/grain-mesh

Props

children
React.ReactNode
default —
The content on top of the print: a hero line, a heading, a call to action.
points
number
default 5
How many colour points (inks) make the mesh, 4 to 6.
grain
number
default 0.55
How the ink is printed, 0 (a smooth gradient) to 1 (a fully grained riso screen).
palette
"poster" | "harbor" | "orchard" | "dusk" | readonly string[]
default "poster"
A named set of inks, or four to six CSS colours of your own.
drift
number
default 0.6
How fast the points drift on their orbits, 0 (still) to 2.
softness
number
default 0.45
How far each ink spreads into its neighbours, 0 (tight pools) to 1 (wide washes).
grainSize
number
default 1.5
The size of a grain, CSS px, 1 to 4.
misregister
number
default 1.2
How far the inks sit out of register, px, 0 to 4.
paper
number
default 0.5
The paper's fibres and tooth, 0 (smooth stock) to 1.
interactive
boolean
default true
The pointer leans the nearest ink toward it, a drag pulls it, and keyboard focus draws it in.
pointerStrength
number
default 0.5
How far the nearest ink leans toward a hovering hand, 0 to 1.
paused
boolean
default false
Hold the points still; the hand still pulls them.
seed
number
default 1
Seeds the points' homes, orbits, grain and register, so two prints never match.
dpr
number
default 2
Cap on the canvas's device pixel ratio, at most 2.
onActiveChange
(active: boolean) => void
default —
Fires when the pointer or keyboard focus starts (true) or stops (false) working the print.
onGrab
(index: number | null) => void
default —
Fires when a drag picks up an ink (its index) and when it lets go (null).
className
string
default "h-full w-full"
Sizes and shapes the box.