Ripple
wise-ui/rippleFreeComponent
A ripple effect animation on click.
Live preview
live · rendered by the registry
Rendered by wise-ui on their own page — this is the component running, not a screenshot of it.Install it
npx shadcn@latest add https://wise-ui.com/r/ripple.jsonSource
1"use client"23import * as React from "react"4import { motion, AnimatePresence } from "motion/react"5import { cn } from "@/registry/wise-ui/lib/utils"67interface RippleProps {8 color?: string9 duration?: number10 ringCount?: number11 mode?: "click" | "pulse"12 children: React.ReactNode13 className?: string14}1516interface RippleEntry {17 x: number18 y: number19 id: number20}2122let nextId = 02324function Ripple({25 color = "currentColor",26 duration = 600,27 ringCount = 3,28 mode = "click",29 children,30 className,31}: RippleProps) {32 const [ripples, setRipples] = React.useState<RippleEntry[]>([])33 const containerRef = React.useRef<HTMLDivElement>(null)3435 function handleClick(e: React.MouseEvent<HTMLDivElement>) {36 if (mode !== "click") return37 const rect = containerRef.current!.getBoundingClientRect()38 const x = e.clientX - rect.left39 const y = e.clientY - rect.top40 setRipples((prev) => [...prev, { x, y, id: nextId++ }])41 }4243 function removeRipple(id: number) {44 setRipples((prev) => prev.filter((r) => r.id !== id))45 }4647 const durationS = duration / 10004849 return (50 <div51 ref={containerRef}52 className={cn("relative overflow-hidden", className)}53 onClick={handleClick}54 >55 {children}5657 {/* Click ripples */}58 <AnimatePresence>59 {ripples.map((ripple) => (60 <div61 key={ripple.id}62 className="pointer-events-none absolute inset-0"63 >64 {Array.from({ length: ringCount }, (_, i) => (65 <motion.div66 key={i}67 className="absolute rounded-full"68 style={{69 left: ripple.x,70 top: ripple.y,71 width: 20,72 height: 20,73 x: "-50%",74 y: "-50%",75 border: `1.5px solid ${color}`,76 }}77 initial={{ scale: 0, opacity: 0.6 }}78 animate={{ scale: 2.5, opacity: 0 }}79 transition={{80 duration: durationS,81 delay: i * (durationS * 0.2),82 ease: "easeOut",83 }}84 onAnimationComplete={() => {85 if (i === ringCount - 1) removeRipple(ripple.id)86 }}87 />88 ))}89 </div>90 ))}91 </AnimatePresence>9293 {/* Pulse mode */}94 {mode === "pulse" && (95// … truncated
What it pulls in
npm packages
Files it writes
More from wise-ui
All 20 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Animated Tabsanimated-tabs | wise-ui | Components | Free | 3 deps | |
| Border Beamborder-beam | wise-ui | Components | Free | 3 deps | |
| Data Tabledata-table | wise-ui | Components | Free | 3 deps | |
| Dockdock | wise-ui | Components | Free | 3 deps | |
| Dot Matrixdot-matrix | wise-ui | Components | Free | 2 deps | |
| Editable Texteditable-text | wise-ui | Components | Free | 4 deps | |
| Gradient Sidebargradient-sidebar | wise-ui | Components | Free | 3 deps | |
| Kanban Boardkanban-board | wise-ui | Components | Free | 6 deps |
