Make a wish
Customize
Usage
import { Meteors } from "@/components/motionkit/meteors";
<Meteors className="h-96 rounded-3xl">
<h1>Your hero</h1>
</Meteors>Motion
The exact curves this component runs, plotted with Motion's own maths.
Streak
Runs on its own
Works in the App Router as is. Requires Tailwind CSS v4.
npm install motionSave as components/motionkit/meteors.tsx.
"use client";
import type { ReactNode } from "react";
import { motion, useReducedMotion } from "motion/react";
type MeteorsProps = {
children?: ReactNode;
/** Number of meteors in flight. */
count?: number;
/** Seconds for one meteor to cross. */
duration?: number;
/** Colour of the meteor head and tail. */
color?: string;
className?: string;
};
// fixed pseudo-random offsets so meteors look scattered but render identically on server and client
const scatter = (index: number) => ((index * 7919) % 100) / 100;
// meteors fall down and to the left at this angle below the horizon
const ANGLE = 35;
const TRAVEL = 700;
const dx = -Math.cos((ANGLE * Math.PI) / 180) * TRAVEL;
const dy = Math.sin((ANGLE * Math.PI) / 180) * TRAVEL;
export function Meteors({ children, count = 12, duration = 2.4, color = "#F6F1E8", className = "" }: MeteorsProps) {
const reduceMotion = useReducedMotion();
return (
<div className={`relative isolate overflow-hidden bg-[#0C1010] ${className}`}>
{/* a still dot texture, so the sky is never empty between meteors or with reduced motion */}
<div aria-hidden className="absolute inset-0 -z-10 bg-[radial-gradient(#ffffff12_1px,transparent_1px)] [background-size:22px_22px]" />
{!reduceMotion && (
<div aria-hidden className="absolute inset-0 -z-10">
{Array.from({ length: count }, (_, index) => (
<motion.span
key={index}
className="absolute h-px w-28"
style={{
left: `${15 + scatter(index) * 100}%`,
top: `${-10 + scatter(index + 4) * 45}%`,
rotate: -ANGLE,
originX: 0,
background: `linear-gradient(to right, ${color}, transparent)`,
}}
initial={{ opacity: 0 }}
animate={{ x: [0, dx], y: [0, dy], opacity: [0, 1, 1, 0] }}
transition={{
duration: duration * (0.75 + scatter(index + 2) * 0.5),
delay: scatter(index + 6) * duration * 2,
repeat: Infinity,
repeatDelay: scatter(index + 9) * duration * 2,
ease: "linear",
}}
>
{/* the bright head */}
<span className="absolute -left-0.5 -top-[1.5px] size-1 rounded-full" style={{ backgroundColor: color, boxShadow: `0 0 8px 2px ${color}` }} />
</motion.span>
))}
</div>
)}
{children}
</div>
);
}
| Prop | Type | Default | Description |
|---|---|---|---|
| count | number | 12 | Number of meteors in flight. |
| duration | number | 2.4 | Seconds for one meteor to cross. |
| color | string | "#F6F1E8" | Colour of the meteor head and tail. |
Look up
Star Field
A slow-drifting night sky with twinkling stars, for space, launch and AI product heroes.
Now shipping
Light Beams
Thin grid lines with streaks of light falling down them at scattered times.
Ambient by default
Aurora Background
Drifting, blurred color fields for hero sections and empty states.