All components
Card Spotlight
cardsAceternity UI component.
responsive · 480px
Install
Same command in any shadcn project — React (Vite/CRA), Next.js, Remix, Astro, and more:
$
npx shadcn@latest add https://your-domain/r/card-spotlight.jsonUsage
"use client";
import { CardSpotlight } from "@/registry/aceternity-ui/card-spotlight";
export default function Demo() {
return (
<div className="flex items-center justify-center min-h-[420px] p-8 bg-background">
<CardSpotlight className="max-w-sm w-full min-h-[220px]">
<p className="relative z-20 text-base font-bold text-white">
Authentication Steps
</p>
<p className="relative z-20 mt-4 text-sm text-neutral-400">
Move your cursor over the card to watch a radial spotlight illuminate
the surface with a canvas particle reveal beneath.
</p>
<ul className="relative z-20 mt-6 space-y-2 text-xs text-neutral-500">
<li className="flex items-center gap-2">
<span className="h-1.5 w-1.5 rounded-full bg-indigo-400" />
Enter your credentials
</li>
<li className="flex items-center gap-2">
<span className="h-1.5 w-1.5 rounded-full bg-indigo-400" />
Verify via two-factor
</li>
<li className="flex items-center gap-2">
<span className="h-1.5 w-1.5 rounded-full bg-indigo-400" />
Access granted
</li>
</ul>
</CardSpotlight>
</div>
);
}Component source
"use client";
import { useMotionValue, motion, useMotionTemplate } from "motion/react";
import React, { MouseEvent as ReactMouseEvent, useState } from "react";
import { CanvasRevealEffect } from "@/registry/aceternity-ui/canvas-reveal-effect";
import { cn } from "@/lib/utils";
export const CardSpotlight = ({
children,
radius = 350,
color = "#262626",
className,
...props
}: {
radius?: number;
color?: string;
children: React.ReactNode;
} & React.HTMLAttributes<HTMLDivElement>) => {
const mouseX = useMotionValue(0);
const mouseY = useMotionValue(0);
function handleMouseMove({
currentTarget,
clientX,
clientY,
}: ReactMouseEvent<HTMLDivElement>) {
let { left, top } = currentTarget.getBoundingClientRect();
mouseX.set(clientX - left);
mouseY.set(clientY - top);
}
const [isHovering, setIsHovering] = useState(false);
const handleMouseEnter = () => setIsHovering(true);
const handleMouseLeave = () => setIsHovering(false);
return (
<div
className={cn(
"group/spotlight p-10 rounded-md relative border border-neutral-800 bg-black dark:border-neutral-800",
className
)}
onMouseMove={handleMouseMove}
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
{...props}
>
<motion.div
className="pointer-events-none absolute z-0 -inset-px rounded-md opacity-0 transition duration-300 group-hover/spotlight:opacity-100"
style={{
backgroundColor: color,
maskImage: useMotionTemplate`
radial-gradient(
${radius}px circle at ${mouseX}px ${mouseY}px,
white,
transparent 80%
)
`,
}}
>
{isHovering && (
<CanvasRevealEffect
animationSpeed={5}
containerClassName="bg-transparent absolute inset-0 pointer-events-none"
colors={[
[59, 130, 246],
[139, 92, 246],
]}
dotSize={3}
/>
)}
</motion.div>
{children}
</div>
);
};Dependencies
motion
Source: Aceternity UI