M3
N7
O7
P4
Q2
R5
E3
F3
G2
H3
I9
J1
Explore the Grid
Move your cursor across the canvas to reveal a modern design system. Each element represents a component in our design language.
Installation
Copy and paste the following code into your project.
"use client";
import React, { useRef, useState } from "react";
import { cn } from "@/lib/utils";
export interface CursorSpotlightProps
extends React.HTMLAttributes<HTMLDivElement> {
children?: React.ReactNode;
backgroundContent: React.ReactNode;
spotlightSize?: number;
overlayOpacity?: number;
spotlightColor?: string;
blurredEdges?: boolean;
showFaintBackground?: boolean;
glowIntensity?: number;
noiseTexture?: boolean;
}
export function CursorSpotlight({
children,
className,
backgroundContent,
spotlightSize = 50,
overlayOpacity = 0.9,
spotlightColor = "rgba(255, 255, 255, 0.15)",
blurredEdges = true,
showFaintBackground = false,
glowIntensity = 0.2,
noiseTexture = true,
...props
}: CursorSpotlightProps) {
const containerRef = useRef<HTMLDivElement>(null);
const [position, setPosition] = useState<{ x: number; y: number }>({
x: -1000,
y: -1000,
});
const [isHovering, setIsHovering] = useState(false);
const handleMouseMove = (e: React.MouseEvent<HTMLDivElement>) => {
if (!containerRef.current) return;
const rect = containerRef.current.getBoundingClientRect();
setPosition({
x: e.clientX - rect.left,
y: e.clientY - rect.top,
});
};
const handleMouseEnter = () => {
setIsHovering(true);
};
const handleMouseLeave = () => {
setIsHovering(false);
setPosition({
x: -1000,
y: -1000,
});
};
const getSpotlightGradient = () => {
const blurAmount = blurredEdges ? "circle" : "circle";
return `radial-gradient(${spotlightSize}px ${blurAmount} at ${position.x}px ${position.y}px,
transparent 0%,
rgba(0, 0, 0, ${overlayOpacity}) ${blurredEdges ? "80%" : "100%"})`;
};
const getGlowEffect = () => {
return `radial-gradient(${spotlightSize * 1.2}px circle at ${position.x}px ${position.y}px,
${spotlightColor} 0%,
transparent 70%)`;
};
return (
<div
ref={containerRef}
className={cn("relative overflow-hidden", className)}
onMouseMove={handleMouseMove}
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
{...props}
>
<div className="absolute inset-0 z-0">{backgroundContent}</div>
<div
className="absolute inset-0 z-10 transition-opacity duration-300"
style={{
background: getSpotlightGradient(),
opacity: 1,
pointerEvents: "none",
}}
/>
{glowIntensity > 0 && (
<div
className="absolute inset-0 z-20 mix-blend-overlay transition-opacity duration-300"
style={{
background: getGlowEffect(),
opacity: isHovering ? glowIntensity : 0,
pointerEvents: "none",
}}
/>
)}
{noiseTexture && (
<div
className="absolute inset-0 z-30 opacity-20 pointer-events-none mix-blend-overlay"
style={{
opacity: isHovering ? 0.1 : 0,
}}
>
<svg
className="h-full w-full opacity-20"
xmlns="http://www.w3.org/2000/svg"
width="100%"
height="100%"
>
<filter id="noise">
<feTurbulence
type="fractalNoise"
baseFrequency="0.65"
numOctaves="3"
stitchTiles="stitch"
/>
<feColorMatrix type="saturate" values="0" />
</filter>
<rect width="100%" height="100%" filter="url(#noise)" />
</svg>
</div>
)}
{showFaintBackground && (
<div
className="absolute inset-0 z-5 transition-opacity duration-300"
style={{
background: `rgba(0, 0, 0, ${overlayOpacity * 0.7})`,
opacity: 1,
pointerEvents: "none",
}}
/>
)}
<div className="relative z-40">{children}</div>
</div>
);
}
Update the import paths to match your project setup.
import CursorSpotlight from "@/components/ui/cursor-spotlight";
Usage
import CursorSpotlight from "@/components/ui/cursor-spotlight";
export default function MyComponent() {
return (
<CursorSpotlight
className="h-[500px] w-full rounded-xl"
spotlightSize={200}
overlayOpacity={0.95}
spotlightColor="rgba(100, 100, 255, 0.2)"
backgroundContent={
<div className="grid h-full w-full grid-cols-4 grid-rows-4 gap-4 p-8">
{/* Your background elements here */}
</div>
}
>
<div className="flex h-full w-full flex-col items-center justify-center p-8 text-center">
<h2 className="text-3xl font-bold">Move your cursor to reveal</h2>
<p className="mt-4 text-muted-foreground">
Content visible on top of the spotlight effect
</p>
</div>
</CursorSpotlight>
);
}
Props
Prop | Type | Description | Default |
---|---|---|---|
backgroundContent | React.ReactNode | Background elements to be revealed by the spotlight | Required |
children | React.ReactNode | Content to display on top of the spotlight effect | - |
spotlightSize | number | Size of the spotlight circle in pixels | 250 |
overlayOpacity | number | Opacity of the overlay covering the background (0-1) | 0.9 |
spotlightColor | string | Color of the spotlight effect | rgba(255, 255, 255, 0.15) |
blurredEdges | boolean | Whether to add a blur effect to the spotlight edges | true |
showFaintBackground | boolean | Whether to show a faint version of the background outside the spotlight | false |
glowIntensity | number | Intensity of the glow effect (0-1) | 0.2 |
noiseTexture | boolean | Whether to add a subtle noise texture to the overlay | true |
Examples
Basic Example
<CursorSpotlight
className="h-[400px] w-full rounded-xl"
spotlightSize={150}
backgroundContent={
<div className="grid h-full w-full grid-cols-3 grid-rows-3 gap-2 p-4">
{/* Your background elements */}
</div>
}
>
<div className="flex h-full items-center justify-center">
<h2 className="text-2xl font-bold">Explore with your cursor</h2>
</div>
</CursorSpotlight>
With Colored Spotlight
<CursorSpotlight
className="h-[400px] w-full rounded-xl"
spotlightSize={200}
spotlightColor="rgba(255, 100, 100, 0.2)"
glowIntensity={0.4}
backgroundContent={
<div className="grid h-full w-full grid-cols-3 grid-rows-3 gap-2 p-4">
{/* Your background elements */}
</div>
}
>
<div className="flex h-full items-center justify-center">
<h2 className="text-2xl font-bold">Red spotlight effect</h2>
</div>
</CursorSpotlight>
With Faint Background
<CursorSpotlight
className="h-[400px] w-full rounded-xl"
spotlightSize={180}
showFaintBackground={true}
backgroundContent={
<div className="grid h-full w-full grid-cols-3 grid-rows-3 gap-2 p-4">
{/* Your background elements */}
</div>
}
>
<div className="flex h-full items-center justify-center">
<h2 className="text-2xl font-bold">Faintly visible background</h2>
</div>
</CursorSpotlight>