Files
Landing/src/app/components/Navbar.tsx
T
Emmanuel RojasandCopilot 794a659369 refactor: reorganizar modulos dentro de app
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]>
2026-10-02 15:47:34 -05:00

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>
</>
);
};