KQ-1477 · BEAD/PIT

Bead Pit

A background whose floor is a pit of glossy glass beads under simple 2D physics: a position-based solve at 120 Hz with gravity, collisions through a spatial hash, bouncing floor and walls and static friction, drawn as shaded spheres with soft contact shadows, sized so the beads fill the same depth at any width. The pointer is a round paddle that pushes beads aside and lends them its speed, and a click pops the beads on top of the pile into the air with a soft blup chord when sound is on; the loop sleeps once every bead is still. Keyboard focus on a control inside pops the beads behind it.

KQ-1477 · BEAD/PIT

Fieldline Beads

Every colour, by the handful

Sorted by hand, sent in cotton bags

160 beads · settled

Install

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

$ pnpm dlx shadcn@latest add @kinetiq/bead-pit

Props

children
React.ReactNode
default —
The content on top of the pit: a hero line, a heading, a call to action.
count
number
default 160
How many beads lie in the pit, 20 to 400; more beads are smaller, so the pit fills the same depth.
gravity
number
default 1
How hard the beads fall, 0 (they drift) to 2 (heavy).
palette
"candy" | "accent" | "pearl" | "ember" | readonly string[]
default "candy"
The beads' glass: a named set of pigments, or CSS colours of your own.
fill
number
default 0.42
How deep the pit is filled, as a share of the height, 0.1 to 0.8.
bounce
number
default 0.3
How lively a bead bounces off the floor, the walls and the others, 0 (dead) to 0.8.
gloss
number
default 0.7
How glossy the glass is: the size and strength of each highlight, 0 (matte) to 1.
stir
number
default 0.6
How much of the hand's speed a stirred bead takes, 0 (it is only pushed aside) to 1.
radius
number
default 40
The hand's reach in the pit, px.
pop
number
default 8
How many beads a click pops into the air, 1 to 24.
popHeight
number
default 0.6
How high a popped bead flies, as a share of the height, 0 to 1.
interactive
boolean
default true
The pointer stirs the pit and a click pops beads; keyboard focus inside pops them too.
paused
boolean
default false
Freeze the beads where they are.
seed
number
default 1
Seeds the beads' colours, sizes and places.
dpr
number
default 2
Cap on the canvas's device pixel ratio, at most 2.
sound
boolean
default false
Pops answer with a soft blup and each popped bead lands with a quieter one. Off unless asked for.
onActiveChange
(active: boolean) => void
default —
Fires when the pointer starts (true) or stops (false) stirring the pit.
onPop
(count: number) => void
default —
Fires on every pop, with how many beads went up.
onSettle
() => void
default —
Fires when every bead has come to rest.
className
string
default "h-full w-full"
Sizes and shapes the box.