KQ-1417 · SOFT/SHAPE

Soft Shape

Flat pigment circles, rounded squares and rounded triangles drawn as signed-distance fields in one WebGL2 pass, joined by a smooth minimum whose reach grows near the pointer: as the pointer draws two shapes together (each leans in on springs.glide and drifts home on springs.drift) they flow into one mass through a neck and their colours blend across it, while their edges soften into a grained gradient near the pointer and stay crisp away from it. Pressing gathers the whole composition into one soft mass and releasing scatters it home on springs.recoil. Keyboard focus on a control inside draws the shapes to it, and Enter or Space on it pulses a gather.

KQ-1417 · SOFT/SHAPE

Fernworks · identity kit

Soft edges, firm ideas.

Shapes, colour and motion for brands that move.

resting · point at the shapes or press Tab

Install

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

$ pnpm dlx shadcn@latest add @kinetiq/soft-shape

Props

children
React.ReactNode
default —
Content laid over the shapes, such as a headline. It keeps every click, focus and key.
shapes
"mixed" | "circles" | "squares" | "triangles" | readonly SoftShapeKind[]
default "mixed"
Which primitives make up the composition: a named set, or your own list of "circle", "square" and "triangle" used in turn.
softness
number
default 28
The widest the edges soften right under the pointer, in px; away from it they stay crisp.
color
"cobalt" | "dusk" | "ember" | "moss" | readonly string[]
default "cobalt"
The pigment palette: a named set from the theme tokens, or your own CSS colours given to the shapes in turn.
count
number
default 6
How many shapes, 2 to 8.
scale
number
default 1
Shape size relative to the room each one has, 0.5 to 1.5.
roundness
number
default 0.3
Corner rounding of the squares and triangles, 0 (sharp) to 1 (pebble).
melt
number
default 44
How far apart two shapes start to flow together near the pointer, in px (the smooth minimum's reach).
radius
number
default 160
How far the pointer's pull and its soft focus reach, in px.
pull
number
default 0.5
How strongly nearby shapes lean toward the pointer, 0 to 1.
grain
number
default 0.4
A fine printed grain inside the soft edges, 0 to 1, so the blur never bands.
ambient
boolean
default true
With nobody pointing, a slow soft spot wanders the composition and the shapes bob.
gather
boolean
default true
Pressing gathers every shape into one soft mass; releasing scatters them home on springs.recoil.
interactive
boolean
default true
Follow the pointer.
followFocus
boolean
default true
Keyboard focus on a control inside draws the shapes and the soft spot to it.
paused
boolean
default false
Hold the composition still and stop the frame loop.
seed
number
default 7
Seed for the layout, the kinds, the colours and the tilts.
dpr
number
default 2
The highest device pixel ratio the canvas draws at (never above 2).
onGatherChange
(gathered: boolean) => void
default —
Fires when a press (or Enter/Space on a control inside) gathers the shapes, and again when they scatter.
className
string
default —
Classes for the box. Give it a height; children are laid out inside it.