"use client";
import React, { useEffect, useState } from "react";
export interface MeteorsProps {
/** Number of meteors to render */
number?: number;
className?: string;
}
export const Meteors = ({ number = 20, className = "" }: MeteorsProps) => {
const [meteors, setMeteors] = useState<
Array<{
id: number;
top: number;
left: number;
animationDelay: string;
animationDuration: string;
}>
>([]);
useEffect(() => {
// Generate meteor styles on the client to avoid hydration mismatches
const generatedMeteors = Array.from({ length: number }).map((_, i) => ({
id: i,
// Random position from left edge (-20% to 80%) to allow downward diagonal movement
left: Math.floor(Math.random() * 100) - 20,
// Start slightly above the container
top: -10,
// Random delay to stagger animations
animationDelay: `${(Math.random() * 2).toFixed(2)}s`,
// Random duration for varied speeds
animationDuration: `${Math.floor(Math.random() * 8 + 2)}s`,
}));
setMeteors(generatedMeteors);
}, [number]);
return (
<div
className={`absolute inset-0 overflow-hidden pointer-events-none ${className}`}
style={{
position: "absolute",
inset: 0,
overflow: "hidden",
pointerEvents: "none",
}}
>
{meteors.map((meteor) => (
<span
key={meteor.id}
className="bare-meteor"
style={{
top: `${meteor.top}%`,
left: `${meteor.left}%`,
animationDelay: meteor.animationDelay,
animationDuration: meteor.animationDuration,
}}
>
{/* Glowing head of the meteor */}
<span className="bare-meteor-head" />
</span>
))}
</div>
);
};