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