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