this repo has no description
www.baileykane.co/
1import { motion } from "motion/react";
2import { useState, useRef, useEffect } from "react";
3
4export default function FlashlightEffect({
5 children,
6 size = 250,
7 intensity = 0.8,
8 softness = 0.8,
9}) {
10 const [isFocused, setIsFocused] = useState(false);
11 const containerRef = useRef(null);
12
13 useEffect(() => {
14 const container = containerRef.current;
15 if (!container) return;
16
17 function handleMouseMove(e) {
18 setIsFocused(true);
19 const rect = container.getBoundingClientRect();
20
21 // Get relative mouse position within the container
22 const x = e.clientX - rect.left;
23 const y = e.clientY - rect.top;
24
25 // Create the gradient background
26 // The first color stop is the bright center
27 // The second color stop creates the soft edge
28 const gradient = `
29 radial-gradient(
30 circle ${size}px at ${x}px ${y}px,
31 rgba(255, 255, 255, 0),
32 rgba(255, 255, 255, ${intensity}) ${100 * softness}%
33 )
34 `;
35
36 // Apply the gradient
37 container.style.setProperty("--light-position", gradient);
38 }
39
40 function handleMouseLeave() {
41 setIsFocused(false);
42 container.style.setProperty("--light-position", "none");
43 }
44
45 container.addEventListener("mousemove", handleMouseMove);
46 container.addEventListener("mouseleave", handleMouseLeave);
47
48 return () => {
49 container.removeEventListener("mousemove", handleMouseMove);
50 container.removeEventListener("mouseleave", handleMouseLeave);
51 };
52 }, [size, intensity, softness]);
53
54 return (
55 <motion.div
56 ref={containerRef}
57 className="relative isolate"
58 style={{
59 "--light-position": "none",
60 }}
61 >
62 {
63 /* Dark overlay */ isFocused && (
64 <div
65 className="absolute inset-0 pointer-events-none"
66 style={{
67 background: "rgba(0, 0, 0, 0.7)",
68 maskImage: "var(--light-position)",
69 WebkitMaskImage: "var(--light-position)",
70 maskComposite: "destination-out",
71 WebkitMaskComposite: "destination-out",
72 }}
73 />
74 )
75 }
76
77 {/* Content */}
78 {children}
79 </motion.div>
80 );
81}