Najjar\NajjarV02 461a00384c
Some checks are pending
CI/CD / test-and-build (push) Waiting to run
CI/CD / deploy (push) Blocked by required conditions
feat: add robotics showcase components and UI enhancements
- Introduced FounderSection component to highlight leadership and vision.
- Created ServicesGrid component to display various robotics services offered.
- Developed RoboticsScrollShowcase for showcasing robots with interactive elements.
- Implemented RoboticsSplineShowcase featuring a 3D Spline scene for enhanced user experience.
- Added reusable Card component for consistent styling across sections.
- Integrated ContainerScroll for animated scrolling effects in the showcase.
- Built SplineScene component for lazy loading Spline 3D scenes.
- Added Spotlight component for interactive hover effects.
- Created utility function for class name merging to streamline styling.
2026-05-20 17:46:36 +04:00

238 lines
8.3 KiB
TypeScript

'use client';
import React, { useEffect, useState } from 'react';
import Link from 'next/link';
import Image from 'next/image';
import { usePathname } from 'next/navigation';
const NAV_LINKS = [
{ label: 'Home', href: '/' },
{ label: 'Robots', href: '/robots/' },
{ label: 'Brands', href: '/brands/' },
{ label: 'Industries', href: '/industries/' },
{ label: 'About', href: '/about/' },
{ label: 'Contact', href: '/contact/' },
{ label: 'Book Demo', href: '/book-demo/' },
];
export function Navbar() {
const [scrolled, setScrolled] = useState(false);
const [mobileOpen, setMobileOpen] = useState(false);
const pathname = usePathname() || '/';
useEffect(() => {
const onScroll = () => setScrolled(window.scrollY > 16);
onScroll();
window.addEventListener('scroll', onScroll, { passive: true });
return () => window.removeEventListener('scroll', onScroll);
}, []);
useEffect(() => {
document.body.style.overflow = mobileOpen ? 'hidden' : '';
return () => {
document.body.style.overflow = '';
};
}, [mobileOpen]);
const isActive = (href: string) => {
if (href === '/') return pathname === '/' || pathname === '';
return pathname.startsWith(href.replace(/\/$/, ''));
};
return (
<>
<nav
style={{
position: 'fixed',
top: 0,
left: 0,
right: 0,
zIndex: 100,
background: scrolled ? 'rgba(5, 5, 5, 0.78)' : 'linear-gradient(180deg, rgba(5, 5, 5,0.6), rgba(5, 5, 5,0))',
backdropFilter: scrolled ? 'blur(18px)' : 'blur(8px)',
WebkitBackdropFilter: scrolled ? 'blur(18px)' : 'blur(8px)',
borderBottom: scrolled ? '1px solid rgba(39, 63, 148,0.14)' : '1px solid transparent',
transition: 'all 0.35s cubic-bezier(0.16,1,0.3,1)',
}}
>
<div
style={{
maxWidth: '1320px',
margin: '0 auto',
padding: scrolled ? '0.85rem clamp(1rem, 4vw, 2rem)' : '1.1rem clamp(1rem, 4vw, 2rem)',
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between',
gap: '1rem',
transition: 'padding 0.3s ease',
}}
>
<Link href="/" style={{ textDecoration: 'none', display: 'flex', alignItems: 'center', gap: '0.65rem', minWidth: 0 }} onClick={() => setMobileOpen(false)} aria-label="YS Lootah Robotics — Home">
<span
style={{
position: 'relative',
width: 40,
height: 40,
borderRadius: '50%',
overflow: 'hidden',
flex: 'none',
boxShadow: '0 0 18px rgba(39, 63, 148, 0.35)',
border: '1px solid rgba(39, 63, 148,0.4)',
}}
>
<Image
src="/images/brands/ys-lootah-robotics-logo.png"
alt="YS Lootah Robotics logo"
fill
sizes="40px"
style={{ objectFit: 'cover' }}
priority
/>
</span>
<span style={{ display: 'flex', flexDirection: 'column', lineHeight: 1 }}>
<span style={{ fontSize: '0.95rem', fontWeight: 700, letterSpacing: '0.16em', color: '#ffffff', textTransform: 'uppercase' }}>
YS Lootah
</span>
<span style={{ fontSize: '0.7rem', fontWeight: 500, letterSpacing: '0.32em', color: '#DEE0F0', textTransform: 'uppercase', marginTop: 3 }}>
Robotics
</span>
</span>
</Link>
<div className="nav-desktop" style={{ alignItems: 'center', gap: '1.4rem' }}>
{NAV_LINKS.map((l) => (
<Link
key={l.href}
href={l.href}
style={{
position: 'relative',
color: isActive(l.href) ? '#DEE0F0' : '#DEE0F0',
fontSize: '0.78rem',
fontWeight: 600,
textDecoration: 'none',
letterSpacing: '0.16em',
textTransform: 'uppercase',
transition: 'color 0.2s',
paddingBottom: 4,
borderBottom: isActive(l.href) ? '1px solid #DEE0F0' : '1px solid transparent',
}}
>
{l.label}
</Link>
))}
</div>
<div style={{ display: 'flex', alignItems: 'center', gap: '0.625rem' }}>
<Link
href="/configure/"
className="nav-desktop-cta btn btn-primary"
style={{ padding: '0.7rem 1.2rem', fontSize: '0.78rem' }}
>
Configure
</Link>
<button
type="button"
className="nav-mobile-toggle"
aria-label={mobileOpen ? 'Close menu' : 'Open menu'}
aria-expanded={mobileOpen}
onClick={() => setMobileOpen((s) => !s)}
style={{
width: 42,
height: 42,
borderRadius: 12,
border: '1px solid rgba(39, 63, 148,0.2)',
background: 'rgba(15, 12, 8,0.6)',
color: '#FBFBFD',
cursor: 'pointer',
display: 'none',
alignItems: 'center',
justifyContent: 'center',
padding: 0,
}}
>
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
{mobileOpen ? <path d="M6 6l12 12M6 18L18 6" /> : <path d="M4 7h16M4 12h16M4 17h16" />}
</svg>
</button>
</div>
</div>
</nav>
<div
role="dialog"
aria-modal="true"
aria-label="Mobile navigation"
style={{
position: 'fixed',
inset: 0,
zIndex: 99,
background: 'rgba(5, 5, 5,0.96)',
backdropFilter: 'blur(20px)',
WebkitBackdropFilter: 'blur(20px)',
transform: mobileOpen ? 'translateY(0)' : 'translateY(-12px)',
opacity: mobileOpen ? 1 : 0,
pointerEvents: mobileOpen ? 'auto' : 'none',
transition: 'opacity 0.25s ease, transform 0.25s ease',
padding: 'clamp(5rem, 14vw, 7rem) clamp(1.5rem, 5vw, 2rem) clamp(2rem, 6vw, 3rem)',
display: 'flex',
flexDirection: 'column',
gap: '1rem',
overflowY: 'auto',
}}
>
{NAV_LINKS.map((l) => (
<Link
key={l.href}
href={l.href}
onClick={() => setMobileOpen(false)}
style={{
fontSize: '1.5rem',
fontWeight: 500,
color: isActive(l.href) ? '#DEE0F0' : '#FBFBFD',
textDecoration: 'none',
letterSpacing: '-0.01em',
padding: '0.75rem 0',
borderBottom: '1px solid rgba(39, 63, 148,0.12)',
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
}}
>
<span>{l.label}</span>
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
<line x1="5" y1="12" x2="19" y2="12" />
<polyline points="12 5 19 12 12 19" />
</svg>
</Link>
))}
<Link
href="/configure/"
onClick={() => setMobileOpen(false)}
className="btn btn-primary"
style={{ marginTop: '1rem', justifyContent: 'center' }}
>
Configure your robot
</Link>
<Link
href="/book-demo/"
onClick={() => setMobileOpen(false)}
className="btn btn-ghost"
style={{ justifyContent: 'center' }}
>
Book a demo
</Link>
</div>
<style jsx>{`
.nav-desktop, .nav-desktop-cta { display: none !important; }
.nav-mobile-toggle { display: inline-flex !important; }
@media (min-width: 1080px) {
.nav-desktop { display: flex !important; }
.nav-desktop-cta { display: inline-flex !important; }
.nav-mobile-toggle { display: none !important; }
}
`}</style>
</>
);
}