Ripple Button
ctafrom MagicUI Effects
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
| Property | Type | Default | Description |
|---|---|---|---|
| children | string | — | |
| duration | string | — | |
| rippleColor | string | — |
View raw JSON schema
{
"type": "object",
"properties": {
"children": {
"type": "string"
},
"duration": {
"type": "string"
},
"rippleColor": {
"type": "string"
}
}
}