Background & Effects
Spotlight
A high-interactive background effect that follows the user's cursor with a localized radial glow.Copy Markdown
A simple container that tracks your mouse with a subtle radial gradient.
A pre-styled card component featuring the spotlight effect.
Innovation
Building the future with modern design systems and interactive components.
Read more →
Speed
Optimized for performance and developer experience from day one.
Read more →
<SpotlightCard
title="Innovation"
description="Building the future with modern design systems."
gradientColor="rgba(59, 130, 246, 0.1)"
/>
- Mouse Tracking: Smooth, spring-animated radial gradient that follows the cursor.
- Customizable: Control the gradient color, size, and hover opacity easily.
- Composable: Wrap any content with the
Spotlight component to add the effect.
- Ready to Use: Pre-styled with borders, backgrounds, and layout for quick implementation.
- Modern Aesthetics: Features an italic font style for titles and a clean description layout.
- Integrated Effects: Automatically includes the spotlight effect with custom color support.
The fastest way to get started is using the shadcn CLI.
Before using the @nurav-ui alias, add this to your components.json:
{
"registries": {
"@nurav-ui": "https://nurav-ui.vercel.app/r"
}
}
Or skip alias setup entirely and use the direct URLs below.
npx shadcn@latest add @nurav-ui/spotlight
npx shadcn@latest add @nurav-ui/spotlight-card
Alternatively, install via direct URL (no components.json changes needed):
npx shadcn@latest add https://nurav-ui.vercel.app/r/spotlight.json
npx shadcn@latest add https://nurav-ui.vercel.app/r/spotlight-card.json
If you prefer manual configuration, follow these steps:
Install Dependencies
Install the necessary animation libraries:
npm install motion clsx tailwind-merge
Create/Customize Component
Copy the source code into your project. You can modify this code to create your own custom spotlight effects:
'use client'
import React, { useRef, useState, useEffect } from 'react'
import { motion, useSpring, useMotionValue } from 'motion/react'
import { cn } from '@/lib/utils'
interface SpotlightProps extends React.HTMLAttributes<HTMLDivElement> {
gradientColor?: string
gradientSize?: number
hoverOpacity?: number
}
export function Spotlight({
children,
gradientColor = "rgba(255, 255, 255, 0.15)",
gradientSize = 350,
hoverOpacity = 1,
className,
...props
}: SpotlightProps) {
const containerRef = useRef<HTMLDivElement>(null)
const mouseX = useMotionValue(0)
const mouseY = useMotionValue(0)
// Use springs for smoother movement
const springX = useSpring(mouseX, { stiffness: 500, damping: 50 })
const springY = useSpring(mouseY, { stiffness: 500, damping: 50 })
const [isHovered, setIsHovered] = useState(false)
const handleMouseMove = (e: React.MouseEvent<HTMLDivElement>) => {
if (!containerRef.current) return
const { left, top } = containerRef.current.getBoundingClientRect()
mouseX.set(e.clientX - left)
mouseY.set(e.clientY - top)
}
return (
<div
ref={containerRef}
onMouseMove={handleMouseMove}
onMouseEnter={() => setIsHovered(true)}
onMouseLeave={() => setIsHovered(false)}
className={cn("relative overflow-hidden group", className)}
{...props}
>
<motion.div
className="pointer-events-none absolute -inset-px transition-opacity duration-300 z-10"
style={{
opacity: isHovered ? hoverOpacity : 0,
background: `radial-gradient(${gradientSize}px circle at ${springX.get()}px ${springY.get()}px, ${gradientColor}, transparent 80%)`,
}}
animate={{
background: `radial-gradient(${gradientSize}px circle at ${springX.get()}px ${springY.get()}px, ${gradientColor}, transparent 80%)`
}}
/>
{children}
</div>
)
}
'use client'
import React from 'react'
import { Spotlight } from './Spotlight'
import { cn } from '@/lib/utils'
interface SpotlightCardProps extends React.HTMLAttributes<HTMLDivElement> {
title?: string
description?: string
gradientColor?: string
}
export function SpotlightCard({
title,
description,
gradientColor,
className,
children,
...props
}: SpotlightCardProps) {
return (
<Spotlight
gradientColor={gradientColor}
className={cn(
"rounded-2xl border border-neutral-200 dark:border-neutral-800 bg-white dark:bg-neutral-900 p-8",
className
)}
{...props}
>
<div className="relative z-20 space-y-3">
{title && (
<h3 className="text-xl font-semibold text-neutral-900 dark:text-neutral-100 italic">
{title}
</h3>
)}
{description && (
<p className="text-neutral-500 dark:text-neutral-400 text-sm leading-relaxed">
{description}
</p>
)}
{children}
</div>
</Spotlight>
);
}