#381
Grid ripple
A grid of dots where a click sends a wave outward: each dot swells and fades back after a delay equal to its distance from the click.
Hand this to your AI. It names the exact library parts, timings and accessibility promises of this demo.
Build the "Grid ripple" pattern (@codeatlasdev/ui demo #381, motion/hero-ambient) in my app.
Call get_demo({ ids: ["#381"] }) first and keep its structure. It needs @codeatlasdev/[email protected].
Use: Empty states, hero backdrops and interactive posters where a click or tap should feel like it disturbs a surface.
Keep these library parts, with the props and tokens the demo uses:
- MotionStage from "@codeatlasdev/ui"
Behaviour to keep:
- `MotionStage` with `loop={2200}`; each cycle starts a ripple from the next entry of `origins`
- The delay is the distance in cells times 70: `--d:{Math.round(dist * 70)}ms`, passed to `animation: rip-wave 700ms cubic-bezier(0.2, 0, 0, 1) var(--d) both`
- `rip-wave` keyframes: `transform: scale(2.6)` at the peak, then back to `scale(1)`, colored with `var(--ca-brand-fill)` at the peak
- `{#key src.n}` remounts the dots on every click so all delays restart from the new origin
- Under reduced motion `class:rip__dot--run={!m.reduced}` drops the animation and every dot stays at rest
Exact motion (do not approximate):
- transform: scale, background-color: 700ms, cubic-bezier(0.2, 0, 0, 1), stagger 70ms
Reduced motion: the demo handles it; keep that branch.
Keyboard: not an interactive control.
Change only the copy and the data. Use the theme tokens (--ca-*), never raw colours. Library parts
- MotionStage
@codeatlasdev/ui
How it is built
- `MotionStage` with `loop={2200}`; each cycle starts a ripple from the next entry of `origins`
- The delay is the distance in cells times 70: `--d:{Math.round(dist * 70)}ms`, passed to `animation: rip-wave 700ms cubic-bezier(0.2, 0, 0, 1) var(--d) both`
- `rip-wave` keyframes: `transform: scale(2.6)` at the peak, then back to `scale(1)`, colored with `var(--ca-brand-fill)` at the peak
- `{#key src.n}` remounts the dots on every click so all delays restart from the new origin
- Under reduced motion `class:rip__dot--run={!m.reduced}` drops the animation and every dot stays at rest
Related
Loading source.