"use client";
import {cn} from "@/app/_lib/cn";
import React, {MouseEvent, ReactNode, useEffect, useRef, useState} from "react";
interface MousePosition {
x: number;
y: number;
}
export default function Spotlight() {
const containerRef = useRef<HTMLDivElement>(null);
const [position, setPosition] = useState<MousePosition | undefined>({
x: 0,
y: 0,
});
const [isMouseLeave, setIsMouseLeave] = useState(true);
const handleMouseMove = (e: MouseEvent<HTMLDivElement>) => {
const {clientX, clientY} = e;
setIsMouseLeave(false);
setPosition({
x: clientX,
y: clientY,
});
};
const handleMouseLeave = () => setIsMouseLeave(true);
return (
<article
onMouseMove={handleMouseMove}
onMouseLeave={handleMouseLeave}
ref={containerRef}
className="font-poppins group/article relative grid min-h-96 place-items-center rounded-xl border border-white/10 bg-white/5 p-4 md:aspect-square md:min-h-0">
<div className="size-full overflow-hidden">
<div className="grid h-full w-full grid-cols-4 grid-rows-16 gap-4 lg:grid-cols-3 lg:grid-rows-15">
<Card
className="col-span-full row-span-6 lg:col-span-2 lg:row-span-11"
containerMousePosition={position}
isMouseLeave={isMouseLeave}>
<div className="relative grid size-full place-items-center">
<div className="absolute top-13 right-4 w-6/10 text-right">
<h1 className="mb-2 text-lg lg:text-xl">
Vietnam’s Reunification Day
</h1>
<p className="text-xs opacity-60">
Apr 30, 1975 - Apr 30, 2025
</p>
</div>
<img
src="https://ik.imagekit.io/khoaphan/playground/Spotlight/VN-map.svg?updatedAt=1745730197368"
className="w-9/10 grayscale-100 transition-[filter] duration-300 group-hover/article:grayscale-50 hover:grayscale-0"
/>
</div>
</Card>
<Card
className="col-span-full row-span-4 lg:col-span-1 lg:row-span-8"
containerMousePosition={position}
isMouseLeave={isMouseLeave}>
<div className="flex size-full flex-col justify-between gap-y-5 px-4 py-6 lg:p-3 lg:py-4">
<p className="text-sm lg:pt-2">
Reunification Day is more than a historical
event—it’s a celebration of resilience, unity,
and the Vietnamese spirit.
</p>
<img
src="https://ik.imagekit.io/khoaphan/playground/Spotlight/end-of-war.jpg?updatedAt=1745732134314"
className="rounded-lg brightness-75"
/>
</div>
</Card>
<Card
className="col-span-full row-span-4 overflow-hidden lg:col-span-1 lg:row-span-7"
containerMousePosition={position}
isMouseLeave={isMouseLeave}>
<img
src="https://ik.imagekit.io/khoaphan/playground/Spotlight/VN-flag.svg?updatedAt=1745730193410"
className="size-full object-cover grayscale-35 transition-[filter] duration-300 will-change-[filter] group-hover/article:grayscale-25 hover:grayscale-0"
/>
</Card>
<Card
className="col-span-full row-span-2 lg:col-span-2 lg:row-span-4"
containerMousePosition={position}
isMouseLeave={isMouseLeave}>
<div className="grid size-full place-items-center">
<div className="p-4">
<h2 className="mb-2 font-medium">
On Apr 30, 1975
</h2>
<p className="text-sm">
Saigon fell, ending the Vietnam War and
reuniting Vietnam, symbolizing peace after
decades of conflict.
</p>
</div>
</div>
</Card>
</div>
</div>
</article>
);
}
const Card = ({
containerMousePosition,
className,
isMouseLeave,
children,
}: {
containerMousePosition?: MousePosition;
className?: string;
isMouseLeave?: boolean;
children: ReactNode;
}) => {
const spotlightRef = useRef<HTMLDivElement>(null);
const [spotlightPosition, setSpotlightPosition] = useState({x: 0, y: 0});
useEffect(() => {
const rect = spotlightRef.current?.getBoundingClientRect();
setSpotlightPosition({
x: (containerMousePosition?.x || 0) - (rect?.left || 0),
y: (containerMousePosition?.y || 0) - (rect?.top || 0),
});
}, [containerMousePosition?.x, containerMousePosition?.y]);
return (
<div
className={cn(
"relative overflow-hidden rounded-xl border-gray-500 backdrop-blur-2xl",
className
)}>
<div
className={cn(
"absolute inset-0 bg-white/10 transition-opacity duration-1000",
isMouseLeave && "opacity-0"
)}
style={{
backgroundImage: `radial-gradient(400px at ${spotlightPosition.x}px ${spotlightPosition.y}px ,rgba(255,255,255,0.3), transparent 70%)`,
}}
/>
<div className="relative h-full w-full p-px">
<div className="h-full w-full overflow-hidden rounded-xl bg-black">
{children}
</div>
</div>
<div
ref={spotlightRef}
style={{
backgroundImage: `radial-gradient(800px at ${spotlightPosition.x}px ${spotlightPosition.y}px ,rgba(255,255,255,0.06), transparent 70%)`,
}}
className={cn(
"pointer-events-none absolute inset-0 transition-opacity duration-1000",
isMouseLeave && "opacity-0"
)}
/>
</div>
);
};