Sparkles Text
Twinkling stars orbiting your headline.
0.9 KB gzippedDeps: motion/reactReduced-motion safeBase UI & Radix compatible
Magic moments
Installation
npx shadcn@latest add https://velora.colorlib.com/r/sparkles-text.jsonInstalls with: motion
Source
"use client";
import { motion, useReducedMotion } from "motion/react";
import { cn } from "@/lib/utils";
interface SparklesTextProps extends React.HTMLAttributes<HTMLSpanElement> {
children: React.ReactNode;
/** Number of sparkles */
count?: number;
}
const colors = ["var(--brand-from)", "var(--brand-via)", "var(--brand-to)"];
/**
* Text with twinkling stars around it. Positions are derived from the
* index so server and client markup match.
*/
export function SparklesText({
children,
className,
count = 9,
...props
}: SparklesTextProps) {
const reducedMotion = useReducedMotion();
const sparkles = Array.from({ length: count }, (_, i) => ({
top: `${(i * 41 + 7) % 100}%`,
left: `${(i * 67 + 13) % 100}%`,
size: 8 + ((i * 29) % 8),
delay: ((i * 53) % 30) / 10,
color: colors[i % colors.length],
}));
return (
<span
data-slot="sparkles-text"
className={cn("relative inline-block", className)}
{...props}
>
{!reducedMotion &&
sparkles.map((s, i) => (
<motion.svg
key={i}
aria-hidden
viewBox="0 0 24 24"
className="pointer-events-none absolute z-10"
style={{
top: s.top,
left: s.left,
width: s.size,
height: s.size,
fill: s.color,
}}
initial={{ scale: 0, rotate: 0, opacity: 0 }}
animate={{ scale: [0, 1, 0], rotate: [0, 120], opacity: [0, 1, 0] }}
transition={{
duration: 1.4,
delay: s.delay,
repeat: Infinity,
repeatDelay: 1.8,
ease: "easeInOut",
}}
>
<path d="M12 0 L14.8 9.2 L24 12 L14.8 14.8 L12 24 L9.2 14.8 L0 12 L9.2 9.2 Z" />
</motion.svg>
))}
<span className="relative">{children}</span>
</span>
);
}