Docs
AI Button
A button for creating magic with AI 🤖 🫣
requires interactionhover
Installation
Install dependencies
npm install tsparticles @tsparticles/react @tsparticles/engine
Update tailwind.config.js
Add the following to your tailwind.config.js file.
module.exports = {
theme: {
extend: {
keyframes: {
sparkle: {
"0%, 100%": { opacity: "0.75", scale: "0.9" },
"50%": { opacity: "1", scale: "1" },
},
},
animation: {
sparkle: "sparkle 2s ease-in-out infinite",
},
}
}
}
Run the following command
It will create a new file ai-button.tsx
inside the components/animata/button
directory.
mkdir -p components/animata/button && touch components/animata/button/ai-button.tsx
Paste the code
Open the newly created file and paste the following code:
import { useEffect, useMemo, useState } from "react";
import { Sparkle } from "lucide-react";
import { loadFull } from "tsparticles";
import type { ISourceOptions } from "@tsparticles/engine";
import Particles, { initParticlesEngine } from "@tsparticles/react";
const options: ISourceOptions = {
key: "star",
name: "Star",
particles: {
number: {
value: 20,
density: {
enable: false,
},
},
color: {
value: ["#7c3aed", "#bae6fd", "#a78bfa", "#93c5fd", "#0284c7", "#fafafa", "#38bdf8"],
},
shape: {
type: "star",
options: {
star: {
sides: 4,
},
},
},
opacity: {
value: 0.8,
},
size: {
value: { min: 1, max: 4 },
},
rotate: {
value: {
min: 0,
max: 360,
},
enable: true,
direction: "clockwise",
animation: {
enable: true,
speed: 10,
sync: false,
},
},
links: {
enable: false,
},
reduceDuplicates: true,
move: {
enable: true,
center: {
x: 120,
y: 45,
},
},
},
interactivity: {
events: {},
},
smooth: true,
fpsLimit: 120,
background: {
color: "transparent",
size: "cover",
},
fullScreen: {
enable: false,
},
detectRetina: true,
absorbers: [
{
enable: true,
opacity: 0,
size: {
value: 1,
density: 1,
limit: {
radius: 5,
mass: 5,
},
},
position: {
x: 110,
y: 45,
},
},
],
emitters: [
{
autoPlay: true,
fill: true,
life: {
wait: true,
},
rate: {
quantity: 5,
delay: 0.5,
},
position: {
x: 110,
y: 45,
},
},
],
};
export default function AiButton() {
const [particleState, setParticlesReady] = useState<"loaded" | "ready">();
const [isHovering, setIsHovering] = useState(false);
useEffect(() => {
initParticlesEngine(async (engine) => {
await loadFull(engine);
}).then(() => {
setParticlesReady("loaded");
});
}, []);
const modifiedOptions = useMemo(() => {
options.autoPlay = isHovering;
return options;
}, [isHovering]);
return (
<button
className="group relative my-8 rounded-full bg-gradient-to-r from-blue-300/30 via-blue-500/30 via-40% to-purple-500/30 p-1 text-white transition-transform hover:scale-110 active:scale-105"
onMouseEnter={() => setIsHovering(true)}
onMouseLeave={() => setIsHovering(false)}
>
<div className="relative flex items-center justify-center gap-2 rounded-full bg-gradient-to-r from-blue-300 via-blue-500 via-40% to-purple-500 px-4 py-2 text-white">
<Sparkle className="size-6 -translate-y-0.5 animate-sparkle fill-white" />
<Sparkle
style={{
animationDelay: "1s",
}}
className="absolute bottom-2.5 left-3.5 z-20 size-2 rotate-12 animate-sparkle fill-white"
/>
<Sparkle
style={{
animationDelay: "1.5s",
animationDuration: "2.5s",
}}
className="absolute left-5 top-2.5 size-1 -rotate-12 animate-sparkle fill-white"
/>
<Sparkle
style={{
animationDelay: "0.5s",
animationDuration: "2.5s",
}}
className="absolute left-3 top-3 size-1.5 animate-sparkle fill-white"
/>
<span className="font-semibold">Generate thumbnails</span>
</div>
{!!particleState && (
<Particles
id="whatever"
className={`pointer-events-none absolute -bottom-4 -left-4 -right-4 -top-4 z-0 opacity-0 transition-opacity ${particleState === "ready" ? "group-hover:opacity-100" : ""}`}
particlesLoaded={async () => {
setParticlesReady("ready");
}}
options={modifiedOptions}
/>
)}
</button>
);
}
Credits
Built by hari
Inspired by this