Test-Generate-123/Template-03/src/components/Header.tsx
2026-05-13 22:38:24 +00:00

172 lines
7.5 KiB
TypeScript

import { Link } from 'react-router-dom';
import { Search, Menu, X, Globe, Twitter, Instagram, Linkedin, Youtube, Bookmark, Zap } from 'lucide-react';
import { useState, useEffect } from 'react';
import { motion, AnimatePresence } from 'motion/react';
import { useLanguage } from '../contexts/LanguageContext';
import { translations } from '../constants';
import SearchOverlay from './SearchOverlay';
import { useBookmarks } from '../contexts/BookmarksContext';
import { cn } from '../lib/utils';
interface HeaderProps {
onSearchOpen: () => void;
}
export default function Header({ onSearchOpen }: HeaderProps) {
const [isMenuOpen, setIsMenuOpen] = useState(false);
const [scrolled, setScrolled] = useState(false);
const { lang, setLang } = useLanguage();
const { bookmarks } = useBookmarks();
const t = translations[lang];
useEffect(() => {
const handleScroll = () => setScrolled(window.scrollY > 20);
window.addEventListener('scroll', handleScroll);
return () => window.removeEventListener('scroll', handleScroll);
}, []);
const categories = [
{ name: 'Estratégia', slug: 'estrategia' },
{ name: 'Técnico', slug: 'tecnico' },
{ name: 'Autoridade', slug: 'autoridade' },
{ name: 'Negócios', slug: 'negocios' }
];
return (
<header className={cn(
"fixed top-0 z-50 w-full transition-all duration-300",
scrolled ? "bg-black/95 backdrop-blur-3xl border-b border-brand/10 py-2 shadow-xl" : "bg-transparent py-4"
)}>
<div className="mx-auto max-w-[1400px] px-6 lg:px-12">
<div className="flex h-14 items-center justify-between">
<div className="flex items-center gap-12">
<Link to="/" className="flex items-center gap-3 group">
<div className="h-8 w-8 bg-brand flex items-center justify-center text-black group-hover:bg-brand-light transition-all skew-x-[-6deg]">
<Zap size={16} fill="currentColor" className="skew-x-[6deg]" />
</div>
<span className="font-display text-xl font-black tracking-tight text-white uppercase italic">
NODE<span className="text-brand">_IDX</span>
</span>
</Link>
<nav className="hidden lg:flex items-center gap-8">
{categories.map((cat) => (
<Link
key={cat.slug}
to={`/categoria/${cat.slug}`}
className="text-[10px] font-mono font-black uppercase tracking-[0.2em] text-slate-500 hover:text-brand transition-colors relative group"
>
{cat.name}
<span className="absolute -bottom-1 left-0 w-0 h-px bg-brand transition-all group-hover:w-full" />
</Link>
))}
</nav>
</div>
<div className="flex items-center gap-3">
<div className="hidden xl:flex items-center gap-2 pr-6 border-r border-white/10 text-[8px] font-mono font-black text-slate-700 uppercase tracking-[0.3em]">
<span className="h-1 w-1 bg-brand animate-pulse" />
Operational
</div>
{/* Language Switcher */}
<button
onClick={() => setLang(lang === 'pt-br' ? 'en' : 'pt-br')}
className="hidden sm:flex items-center gap-3 px-5 py-2 hover:bg-brand/5 border border-white/5 hover:border-brand/30 transition-all group skew-x-[-12deg]"
>
<Globe size={14} className="text-slate-400 group-hover:text-brand transition-colors skew-x-[12deg]" />
<span className="text-[10px] font-mono font-black uppercase tracking-widest text-slate-400 group-hover:text-white skew-x-[12deg]">
{lang === 'pt-br' ? 'PT' : 'EN'}
</span>
</button>
<button
className="p-3 text-slate-400 hover:text-brand hover:bg-brand/5 border border-white/5 hover:border-brand/20 transition-all skew-x-[-12deg]"
onClick={onSearchOpen}
>
<Search size={18} className="skew-x-[12deg]" />
</button>
<Link
to="/leituras-salvas"
className="relative p-3 text-slate-400 hover:text-brand hover:bg-brand/5 border border-white/5 hover:border-brand/20 transition-all skew-x-[-12deg]"
title="Leituras Salvas"
>
<Bookmark size={18} className="skew-x-[12deg]" />
<AnimatePresence>
{bookmarks.length > 0 && (
<motion.span
initial={{ scale: 0 }}
animate={{ scale: 1 }}
exit={{ scale: 0 }}
className="absolute -top-1 -right-1 h-5 w-5 bg-brand text-black text-[9px] font-black flex items-center justify-center border border-black skew-x-[12deg]"
>
{bookmarks.length}
</motion.span>
)}
</AnimatePresence>
</Link>
<button
className="lg:hidden p-3 text-white hover:bg-brand/10 border border-white/10 transition-all skew-x-[-12deg]"
onClick={() => setIsMenuOpen(!isMenuOpen)}
>
<div className="skew-x-[12deg]">
{isMenuOpen ? <X size={20} /> : <Menu size={20} />}
</div>
</button>
</div>
</div>
</div>
<AnimatePresence>
{isMenuOpen && (
<motion.div
initial={{ height: 0, opacity: 0 }}
animate={{ height: 'auto', opacity: 1 }}
exit={{ height: 0, opacity: 0 }}
className="lg:hidden bg-black border-t border-brand/20 overflow-hidden"
>
<div className="flex flex-col gap-10 p-10 font-mono">
<div className="flex flex-col gap-6">
{categories.map((cat) => (
<Link
key={cat.slug}
to={`/categoria/${cat.slug}`}
className="text-4xl font-display font-black text-white hover:text-brand transition-colors uppercase italic"
onClick={() => setIsMenuOpen(false)}
>
{" >> "} {cat.name}
</Link>
))}
<div className="h-px w-full bg-white/5 my-4" />
<Link
to="/contato"
className="text-xl font-black uppercase tracking-[0.4em] text-slate-600 hover:text-brand transition-colors"
onClick={() => setIsMenuOpen(false)}
>
Contact_Protocol
</Link>
<Link
to="/arquivo"
className="text-xl font-black uppercase tracking-[0.4em] text-slate-600 hover:text-brand transition-colors"
onClick={() => setIsMenuOpen(false)}
>
Archive_Files
</Link>
</div>
<div className="pt-10 border-t border-white/5 flex items-center justify-start gap-4">
{[Twitter, Linkedin, Instagram].map((Icon, i) => (
<a key={i} href="#" className="h-14 w-14 flex items-center justify-center bg-white/5 text-slate-400 hover:text-brand hover:border-brand/40 transition-all border border-white/5 skew-x-[-12deg]">
<Icon size={20} className="skew-x-[12deg]" />
</a>
))}
</div>
</div>
</motion.div>
)}
</AnimatePresence>
</header>
);
}