Command Palette

Search for a command to run...

Docs
Spotlight Border Glow

Spotlight Border Glow

Cards with a dynamic spotlight effect that follows your cursor and a glowing animated border.

Your AI Companion, Designed for you

Syncs with your life

Connects with Spotify, Calendar, and your DMs to understand your mood and provide relevant support.

Mood-reactive voice

Adapts to your emotional state, speaking with empathy when you need comfort and clarity when you need focus.

Works offline

Your companion stays with you even without an internet connection, because support shouldn't depend on WiFi.

Private by default

Your conversations, emotions, and data stay between you and your companion. No exceptions.

Installation

Install the required dependencies:

npm install framer-motion clsx tailwind-merge

Add the utils.ts file to the @/lib folder

utils.ts

import { ClassValue, clsx } from "clsx";
import { twMerge } from "tailwind-merge";
 
export function cn(...inputs: ClassValue[]) {
  return twMerge(clsx(inputs));
}

Create a spotlight-border-glow.tsx component file and copy the below code.

spotlight-border-glow.tsx

 
"use client";
 
import { motion, useMotionTemplate, useMotionValue } from "framer-motion";
import React, { useCallback, useEffect, useRef } from "react";
 
import { cn } from "@/lib/utils";
 
interface SpotlightBorderGlowProps
extends React.HTMLAttributes<HTMLDivElement> {
gradientSize?: number;
gradientColor?: string;
gradientOpacity?: number;
borderColor?: string;
gradientFrom?: string;
gradientTo?: string;
}
 
export function SpotlightBorderGlow({
children,
className,
gradientSize = 200,
gradientColor = "#001530",
gradientOpacity = 0.8,
gradientFrom = "#0ea5e9",
gradientTo = "#3b82f6",
borderColor = "#ffffff1a",
}: SpotlightBorderGlowProps) {
const cardRef = useRef<HTMLDivElement>(null);
const mouseX = useMotionValue(-gradientSize);
const mouseY = useMotionValue(-gradientSize);
 
const handleMouseMove = useCallback(
(e: MouseEvent) => {
if (cardRef.current) {
const { left, top } = cardRef.current.getBoundingClientRect();
const clientX = e.clientX;
const clientY = e.clientY;
mouseX.set(clientX - left);
mouseY.set(clientY - top);
}
},
[mouseX, mouseY]
);
 
const handleMouseOut = useCallback(
(e: MouseEvent) => {
if (!e.relatedTarget) {
document.removeEventListener("mousemove", handleMouseMove);
mouseX.set(-gradientSize);
mouseY.set(-gradientSize);
}
},
[handleMouseMove, mouseX, gradientSize, mouseY]
);
 
const handleMouseEnter = useCallback(() => {
document.addEventListener("mousemove", handleMouseMove);
mouseX.set(-gradientSize);
mouseY.set(-gradientSize);
}, [handleMouseMove, mouseX, gradientSize, mouseY]);
 
useEffect(() => {
document.addEventListener("mousemove", handleMouseMove);
document.addEventListener("mouseout", handleMouseOut);
document.addEventListener("mouseenter", handleMouseEnter);
 
return () => {
document.removeEventListener("mousemove", handleMouseMove);
document.removeEventListener("mouseout", handleMouseOut);
document.removeEventListener("mouseenter", handleMouseEnter);
};
 
}, [handleMouseEnter, handleMouseMove, handleMouseOut]);
 
useEffect(() => {
mouseX.set(-gradientSize);
mouseY.set(-gradientSize);
}, [gradientSize, mouseX, mouseY]);
 
return (
 
<div
ref={cardRef}
className={cn("group relative flex size-full rounded-xl ", className)}
>
<div className="absolute inset-px z-10 rounded-xl bg-[#f7f7f7] dark:bg-[#0a0a0a]" />
<div className="relative z-30 w-full">{children}</div>
{/* spotlight overlay */}
<motion.div
className="pointer-events-none absolute inset-px z-10 rounded-xl opacity-0 transition-opacity duration-300 group-hover:opacity-100"
style={{
background: useMotionTemplate`
  radial-gradient(${gradientSize}px circle at ${mouseX}px ${mouseY}px, ${gradientColor}, transparent 100%)
`,
opacity: gradientOpacity,
}}
/>
{/* glowing border */}
<motion.div
className="pointer-events-none absolute inset-0 rounded-xl duration-300 group-hover:opacity-100"
style={{
background: useMotionTemplate`
  radial-gradient(${gradientSize}px circle at ${mouseX}px ${mouseY}px, ${gradientFrom}, ${gradientTo}, ${borderColor} 100% )
`,
}}
/>
</div>
); }
 

Update the import paths to match your project setup.

Usage

import { SpotlightBorderGlow } from "@/components/breezeblocks/spotlight-border-glow";
<SpotlightBorderGlow
  className="p-6"
  gradientSize={120}
  gradientColor="#001530"
  borderColor="#ffffff1a"
  gradientFrom="#0ea5e9"
  gradientTo="#3b82f6"
>
  <div>Card content here</div>
</SpotlightBorderGlow>

Props

PropTypeDescriptionDefault
childrenReact.ReactNodeContent inside the container(required)
classNamestringAdditional custom classes-
gradientSizenumberRadius (px) for the spotlight & border glow200
gradientColorstringSpotlight color#001530
gradientOpacitynumberSpotlight layer opacity0.8
borderColorstringDefault border color#ffffff1a
gradientFromstringBorder glow start color#0ea5e9
gradientTostringBorder glow end color#3b82f6
...propsHTMLAttributes<HTMLDivElement>Any other <div> props-