feat: add robotics components and data structures
CI/CD / test-and-build (push) Waiting to run
CI/CD / deploy (push) Blocked by required conditions

- Introduced RobotProductCard component for displaying robot details.
- Added WhyUs component highlighting key reasons for choosing our robotics solutions.
- Implemented CursorSpotlight for enhanced user interaction.
- Created GlassPanel for a stylish UI element.
- Developed MotionSection for animated section visibility.
- Added PremiumButton for versatile button options.
- Established data structures for industries and robots, including detailed specifications and use cases.
- Included utility functions for retrieving robots by slug and category.
This commit is contained in:
Najjar\NajjarV02
2026-05-20 17:22:47 +04:00
parent 2eac53dac3
commit 92cf4aba3b
87 changed files with 6887 additions and 1430 deletions
+62
View File
@@ -0,0 +1,62 @@
'use client';
import { useEffect, useRef, useState } from 'react';
type Props = {
color?: string;
size?: number;
className?: string;
};
export function CursorSpotlight({ color = 'rgba(196, 162, 101, 0.18)', size = 520, className = '' }: Props) {
const ref = useRef<HTMLDivElement | null>(null);
const [pos, setPos] = useState<{ x: number; y: number } | null>(null);
const [enabled, setEnabled] = useState(false);
useEffect(() => {
const finePointer = window.matchMedia('(pointer: fine)').matches;
const reduced = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
if (!finePointer || reduced) return;
setEnabled(true);
const el = ref.current?.parentElement;
if (!el) return;
let raf = 0;
const onMove = (e: MouseEvent) => {
const rect = el.getBoundingClientRect();
const x = e.clientX - rect.left;
const y = e.clientY - rect.top;
cancelAnimationFrame(raf);
raf = requestAnimationFrame(() => setPos({ x, y }));
};
const onLeave = () => setPos(null);
el.addEventListener('mousemove', onMove);
el.addEventListener('mouseleave', onLeave);
return () => {
el.removeEventListener('mousemove', onMove);
el.removeEventListener('mouseleave', onLeave);
cancelAnimationFrame(raf);
};
}, []);
if (!enabled) return null;
return (
<div
ref={ref}
aria-hidden
className={className}
style={{
position: 'absolute',
inset: 0,
pointerEvents: 'none',
opacity: pos ? 1 : 0,
transition: 'opacity 0.4s ease',
background: pos
? `radial-gradient(${size}px ${size}px at ${pos.x}px ${pos.y}px, ${color}, transparent 70%)`
: 'transparent',
zIndex: 1,
}}
/>
);
}