Goal: Create a "Ripple" radio group animation.
Visual behavior: A radio group with 3 options. Each option has a 22×22px radio indicator. On selection, 3 concentric rings expand outward from the dot (CSS: scale 1→2.8, opacity 0.6→0) with staggered animation-delay (0ms, 130ms, 260ms), each ring animating over 900ms. The core dot shows an indigo glow ring. An inner 8px dot springs in on select. The effect simulates a water drop ripple. Ripple rings are restarted on each selection change via a rippleKey counter that forces remount.
Technique: React useState tracks selected option and rippleKey counter. The ripple rings are absolutely positioned spans inside a relative wrapper. They use a CSS @keyframes (ripple-out) for the scale+fade animation. The key prop forces React to remount them on each selection. Inline styles drive the ring animation-delay and core dot transitions. No library dependencies.
Accessibility: Hidden native <input type="radio"> per option, shared name attribute. Keyboard-navigable. Ripple animation skipped under prefers-reduced-motion via CSS.
My stack: {{USER_STACK}}
My styling: {{USER_STYLING}}
My constraints: {{USER_CONSTRAINTS}}
Return a single self-contained component. Do not introduce dependencies beyond what I've listed.
Paste into Claude, ChatGPT, or Cursor. Edit YOUR_STACK /
YOUR_STYLING / YOUR_CONSTRAINTS before sending.