shimmer-button.tsx
1 import { cn } from "@/lib/utils"; 2 import React, { CSSProperties } from "react"; 3 4 export interface ShimmerButtonProps 5 extends React.ButtonHTMLAttributes<HTMLButtonElement> { 6 shimmerColor?: string; 7 shimmerSize?: string; 8 borderRadius?: string; 9 shimmerDuration?: string; 10 background?: string; 11 className?: string; 12 children?: React.ReactNode; 13 } 14 15 const ShimmerButton = React.forwardRef<HTMLButtonElement, ShimmerButtonProps>( 16 ( 17 { 18 shimmerColor = "#ffffff", 19 shimmerSize = "0.05em", 20 shimmerDuration = "3s", 21 borderRadius = "100px", 22 background = "rgba(0, 0, 0, 1)", 23 className, 24 children, 25 ...props 26 }, 27 ref, 28 ) => { 29 return ( 30 <button 31 style={ 32 { 33 "--spread": "90deg", 34 "--shimmer-color": shimmerColor, 35 "--radius": borderRadius, 36 "--speed": shimmerDuration, 37 "--cut": shimmerSize, 38 "--bg": background, 39 } as CSSProperties 40 } 41 className={cn( 42 "group relative z-0 flex cursor-pointer items-center justify-center overflow-hidden whitespace-nowrap border border-white/10 px-6 py-3 text-white [background:var(--bg)] [border-radius:var(--radius)] dark:text-black", 43 "transform-gpu transition-transform duration-300 ease-in-out active:translate-y-[1px]", 44 className, 45 )} 46 ref={ref} 47 {...props} 48 > 49 {/* spark container */} 50 <div 51 className={cn( 52 "-z-30 blur-[2px]", 53 "absolute inset-0 overflow-visible [container-type:size]", 54 )} 55 > 56 {/* spark */} 57 <div className="absolute inset-0 h-[100cqh] animate-slide [aspect-ratio:1] [border-radius:0] [mask:none]"> 58 {/* spark before */} 59 <div className="animate-spin-around absolute inset-[-100%] w-auto rotate-0 [background:conic-gradient(from_calc(270deg-(var(--spread)*0.5)),transparent_0,var(--shimmer-color)_var(--spread),transparent_var(--spread))] [translate:0_0]" /> 60 </div> 61 </div> 62 {children} 63 64 {/* Highlight */} 65 <div 66 className={cn( 67 "insert-0 absolute h-full w-full", 68 69 "rounded-2xl px-4 py-1.5 text-sm font-medium shadow-[inset_0_-8px_10px_#ffffff1f]", 70 71 // transition 72 "transform-gpu transition-all duration-300 ease-in-out", 73 74 // on hover 75 "group-hover:shadow-[inset_0_-6px_10px_#ffffff3f]", 76 77 // on click 78 "group-active:shadow-[inset_0_-10px_10px_#ffffff3f]", 79 )} 80 /> 81 82 {/* backdrop */} 83 <div 84 className={cn( 85 "absolute -z-20 [background:var(--bg)] [border-radius:var(--radius)] [inset:var(--cut)]", 86 )} 87 /> 88 </button> 89 ); 90 }, 91 ); 92 93 ShimmerButton.displayName = "ShimmerButton"; 94 95 export default ShimmerButton;