Sparkles

Sparkles effect on the button when it's been clicked.

Installation

Run the following command

It will create a new file sparkles.tsx inside the components/buttons/sparkles.tsx directory.

mkdir -p components/buttons && touch components/buttons/sparkles.tsx

Paste the code

Open the newly created file and paste the following code:

"use client";
 
import { animate, stagger, useAnimate } from "framer-motion";
import { Star } from "lucide-react";
import { useEffect, useState } from "react";
 
type AnimationSequence = Parameters<typeof animate>[0];
 
const Sparkles = ({ text = "Click me" }: { text: string }) => {
  const [starCount, setStarCount] = useState(0);
  useEffect(() => {
    setTimeout(() => {
      setStarCount(randomNumberGenerator(2, 50));
    }, 1000);
  }, [starCount]);
 
  const randomNumberGenerator = (min: number, max: number) => {
    return Math.random() * (max - min) + min;
  };
  const [scope, animate] = useAnimate();
  const letters = text.split("");
 
  const handleBtnClick = () => {
    const sparkles = Array.from({ length: starCount });
 
    const sparkleAnimation: AnimationSequence = sparkles.map((_, index) => [
      `.stars-${index}`,
      {
        x: randomNumberGenerator(-100, 100),
        y: randomNumberGenerator(-100, 100),
        scale: randomNumberGenerator(1, 0.5),
        opacity: 1,
      },
      {
        duration: 0.4,
        at: "<",
      },
    ]);
    const sparklesFadeOut: AnimationSequence = sparkles.map((_, index) => [
      `.stars-${index}`,
      {
        opacity: 0,
        scale: 0,
      },
      {
        duration: 0.3,
        at: "<",
      },
    ]);
    const sparkleReset: AnimationSequence = sparkles.map((_, index) => [
      `.stars-${index}`,
      {
        x: 0,
        y: 0,
      },
      {
        duration: 0.00000000001,
        at: "<",
      },
    ]);
 
    animate([
      ...sparkleReset,
      [".letter", { y: -32 }, { duration: 0.2, delay: stagger(0.05) }],
      ["button", { scale: 0.8 }, { duration: 0.1, at: "<" }],
      ["button", { scale: 1 }, { duration: 0.1 }],
      ...sparkleAnimation,
      [".letter", { y: 0 }, { duration: 0.00000000001 }],
      ...sparklesFadeOut,
    ]);
  };
  return (
    <div className="h-full center">
      <div ref={scope}>
        <button
          onClick={handleBtnClick}
          className="border-2 text-2xl px-10 py-1.5 rounded-full transition-colors duration-150 border-border  relative"
        >
          <span className="sr-only">{text}</span>
          <span
            className="flex items-center justify-center overflow-hidden h-8"
            aria-hidden
          >
            {letters.map((letter, index) => (
              <span
                data-letter={letter}
                className="letter inline-block relative h-8 after:h-8 after:absolute after:left-0 after:top-full after:content-[attr(data-letter)] leading-8 text-base"
                key={index}
              >
                {letter}
              </span>
            ))}
          </span>
          <span className="absolute inset-0 block -z-10 pointer-events-none">
            {Array.from({ length: starCount }).map((_, index) => (
              <Star
                className={`w-4 h-4 absolute opacity-0 left-1/2 top-1/2 stars-${index}`}
                fill="blue"
                key={index}
              />
            ))}
          </span>
        </button>
      </div>
    </div>
  );
};
 
export default Sparkles;

Usage

In the directory you want to use, do the following:

import Sparkles from "@/components/buttons/sparkles";
 
const MyButtons = () => {
  return (
    <div>
      {/* your other content*/}
 
      <Sparkles text="Click me" />
 
      {/* your other content*/}
    </div>
  );
};
 
export default MyButtons;

Credits

Built by Bossadi Zenith