diff options
Diffstat (limited to 'src/components/ui/card-spotlight.tsx')
-rw-r--r-- | src/components/ui/card-spotlight.tsx | 74 |
1 files changed, 74 insertions, 0 deletions
diff --git a/src/components/ui/card-spotlight.tsx b/src/components/ui/card-spotlight.tsx new file mode 100644 index 0000000..f0b17d7 --- /dev/null +++ b/src/components/ui/card-spotlight.tsx @@ -0,0 +1,74 @@ +"use client"; + +import { useMotionValue, motion, useMotionTemplate } from "motion/react"; +import React, { MouseEvent as ReactMouseEvent, useState } from "react"; +import { CanvasRevealEffect } from "@/components/ui/canvas-reveal-effect"; +import { cn } from "@/lib/utils"; + +export const CardSpotlight = ({ + children, + radius = 350, + color = "#ffffff33", + 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> + ); +}; |