Coloca las secciones, datos, componentes, servicios y tipos dentro de sus dominios de app y normaliza los imports con el alias @. Co-authored-by: Copilot <[email protected]>
146 lines
5.6 KiB
TypeScript
146 lines
5.6 KiB
TypeScript
'use client';
|
|
import { useState, useEffect } from 'react';
|
|
import { motion, AnimatePresence } from 'framer-motion';
|
|
import { Menu, X } from 'lucide-react';
|
|
import Link from 'next/link';
|
|
import { usePathname } from 'next/navigation';
|
|
import { Button } from './Button';
|
|
import { pageLinks } from '@/app/home/data/navigationData';
|
|
|
|
export const Navbar = () => {
|
|
const [scrolled, setScrolled] = useState(false);
|
|
const [menuOpen, setMenuOpen] = useState(false);
|
|
const rawPathname = usePathname();
|
|
const pathname = rawPathname?.replace(/\/$/, '') || '/';
|
|
|
|
const scrollToContact = () => {
|
|
setMenuOpen(false);
|
|
const el = document.getElementById('contacto');
|
|
if (el) el.scrollIntoView({ behavior: 'smooth' });
|
|
else window.location.href = '/#contacto';
|
|
};
|
|
|
|
useEffect(() => {
|
|
const onScroll = () => setScrolled(window.scrollY > 80);
|
|
window.addEventListener('scroll', onScroll, { passive: true });
|
|
return () => window.removeEventListener('scroll', onScroll);
|
|
}, []);
|
|
|
|
useEffect(() => {
|
|
setMenuOpen(false);
|
|
}, [pathname]);
|
|
|
|
return (
|
|
<>
|
|
<motion.header
|
|
className="fixed top-0 left-0 right-0 z-50"
|
|
initial={{ y: -72, opacity: 0 }}
|
|
animate={{ y: 0, opacity: 1 }}
|
|
transition={{ duration: 0.65, ease: [0.22, 1, 0.36, 1] }}
|
|
role="banner"
|
|
>
|
|
<div
|
|
style={{
|
|
background: scrolled ? 'rgba(255,255,255,0.97)' : 'transparent',
|
|
borderBottom: scrolled ? '1px solid rgba(0,0,0,0.08)' : '1px solid transparent',
|
|
backdropFilter: scrolled ? 'blur(16px)' : 'none',
|
|
WebkitBackdropFilter: scrolled ? 'blur(16px)' : 'none',
|
|
transition: 'background 200ms, border-color 200ms',
|
|
}}
|
|
>
|
|
<div className="mx-auto flex max-w-7xl items-center justify-between px-8 py-4 md:px-14">
|
|
<Link href="/" aria-label="Rynext Technologies — inicio" className="flex items-center gap-2.5">
|
|
<img
|
|
src="/icons/Logo_negro.svg"
|
|
alt="Logo"
|
|
className="h-11 w-11 shrink-0 object-contain"
|
|
/>
|
|
<div className="flex flex-col leading-none">
|
|
<span style={{ fontFamily: "'Quicksand', sans-serif", fontWeight: 700, fontSize: 19, letterSpacing: '-0.01em', color: '#111827' }}>
|
|
Rynext
|
|
</span>
|
|
<span style={{ fontFamily: "'Quicksand', sans-serif", fontWeight: 500, fontSize: 12, letterSpacing: '0.04em', color: '#6b7280' }}>
|
|
Technologies
|
|
</span>
|
|
</div>
|
|
</Link>
|
|
|
|
{/* Desktop nav */}
|
|
<nav className="hidden items-center gap-8 md:flex" aria-label="Navegación principal">
|
|
{pageLinks.filter(l => l.href !== '/privacidad').map((link) => {
|
|
const active = pathname === link.href;
|
|
return (
|
|
<Link
|
|
key={link.href}
|
|
href={link.href}
|
|
className="text-sm font-semibold transition-colors"
|
|
style={{ color: active ? '#0a0a0a' : '#6a6866', textDecoration: 'none' }}
|
|
onMouseEnter={(e) => (e.currentTarget.style.color = '#0a0a0a')}
|
|
onMouseLeave={(e) => (e.currentTarget.style.color = active ? '#0a0a0a' : '#6a6866')}
|
|
>
|
|
{link.label}
|
|
</Link>
|
|
);
|
|
})}
|
|
|
|
<button
|
|
onClick={scrollToContact}
|
|
className="inline-flex items-center gap-2 px-5 py-2.5 text-sm font-bold text-white transition hover:scale-[1.02] hover:opacity-90"
|
|
style={{ background: '#3b82f6', border: 'none', cursor: 'pointer', borderRadius: 3 }}
|
|
>
|
|
Hablemos
|
|
</button>
|
|
</nav>
|
|
|
|
{/* Mobile menu button */}
|
|
<button
|
|
onClick={() => setMenuOpen((v) => !v)}
|
|
className="flex items-center justify-center rounded p-2 md:hidden"
|
|
style={{ color: '#0a0a0a', background: 'none', border: 'none', cursor: 'pointer' }}
|
|
aria-label={menuOpen ? 'Cerrar menú' : 'Abrir menú'}
|
|
aria-expanded={menuOpen}
|
|
>
|
|
{menuOpen ? <X size={22} /> : <Menu size={22} />}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</motion.header>
|
|
|
|
{/* Mobile menu */}
|
|
<AnimatePresence>
|
|
{menuOpen && (
|
|
<motion.div
|
|
initial={{ opacity: 0, y: -8 }}
|
|
animate={{ opacity: 1, y: 0 }}
|
|
exit={{ opacity: 0, y: -8 }}
|
|
transition={{ duration: 0.2 }}
|
|
className="fixed inset-x-0 top-[73px] z-40 px-8 py-6 md:hidden"
|
|
style={{ background: '#ffffff', borderBottom: '1px solid #dddbd5' }}
|
|
role="dialog"
|
|
aria-modal="true"
|
|
aria-label="Menú de navegación"
|
|
>
|
|
<nav className="flex flex-col gap-5">
|
|
{pageLinks.map((link) => (
|
|
<Link
|
|
key={link.href}
|
|
href={link.href}
|
|
className="text-left text-base font-semibold"
|
|
style={{ color: pathname === link.href ? '#0a0a0a' : '#6a6866', textDecoration: 'none' }}
|
|
>
|
|
{link.label}
|
|
</Link>
|
|
))}
|
|
<div className="pt-2">
|
|
<Button onClick={scrollToContact} className="w-full py-3 text-center text-sm font-bold text-white">
|
|
Hablemos
|
|
</Button>
|
|
</div>
|
|
</nav>
|
|
</motion.div>
|
|
)}
|
|
</AnimatePresence>
|
|
</>
|
|
);
|
|
};
|