"use client"; import { useEffect, useRef, type CSSProperties, type ReactNode } from "react"; type BorderGlowProps = { children: ReactNode; className?: string; /** Glow colour. Any CSS colour. */ color?: string; /** Distance from the card, in pixels, where the glow starts to show. */ reach?: number; /** Width of the lit part of the border, in degrees. */ spread?: number; /** Border colour where the light is not. */ border?: string; }; /* BorderGlow: the edge nearest the pointer lights up, even before the pointer reaches the card. */ export function BorderGlow({ children, className = "rounded-[15px] bg-[#100e1c] p-6 text-white", color = "#a78bfa", reach = 160, spread = 70, border = "rgba(255,255,255,0.1)", }: BorderGlowProps) { const ref = useRef(null); useEffect(() => { let frame = 0; const onMove = (e: PointerEvent) => { cancelAnimationFrame(frame); frame = requestAnimationFrame(() => { const el = ref.current; if (!el) return; const r = el.getBoundingClientRect(); const angle = (Math.atan2(e.clientY - (r.top + r.height / 2), e.clientX - (r.left + r.width / 2)) * 180) / Math.PI + 90; const dx = Math.max(r.left - e.clientX, 0, e.clientX - r.right); const dy = Math.max(r.top - e.clientY, 0, e.clientY - r.bottom); const glow = Math.max(0, 1 - Math.hypot(dx, dy) / reach); el.style.setProperty("--angle", `${angle}deg`); el.style.setProperty("--glow", `${glow}`); }); }; window.addEventListener("pointermove", onMove, { passive: true }); return () => { window.removeEventListener("pointermove", onMove); cancelAnimationFrame(frame); }; }, [reach]); const light = `conic-gradient(from calc(var(--angle) - ${spread}deg), transparent 0deg, ${color} ${spread}deg, transparent ${spread * 2}deg)`; return (
{children}
); }