Components

Ripple Button

ripple x click

Button with material ripple effect on click. From Animata.

buttonripplematerialanimata

Code

button-ripple.tsx
"use client";
import { useRef, useState } from "react";

export function RippleButton({ children }: { children: React.ReactNode }) {
  const [ripples, setRipples] = useState<{ x: number; y: number; id: number }[]>([]);
  const id = useRef(0);
  function click(e: React.MouseEvent) {
    const r = e.currentTarget.getBoundingClientRect();
    const newRipple = { x: e.clientX - r.left, y: e.clientY - r.top, id: ++id.current };
    setRipples(p => [...p, newRipple]);
    setTimeout(() => setRipples(p => p.filter(r => r.id !== newRipple.id)), 600);
  }
  return (
    <button onClick={click} className="relative overflow-hidden rounded-lg bg-brand px-6 py-2.5 text-sm font-medium text-brand-foreground">
      {ripples.map(r => (
        <span key={r.id} className="absolute size-20 -translate-x-1/2 -translate-y-1/2 animate-[ripple_0.6s_ease-out] rounded-full bg-white/30"
          style={{ left: r.x, top: r.y }} />
      ))}
      {children}
    </button>
  );
}
/* CSS: @keyframes ripple { 0% { transform: translate(-50%,-50%) scale(0); opacity: 0.5 } 100% { transform: translate(-50%,-50%) scale(4); opacity: 0 } } */

Use it in another build

Paste the code into a component file, keep your project tokens (background, brand, radius) and it themes itself. Or tell Claude Code: “add the Ripple Button component and wire it to my accent.”