KQ-1427 · SHAPE/SWELL
Shape Swell
A grid of small circles, rounded squares, plus signs and triangles as a background, each a signed distance field in one WebGL2 pass so every edge stays crisp, with the content on top: a diagonal swell rolls through, and a shape rising toward the crest grows, turns and fills with colour while one sinking into the trough shrinks, turns home and fades to a fine outline. The pointer raises a crest of its own, placed on springs.glide and lifted on springs.drift, and a press sends a ring crest across the grid that pops every shape it passes. It never takes focus; keyboard focus on a control inside raises the crest there and sends a softer ring.
Gaugeworks Studio
A grammar of simple forms
Four shapes, one rhythm, every product
at rest · mixed shapes, 28 px apart
Install
One command — the source lands in your repo. Or copy it from the Code tab.
$ pnpm dlx shadcn@latest add @kinetiq/shape-swell
Props
- children
- React.ReactNode
- default —
- The content on top of the field: a hero line, a heading, a call to action.
- spacing
- number
- default 28
- Distance between shape centres, in px (12 to 80).
- speed
- number
- default 1
- How fast the swell rolls, 0 (held) to 3.
- shapes
- "mixed" | "round" | "plus" | "angular"
- default "mixed"
- Which shapes fill the grid: all four, circles, plus signs, or squares and triangles.
- size
- number
- default 0.5
- A shape's size at the crest, as a share of the spacing (0.2 to 0.8).
- colors
- readonly string[]
- default ["var(--accent-bright)", "color-mix(in oklch, var(--accent-bright) 40%, var(--signal))"]
- Crest fill colours, laid across the field along the swell, as CSS colours (1 to 3).
- outline
- string
- default "var(--ink-3)"
- The trough outlines' colour, any CSS colour.
- stroke
- number
- default 1.25
- Outline width, in px.
- turn
- number
- default 90
- Degrees a shape turns as the crest lifts it (0 to 180): squares become diamonds, plus signs crosses.
- wavelength
- number
- default 320
- Distance between crests, in px.
- angle
- number
- default 35
- The heading the swell rolls along, in degrees; 0 runs left to right.
- interactive
- boolean
- default true
- The pointer and keyboard focus raise a crest of their own.
- pointerStrength
- number
- default 0.6
- How strongly the pointer lifts the shapes near it, 0 to 1.
- pulse
- boolean
- default true
- A press on the field (not on a control) sends a ring crest out from it.
- intro
- boolean
- default true
- The swell rises out of quiet outlines the first time the field comes into view.
- paused
- boolean
- default false
- Hold the swell still; the pointer can still lift shapes.
- seed
- number
- default 1
- Seeds which shape sits where and how each lags the swell.
- 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) raising its crest.
- className
- string
- default —
- Sizes and shapes the box; it fills its parent by default (h-full w-full).
| Prop | Type | Default | Description |
|---|---|---|---|
| children | React.ReactNode | — | The content on top of the field: a hero line, a heading, a call to action. |
| spacing | number | 28 | Distance between shape centres, in px (12 to 80). |
| speed | number | 1 | How fast the swell rolls, 0 (held) to 3. |
| shapes | "mixed" | "round" | "plus" | "angular" | "mixed" | Which shapes fill the grid: all four, circles, plus signs, or squares and triangles. |
| size | number | 0.5 | A shape's size at the crest, as a share of the spacing (0.2 to 0.8). |
| colors | readonly string[] | ["var(--accent-bright)", "color-mix(in oklch, var(--accent-bright) 40%, var(--signal))"] | Crest fill colours, laid across the field along the swell, as CSS colours (1 to 3). |
| outline | string | "var(--ink-3)" | The trough outlines' colour, any CSS colour. |
| stroke | number | 1.25 | Outline width, in px. |
| turn | number | 90 | Degrees a shape turns as the crest lifts it (0 to 180): squares become diamonds, plus signs crosses. |
| wavelength | number | 320 | Distance between crests, in px. |
| angle | number | 35 | The heading the swell rolls along, in degrees; 0 runs left to right. |
| interactive | boolean | true | The pointer and keyboard focus raise a crest of their own. |
| pointerStrength | number | 0.6 | How strongly the pointer lifts the shapes near it, 0 to 1. |
| pulse | boolean | true | A press on the field (not on a control) sends a ring crest out from it. |
| intro | boolean | true | The swell rises out of quiet outlines the first time the field comes into view. |
| paused | boolean | false | Hold the swell still; the pointer can still lift shapes. |
| seed | number | 1 | Seeds which shape sits where and how each lags the swell. |
| 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) raising its crest. |
| className | string | — | Sizes and shapes the box; it fills its parent by default (h-full w-full). |