102

Meteor Shower

A Meteor Shower component for Next.js, built with React and styled using TailwindCSS.

Meteor Shower Component

This interactive component displays a meteor shower that automatically adapt to dark and light mode. Using the Meteors component in your application. Adjust the number prop to control the intensity of the meteor display.

Usage

To use the Meteors component in your project, simply import it and set the number prop as shown below:

import { Meteors } from "./components/Meteors";
 
function MyApp() {
  return <Meteors number={20} />;
}

Source Code

To implement the animation effect, update your tailwind.config.js as follows:

  theme: {
    extend: {
      animation: {
        "meteor-effect": "meteor 5s linear infinite",
      },
      keyframes: {
        meteor: {
          "0%": { transform: "rotate(215deg) translateX(0)", opacity: 1 },
          "70%": { opacity: 1 },
          "100%": {
            transform: "rotate(215deg) translateX(-500px)",
            opacity: 0,
          },
        },
      }
    }
  }

Then, create the Meteors component in @/app/components/Meteors.tsx with the following structure:

import clsx from "clsx";
import React from "react";
 
export const Meteors = ({ number }: { number?: number }) => {
  // Helper function to generate random values
  const getRandomValue = (min: number, max: number, isInt = false) => {
    const value = Math.random() * (max - min) + min;
    return isInt ? Math.floor(value) : value;
  };
 
  // Create an array of meteors
  const meteors = Array.from({ length: number ?? 20 }, (_, idx) => (
    <span
      key={"meteor" + idx}
      className={clsx(
        "animate-meteor-effect absolute -top-2 left-1/2 h-0.5 w-0.5 rounded-full bg-slate-500 shadow-[0_0_0_1px_#ffffff10] rotate-[215deg]",
        "before:content-[''] before:absolute before:top-1/2 before:transform before:-translate-y-[50%] before:w-[50px] before:h-[1px] before:bg-gradient-to-r before:from-[#64748b] before:to-transparent"
      )}
      style={{
        left: `${getRandomValue(-800, 800, true)}px`,
        animationDelay: `${getRandomValue(0.2, 2.8)}s`,
        animationDuration: `${getRandomValue(2, 10, true)}s`,
      }}
    ></span>
  ));
 
  return (
    <div className="absolute inset-0 overflow-hidden pointer-events-none">
      {meteors}
    </div>
  );
};