Interactions
Ripple Grid
A lattice of nodes lit by propagating wavefronts. Fires automatically every 2.5 s. Click anywhere on the grid to spawn your own.
Installation
Coming soon. Components will be available via the registry once checkout goes live.
Usage
<RippleGrid
columns={8}
rows={5}
nodeSize={1.2}
autoInterval={2200}
onRipple={({ source }) => {
if (source === "user") {
navigator.vibrate?.(8);
analytics.track("ripple_grid_tap");
}
}}
/>Props
| Prop | Type | Default | Description |
|---|---|---|---|
| columns | number | 6 | Number of columns in the grid. |
| rows | number | 4 | Number of rows in the grid. |
| nodeSize | number | 1 | Multiplier for the node (circle) radius. `0.5` halves them, `2` doubles them. |
| autoPlay | boolean | true | Auto-fire ripples on an interval. Drives the initial play / pause state. |
| autoInterval | number | 2600 | Interval between auto-fired ripples, in ms. |
| rippleDuration | number | 2400 | Lifetime of a single ripple, in ms. Higher = slower wave. |
| tapToRipple | boolean | true | Allow click / tap on the grid to spawn a ripple. |
| showControls | boolean | true | Show the play / pause control in the corner. |
| hint | string | null | — | Override the small hint label below the grid. Pass `null` to hide. |
| onRipple | (o: { x: number; y: number; source: "auto" | "user" }) => void | — | Fired whenever a ripple is spawned. Use to trigger sound, haptics, or analytics. |
| className | string | — | Classes merged onto the root wrapper. |
Use cases
Empty-state canvas
Reward exploration on otherwise-quiet states (no notifications, search empty, etc.).
Sign-in / hero background
Subtle ambient motion behind a centered card without competing for attention.
404 / not-found page
Make a dead end feel intentional and clickable.
Status / health page
Quiet ambient grid behind uptime tiles that doesn't pull focus from the data.