A dynamic interactive button with a smooth spotlight effect that follows your cursor movement. Perfect for creating engaging call-to-action buttons with visual feedback. ✨
npm i clsx tailwind-merge//lib/utils.ts
import { clsx, type ClassValue } from "clsx";
import { twMerge } from "tailwind-merge";
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}
### Code
_ZapButton.tsx_
```tsx
"use client";
import { cn } from "@/lib/utils";
import { useEffect, useRef } from "react";
export default function ZapButton() {
return (
<div className="flex h-screen w-full items-center justify-center bg-zinc-950 px-4">
<Zap></Zap>
</div>
);
}
interface btnProps{
className?:string;
btnText?:string;
onClick?: () => void
}
const Zap = ({className,btnText="Hover",onClick}:btnProps) =>{
const btnRef = useRef<HTMLButtonElement | null>(null);
const spanRef = useRef<HTMLSpanElement>({} as HTMLSpanElement);
useEffect( () => {
const handleMouseMove = (e:any) => {
const {width} = e.target.getBoundingClientRect();
const offset = e.offsetX;
const left = `${(offset / width) * 100}%`;
spanRef.current.animate({left}, {duration: 250, fill: "forwards"});
};
const handleMouseLeave = (e:any) => {
spanRef.current.animate({left:"50%"}, {duration: 100, fill: "forwards"});
};
btnRef.current?.addEventListener("mousemove", handleMouseMove);
btnRef.current?.addEventListener("mouseleave", handleMouseLeave);
return () => {
btnRef.current?.removeEventListener("mousemove", handleMouseMove);
btnRef.current?.removeEventListener("mouseleave", handleMouseLeave);
};
}, []);
return (
<button onClick={onClick} ref={btnRef} className={cn("w-full max-w-3xs rounded-lg bg-slate-950 px-4 py-3 text-lg font-medium text-white relative overflow-hidden border-1 border-dashed border-slate-400/90", className)}>
<span className="pointer-events-none relative z-10 mix-blend-difference">{btnText}</span>
<span ref={spanRef} className="pointer-events-none absolute left-[50%] top-[50%] h-20 w-30 -translate-x-[50%] -translate-y-[50%] rounded-full bg-slate-200 border-1 border-dashed border-slate-900"></span>
</button>
)
}
| Prop | Type | Default | Description |
|---|---|---|---|
| className | string | undefined | Additional CSS classes for styling customization |
| btnText | string | "Hover" | Text content displayed on the button |
| onClick | function | undefined | Click handler function for button interactions |