A ring that spreads from the exact point of a press, built on Motion. It works on any positioned element, for real clicks and for a Demo Cursor's scripted ones.
When to use
- Product demos and recordings, where a click has to be seen to be followed.
- Tutorials and walkthroughs that replay a sequence of presses.
- A canvas or surface where the press point itself matters (a map, a whiteboard, a colour field).
When not to use
Installation
npx shadcn add https://eased.dev/r/click-ripple.jsonThe command adds Click Ripple, everything it builds on and Eased’s tokens to your project.
Usage
import { ClickRipple } from "@/components/eased/click-ripple/click-ripple";export function Example() { return ( <div className="relative grid h-48 place-items-center rounded-panel bg-surface-sunken"> Click anywhere <ClickRipple /> </div> );}Mount it inside the element whose presses should ring; that element needs position: relative (or any positioning). Presses on its children bubble to it.
Examples
With a demo cursor
trigger="demo" rings only at the cursor's presses, so a viewer's own clicks on the stage stay quiet.
<div ref={stage} inert className="relative"> <Button data-demo="deploy">Deploy</Button> <DemoCursor to="deploy" pressed={step === "press"} /> <ClickRipple trigger="demo" /></div>A neutral ring
The ring is currentColor; set it with a text class.
<ClickRipple className="text-text-muted" />API reference
ClickRipple
| Prop | Type | Default | Description |
|---|---|---|---|
trigger | "pointer" | "demo" | "both" | "both" | Real pointer presses on the parent, Demo Cursor presses inside it, or both. |
className | string | "text-brand-text" | Sets the ring's colour (a text class) and anything else on the layer. |
A Demo Cursor press is an eased-demo-press event (DEMO_PRESS in eased-demo-core) with { clientX, clientY }; dispatch your own to ring anywhere from a script.
Accessibility
- The layer is
aria-hiddenandpointer-events: none; it never changes what a press does or what is announced. - It draws over the parent only; nothing is focusable.
Motion
A soft disc marks the press and is gone in 300ms on the exit curve. The ring, 56px across with a surface-coloured halo under a 1.5px stroke so it reads over filled buttons, grows from 30% on the smooth spring (no overshoot) while its opacity falls on the ease-in curve over 500ms, apart from the spring, so it never rings twice. At most four rings are in flight. Under reduced motion the ring shows at full size, holds for 300ms and fades in 100ms, without growing.
Notes for AI
Use Click Ripple when a click should be visible to someone watching: a demo, a recording, a tutorial. Put it inside the stage next to a Demo Cursor with trigger="demo", or inside any relative element for real clicks.
Do not wrap individual buttons in their own ripple when one ripple on their shared container covers them, and do not add it to production controls as general press feedback. It already clips nothing, takes no input and cleans up each ring when it fades.
Related
- Demo Cursor: the scripted presses it rings at.
- Button: press feedback for everyday controls.
- Product demo set: the pieces on one timeline.