generated from autoblog/Seo
172 lines
7.5 KiB
TypeScript
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>
|
|
);
|
|
}
|