Spotlight Card
Card surface with a soft spotlight that tracks the cursor and fades in on hover. Built on design tokens, no hard-coded colors.
Example
Installation
npx shadcn@latest add https://hirael.com/r/spotlight-card.jsonAPI
<SpotlightCard />
+ native element props| Prop | Type | Default |
|---|---|---|
sizeDiameter of the spotlight, in px. | number | 350 |
Component source
"use client";
import * as React from "react";
import { motion, useMotionTemplate, useMotionValue } from "motion/react";
import { cn } from "@/lib/utils";
type SpotlightCardProps = React.ComponentProps<"div"> & {
/** Diameter of the spotlight, in px. */
size?: number;
};
function SpotlightCard({
className,
children,
size = 350,
...props
}: SpotlightCardProps) {
const x = useMotionValue(0);
const y = useMotionValue(0);
const background = useMotionTemplate`radial-gradient(${size}px circle at ${x}px ${y}px, color-mix(in oklch, var(--foreground) 10%, transparent), transparent 70%)`;
const onPointerMove = (event: React.PointerEvent<HTMLDivElement>) => {
const rect = event.currentTarget.getBoundingClientRect();
x.set(event.clientX - rect.left);
y.set(event.clientY - rect.top);
};
return (
<div
data-slot="spotlight-card"
onPointerMove={onPointerMove}
className={cn(
"group relative overflow-hidden rounded-lg border border-border bg-card text-card-foreground",
className,
)}
{...props}
>
<motion.div
aria-hidden
data-slot="spotlight-card-glow"
className="pointer-events-none absolute inset-0 opacity-0 transition-opacity duration-300 group-hover:opacity-100"
style={{ background }}
/>
<div data-slot="spotlight-card-content" className="relative">
{children}
</div>
</div>
);
}
export { SpotlightCard };
Dependencies
npm
motion