Glass Ripple
einui/glass-rippleFreeComponent
A ripple effect component that can be applied to various elements for a dynamic interaction experience.
Live preview
live · rendered by the registry
Rendered by einui on their own page — this is the component running, not a screenshot of it.Install it
npx shadcn@latest add https://ui.eindev.ir/r/glass-ripple.jsonSource
1"use client"23import * as React from "react"4import { cn } from "@/lib/utils"56interface Ripple {7 id: number8 x: number9 y: number10 size: number11}1213interface GlassRippleProps extends React.HTMLAttributes<HTMLDivElement> {14 color?: "cyan" | "purple" | "white" | "blue"15 duration?: number16 disabled?: boolean17}1819const rippleColors = {20 cyan: "bg-cyan-400/30",21 purple: "bg-purple-400/30",22 white: "bg-white/30",23 blue: "bg-blue-400/30",24}2526const GlassRipple = React.forwardRef<HTMLDivElement, GlassRippleProps>(27 ({ className, children, color = "white", duration = 600, disabled = false, ...props }, ref) => {28 const [ripples, setRipples] = React.useState<Ripple[]>([])29 const containerRef = React.useRef<HTMLDivElement>(null)3031 const createRipple = React.useCallback(32 (e: React.MouseEvent<HTMLDivElement> | React.TouchEvent<HTMLDivElement>) => {33 if (disabled || !containerRef.current) return3435 const rect = containerRef.current.getBoundingClientRect()36 let x: number, y: number3738 if ("touches" in e) {39 x = e.touches[0].clientX - rect.left40 y = e.touches[0].clientY - rect.top41 } else {42 x = e.clientX - rect.left43 y = e.clientY - rect.top44 }4546 const size = Math.max(rect.width, rect.height) * 24748 const newRipple: Ripple = {49 id: Date.now(),50 x,51 y,52 size,53 }5455 setRipples((prev) => [...prev, newRipple])5657 setTimeout(() => {58 setRipples((prev) => prev.filter((r) => r.id !== newRipple.id))59 }, duration)60 },61 [disabled, duration],62 )6364 return (65 <div ref={ref} className={cn("relative overflow-hidden cursor-pointer", className)} {...props}>66 <div ref={containerRef} className="absolute inset-0" onMouseDown={createRipple} onTouchStart={createRipple}>67 {ripples.map((ripple) => (68 <span69 key={ripple.id}70 className={cn(71 "absolute rounded-full pointer-events-none",72 "animate-[ripple_0.6s_ease-out_forwards]",73 rippleColors[color],74 )}75 style={{76 left: ripple.x - ripple.size / 2,77 top: ripple.y - ripple.size / 2,78 width: ripple.size,79 height: ripple.size,80 }}81 />82 ))}83 </div>84 <div className="relative z-10 pointer-events-none">{children}</div>85// … truncated
Files it writes
More from einui
All 44 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Base Widgetbase-widget | einui | Components | Free | 1 dep | |
| Calendar Widgetscalendar-widget | einui | Components | Free | 1 dep | |
| Clock Widgetsclock-widget | einui | Components | Free | 1 dep | |
| Glass Alert Dialogglass-alert-dialog | einui | Components | Free | 1 dep | |
| Glass Avatarglass-avatar | einui | Components | Free | 1 dep | |
| Glass Badgeglass-badge | einui | Components | Free | 1 dep | |
| Glass Breadcrumbglass-breadcrumb | einui | Components | Free | 1 dep | |
| Glass Buttonglass-button | einui | Components | Free | 2 deps |
