Goal Tracking
Analytics Dashboard
Task Management
Team Collaboration
Performance Metrics
Monitor individual and team performance with detailed metrics and KPIs. Identify areas for improvement and recognize outstanding achievements.
Installation
Install the following dependencies:
pnpm add motion
Create a file at components/motions/spotlight-card.tsx
and paste the given code.
'use client'
import { cn } from '@/lib/utils'
import React, {
useRef,
useState,
// MouseEvent,
useContext,
createContext,
} from 'react'
// interface MousePosition {
// x: number
// y: number
// }
/*eslint-disable @typescript-eslint/no-explicit-any*/
interface SpotlightProps {
children: React.ReactNode
className?: string
ProximitySpotlight?: boolean
HoverFocusSpotlight?: boolean
CursorFlowGradient?: boolean
}
interface SpotlightItemProps {
children: React.ReactNode
className?: string
}
interface SpotLightContextType {
ProximitySpotlight: boolean
HoverFocusSpotlight: boolean
CursorFlowGradient: boolean
}
const SpotLightContext = createContext<SpotLightContextType | undefined>(
undefined
)
export const useSpotlight = () => {
const context = useContext(SpotLightContext)
if (!context) {
throw new Error('useSpotlight must be used within a SpotlightProvider')
}
return context
}
export const Spotlight = ({
children,
className,
ProximitySpotlight = true,
HoverFocusSpotlight = false,
CursorFlowGradient = true,
}: SpotlightProps) => {
return (
<SpotLightContext.Provider
value={{
ProximitySpotlight,
HoverFocusSpotlight,
CursorFlowGradient,
}}
>
<div className={cn('group relative z-10 rounded-md ', className)}>
{children}
</div>
</SpotLightContext.Provider>
)
}
export function SpotLightItem({ children, className }: SpotlightItemProps) {
const { HoverFocusSpotlight, ProximitySpotlight, CursorFlowGradient } =
useSpotlight()
const boxWrapper = useRef(null)
const [isHovered, setIsHovered] = useState(false)
const [mousePosition, setMousePosition] = React.useState({
x: null,
y: null,
})
React.useEffect(() => {
const updateMousePosition = (ev: { clientX: any; clientY: any }) => {
setMousePosition({ x: ev.clientX, y: ev.clientY })
}
window.addEventListener('mousemove', updateMousePosition)
return () => {
window.removeEventListener('mousemove', updateMousePosition)
}
}, [])
const [overlayColor, setOverlayColor] = useState({ x: 0, y: 0 })
const handleMouemove = (e: React.MouseEvent<HTMLDivElement>): void => {
const { currentTarget, clientX, clientY } = e;
const { left, top } = currentTarget.getBoundingClientRect()
const x = clientX - left
const y = clientY - top
setOverlayColor({ x, y })
}
// console.log(overlayColor)
return (
<div
onMouseMove={handleMouemove}
onMouseEnter={() => CursorFlowGradient && setIsHovered(true)}
onMouseLeave={() => setIsHovered(false)}
ref={boxWrapper}
className={cn(
className,
' relative rounded-lg p-[2px] bg-[#ffffff15] overflow-hidden'
)}
>
{isHovered && (
<div
className="pointer-events-none absolute opacity-0 z-50 rounded-xl w-full h-full group-hover:opacity-100 transition duration-300 "
style={{
background: `
radial-gradient(
250px circle at ${overlayColor.x}px ${overlayColor.y}px,
rgba(255, 255, 255, 0.137),
transparent 80%
)
`,
}}
/>
)}
{HoverFocusSpotlight && (
<div
className="absolute opacity-0 group-hover:opacity-100 z-10 inset-0 bg-fixed rounded-lg"
style={{
background: `radial-gradient(circle at ${mousePosition.x}px ${mousePosition.y}px, #ffffff76 0%,transparent 20%,transparent) fixed `,
}}
></div>
)}
{ProximitySpotlight && (
<div
className="absolute inset-0 z-0 bg-fixed rounded-lg"
style={{
background: `radial-gradient(circle at ${mousePosition.x}px ${mousePosition.y}px, #ffffff6e 0%,transparent 20%,transparent) fixed`,
}}
></div>
)}
{children}
</div>
)
}
type SpotlightCardProps = {
children: React.ReactNode
className?: string
}
export function SpotlightCard({
children,
className = '',
}: SpotlightCardProps) {
return (
<div
className={`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}`}
>
{children}
</div>
)
}
/*eslint-enable @typescript-eslint/no-explicit-any*/