Spotlight
Installation
Copy and paste the following code into your project.
components/ui/spotlight.tsx
import React, { useRef } from "react";
import { motion, AnimatePresence } from "framer-motion";
import { cn } from "@/lib/utils";
export interface SpotlightProps extends React.HTMLAttributes<HTMLDivElement> {
children?: React.ReactNode;
spotlightColor?: string;
spotlightIntensity?: number;
enableAnimations?: boolean;
}
export function Spotlight({
children,
className,
spotlightColor = "#4332CF",
spotlightIntensity = 80,
enableAnimations = true,
...props
}: SpotlightProps) {
const containerRef = useRef<HTMLDivElement>(null);
const normalizedIntensity = spotlightIntensity / 100;
const baseVariants = {
initial: { opacity: 0, scale: 0.8 },
animate: {
opacity: 1,
scale: 1,
transition: {
duration: 1.5,
ease: "easeOut",
},
},
pulse: {
opacity: [
normalizedIntensity * 0.3,
normalizedIntensity * 0.4,
normalizedIntensity * 0.3,
],
scale: [1, 1.1, 1],
transition: {
duration: 8,
repeat: Infinity,
repeatType: "reverse" as const,
ease: "easeInOut",
},
},
};
const middleVariants = {
initial: { opacity: 0, scale: 0.9 },
animate: {
opacity: 1,
scale: 1,
transition: {
duration: 1.5,
ease: "easeOut",
},
},
pulse: {
opacity: [
normalizedIntensity * 0.6,
normalizedIntensity * 0.7,
normalizedIntensity * 0.6,
],
scale: [1, 1.05, 1],
transition: {
duration: 6,
repeat: Infinity,
repeatType: "reverse" as const,
ease: "easeInOut",
delay: 0.5,
},
},
};
const mainVariants = {
initial: { opacity: 0, scale: 0.95 },
animate: {
opacity: 1,
scale: 1,
transition: {
duration: 1.5,
ease: "easeOut",
},
},
pulse: {
opacity: [
normalizedIntensity,
normalizedIntensity * 1.1,
normalizedIntensity,
],
scale: [1, 1.02, 1],
transition: {
duration: 4,
repeat: Infinity,
repeatType: "reverse" as const,
ease: "easeInOut",
delay: 1,
},
},
};
return (
<div
ref={containerRef}
className={cn("relative overflow-hidden bg-black", className)}
{...props}
>
<AnimatePresence>
<motion.div
key="base-layer"
className="z-8 absolute inset-0 w-full"
initial="initial"
animate={enableAnimations ? "pulse" : "animate"}
variants={baseVariants}
style={{
background: `radial-gradient(ellipse at 50% 100%,
${spotlightColor} 0%,
rgba(67, 50, 207, 0.4) 25%,
rgba(67, 50, 207, 0.1) 50%,
transparent 80%)`,
mixBlendMode: "screen",
}}
/>
<motion.div
key="middle-layer"
className="z-9 absolute inset-0 w-full"
initial="initial"
animate={enableAnimations ? "pulse" : "animate"}
variants={middleVariants}
style={{
background: `radial-gradient(ellipse at 50% 100%,
${spotlightColor} 0%,
rgba(67, 50, 207, 0.6) 20%,
rgba(67, 50, 207, 0.2) 40%,
transparent 70%)`,
mixBlendMode: "screen",
}}
/>
<motion.div
key="main-layer"
className="absolute inset-0 z-10 w-full"
initial="initial"
animate={enableAnimations ? "pulse" : "animate"}
variants={mainVariants}
style={{
background: `radial-gradient(ellipse at 50% 100%,
${spotlightColor} 0%,
rgba(67, 50, 207, 0.8) 15%,
rgba(67, 50, 207, 0.3) 35%,
transparent 70%)`,
mixBlendMode: "screen",
}}
/>
<div key="content" className="relative z-20">
{children}
</div>
</AnimatePresence>
</div>
);
}
Update the import paths to match your project setup.
import Spotlight from "@/components/ui/spotlight";
Usage
import { Spotlight } from "@/components/ui/spotlight";
export default function SpotlightDemo() {
return (
<Spotlight>
<h1>Your content here</h1>
</Spotlight>
);
}
Examples
Basic spotlight
A basic spotlight effect with default settings.
<Spotlight>
<h1>Spotlight</h1>
</Spotlight>
Custom color and intensity
Customize the spotlight's color and intensity.
<Spotlight spotlightColor="#4332CF" spotlightIntensity={80}>
<h1>Custom Spotlight</h1>
</Spotlight>
Disabled animations
Use the spotlight effect without animations.
<Spotlight enableAnimations={false}>
<h1>Static Spotlight</h1>
</Spotlight>
Props
Prop | Type | Default | Description |
---|---|---|---|
spotlightColor | string | "#4332CF" | The color of the spotlight effect |
spotlightIntensity | number | 100 | The intensity of the spotlight effect (0-100) |
enableAnimations | boolean | true | Whether to enable the pulsing animations |
className | string | "" | Additonal CSS classes to apply to the spotlight |
children | ReactNode | undefined | The content to display on top of the spotlight |