Components/a73710cc-4867-431a-977a-38240922091f

Ripple Button

ctafrom MagicUI Effects
Sign in to Add to Project
Ripple Button

AI Usage Rules

Use RippleButton for material-design-style click feedback. Requires animate-ripple keyframe. The ripple expands from the click point. Use for interactive buttons where tactile feedback matters.

Code Template

"use client"
import React, { useState, type MouseEvent } from "react"
import { cn } from "@/lib/utils"

interface RippleButtonProps extends React.ComponentProps<"button"> {
  rippleColor?: string
  duration?: string
}

export function RippleButton({ className, children, rippleColor = "#fff", duration = "600ms", onClick, ...props }: RippleButtonProps) {
  const [ripples, setRipples] = useState<Array<{ x: number; y: number; size: number; key: number }>>([])

  const handleClick = (e: MouseEvent<HTMLButtonElement>) => {
    const rect = e.currentTarget.getBoundingClientRect()
    const size = Math.max(rect.width, rect.height)
    setRipples((prev) => [...prev, { x: e.clientX - rect.left - size / 2, y: e.clientY - rect.top - size / 2, size, key: Date.now() }])
    onClick?.(e)
  }

  return (
    <button className={cn("relative flex cursor-pointer items-center justify-center overflow-hidden rounded-lg border bg-primary px-4 py-2 text-center text-primary-foreground", className)} onClick={handleClick} {...props}>
      <span className="relative z-10">{children}</span>
      {ripples.map((ripple) => (
        <span key={ripple.key} className="absolute animate-ripple rounded-full bg-white/25"
          style={{ width: ripple.size, height: ripple.size, top: ripple.y, left: ripple.x, animationDuration: duration, backgroundColor: rippleColor }}
          onAnimationEnd={() => setRipples((prev) => prev.filter((r) => r.key !== ripple.key))} />
      ))}
    </button>
  )
}

Props Schema

PropertyTypeDefaultDescription
childrenstring
durationstring
rippleColorstring
View raw JSON schema
{
  "type": "object",
  "properties": {
    "children": {
      "type": "string"
    },
    "duration": {
      "type": "string"
    },
    "rippleColor": {
      "type": "string"
    }
  }
}