| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283 |
- 'use client';
- import { motion } from 'motion/react';
- import type { PercentageGeometry } from '@/lib/types/action';
- interface LaserOverlayProps {
- geometry: PercentageGeometry;
- color?: string;
- duration?: number;
- }
- /**
- * Laser pointer overlay component
- *
- * Features:
- * - Smoothly flies in from the nearest corner to the element center
- * - Elegant light dot with soft breathing glow
- * - Uses percentage positioning (0-100)
- */
- export function LaserOverlay({
- geometry,
- color = '#ff3b30',
- duration: _duration = 3000,
- }: LaserOverlayProps) {
- const { centerX, centerY } = geometry;
- const startPos = {
- x: centerX > 50 ? 105 : -5,
- y: centerY > 50 ? 105 : -5,
- };
- return (
- <motion.div
- key={`laser-${centerX}-${centerY}`}
- initial={{
- opacity: 0,
- left: `${startPos.x}%`,
- top: `${startPos.y}%`,
- }}
- animate={{
- opacity: 1,
- left: `${centerX}%`,
- top: `${centerY}%`,
- }}
- exit={{
- opacity: 0,
- left: `${startPos.x}%`,
- top: `${startPos.y}%`,
- transition: { duration: 0.25, ease: [0.4, 0, 1, 1] },
- }}
- transition={{
- left: { duration: 0.5, ease: [0.22, 1, 0.36, 1] },
- top: { duration: 0.5, ease: [0.22, 1, 0.36, 1] },
- opacity: { duration: 0.15 },
- }}
- className="absolute z-[101] pointer-events-none"
- >
- <div className="relative -translate-x-1/2 -translate-y-1/2">
- {/* Ring pulse */}
- <motion.div
- animate={{ scale: [1, 2.8], opacity: [0.6, 0] }}
- transition={{
- repeat: Infinity,
- duration: 1.5,
- ease: 'easeOut',
- repeatDelay: 0.3,
- }}
- className="absolute inset-0 rounded-full"
- style={{ border: `1.5px solid ${color}` }}
- />
- {/* Light core */}
- <div
- className="w-2.5 h-2.5 rounded-full"
- style={{
- backgroundColor: color,
- boxShadow: `0 0 8px 2px ${color}60`,
- }}
- />
- </div>
- </motion.div>
- );
- }
|