Sportlight Cards
Spotlight cards with a mouse-sensitive spotlight effect that highlights the border of the div or section as you move your cursor
Spotlight cards with a mouse-sensitive spotlight effect that highlights the border of the div or section as you move your cursor
Keeping track of your goals helps you stay organized, motivated, and focused. Regularly monitoring your progress ensures you stay on course.
1'use client';23import { cn } from '@/lib/utils';4import React, {5useRef,6useState,7MouseEvent,8useContext,9createContext,10} from 'react';11interface MousePosition {12x: number;13y: number;14}1516interface SpotlightProps {17children: React.ReactNode;18className?: string;19ProximitySpotlight?: boolean;20HoverFocusSpotlight?: boolean;21CursorFlowGradient?: boolean;22}23interface SpotlightItemProps {24children: React.ReactNode;25className?: string;26}2728interface SpotLightContextType {29ProximitySpotlight: boolean;30HoverFocusSpotlight: boolean;31CursorFlowGradient: boolean;32}3334const SpotLightContext = createContext<SpotLightContextType | undefined>(35undefined36);37export const useSpotlight = () => {38const context = useContext(SpotLightContext);39if (!context) {40throw new Error('useSpotlight must be used within a SpotlightProvider');41}42return context;43};44export const Spotlight = ({45children,46className,47ProximitySpotlight = true,48HoverFocusSpotlight = false,49CursorFlowGradient = true,50}: SpotlightProps) => {51return (52<SpotLightContext.Provider53value={{54ProximitySpotlight,55HoverFocusSpotlight,56CursorFlowGradient,57}}58>59<div60className={cn(61className,62'group relative z-10 rounded-md grid grid-cols-4 gap-2 '63)}64>65{children}66</div>67</SpotLightContext.Provider>68);69};70export function SpotLightItem({ children, className }: SpotlightItemProps) {71const { HoverFocusSpotlight, ProximitySpotlight, CursorFlowGradient } =72useSpotlight();73const boxWrapper = useRef(null);74const [isHovered, setIsHovered] = useState(false);75const [mousePosition, setMousePosition] = React.useState({76x: null,77y: null,78});79React.useEffect(() => {80const updateMousePosition = (ev: { clientX: any; clientY: any }) => {81setMousePosition({ x: ev.clientX, y: ev.clientY });82};83window.addEventListener('mousemove', updateMousePosition);84return () => {85window.removeEventListener('mousemove', updateMousePosition);86};87}, []);8889const [overlayColor, setOverlayColor] = useState({ x: 0, y: 0 });90const handleMouemove = ({ currentTarget, clientX, clientY }): MouseEvent => {91let { left, top } = currentTarget.getBoundingClientRect();9293const x = clientX - left;94const y = clientY - top;9596setOverlayColor({ x, y });97};98// console.log(overlayColor)99100return (101<div102onMouseMove={handleMouemove}103onMouseEnter={() => CursorFlowGradient && setIsHovered(true)}104onMouseLeave={() => setIsHovered(false)}105ref={boxWrapper}106className={cn(107className,108' relative rounded-lg justify-center items-center p-[2px] bg-[#ffffff15] overflow-hidden'109)}110>111{isHovered && (112<div113className='pointer-events-none absolute opacity-0 z-50 rounded-xl w-full h-full group-hover:opacity-100 transition duration-300 '114style={{115background: `116radial-gradient(117250px circle at ${overlayColor.x}px ${overlayColor.y}px,118rgba(255, 255, 255, 0.137),119transparent 80%120)121`,122}}123/>124)}125{HoverFocusSpotlight && (126<div127className='absolute opacity-0 group-hover:opacity-100 z-10 inset-0 bg-fixed rounded-lg'128style={{129background: `radial-gradient(circle at ${mousePosition.x}px ${mousePosition.y}px, #ffffff76 0%,transparent 20%,transparent) fixed `,130}}131></div>132)}133{ProximitySpotlight && (134<div135className='absolute inset-0 z-0 bg-fixed rounded-lg'136style={{137background: `radial-gradient(circle at ${mousePosition.x}px ${mousePosition.y}px, #ffffff6e 0%,transparent 20%,transparent) fixed`,138}}139></div>140)}141{children}142</div>143);144}145146type SpotlightCardProps = {147children: React.ReactNode;148className?: string;149};150151export function SpotlightCard({152children,153className = '',154}: SpotlightCardProps) {155return (156<div157className={`relative h-full bg-slate-800 rounded-3xl p-px before:absolute before:w-80 before:h-80 before:-left-40 before:-top-40 before:bg-slate-400 before:rounded-full before:opacity-0 before:pointer-events-none before:transition-opacity before:duration-500 before:translate-x-[var(--mouse-x)] before:translate-y-[var(--mouse-y)] before:group-hover:opacity-100 before:z-10 before:blur-[100px] after:absolute after:w-96 after:h-96 after:-left-48 after:-top-48 after:bg-indigo-500 after:rounded-full after:opacity-0 after:pointer-events-none after:transition-opacity after:duration-500 after:translate-x-[var(--mouse-x)] after:translate-y-[var(--mouse-y)] after:hover:opacity-10 after:z-30 after:blur-[100px] overflow-hidden ${className}`}158>159{children}160</div>161);162}
Control the border by chaning padding p-[2px]
from spotlight.tsx
file:
<divonMouseMove={handleMouemove}onMouseEnter={() => CursorFlowGradient && setIsHovered(true)}onMouseLeave={() => setIsHovered(false)}ref={boxWrapper}className={cn(className,' relative rounded-lg justify-center items-center p-[2px] bg-[#ffffff15] overflow-hidden')}></div>
Prop | Type | Default | Description |
---|---|---|---|
children | ReactNode | The content to be rendered inside the Spotlight component. | |
className | string | Optional CSS class for styling the Spotlight component. | |
ProximitySpotlight | boolean | true | Whether to enable proximity-based spotlight effect. |
HoverFocusSpotlight | boolean | false | Whether to enable spotlight effect on hover or focus. |
CursorFlowGradient | boolean | true | Whether to enable gradient flow based on cursor movement. |
Seamless chats, crystal-clear videos, and
premium audio quality
Experience a significant boost in your subscriber
count, achieving 3x growth.
Effortlessly connect with today's leading technologies including React, TypeScript, Next.js, Tailwind CSS, Motion, and Cypress.