Import source: src/components/Header

Import the existing local project snapshot. This commit organizes existing files; it does not represent newly developed functionality.
This commit is contained in:
arsam
2026-09-18 23:05:51 +03:30
parent f077a35782
commit 211b543414
+145
View File
@@ -0,0 +1,145 @@
'use client';
import { useState, useEffect } from 'react';
import { usePathname, useRouter } from '@/i18n/routing';
import { useLocale, useTranslations } from 'next-intl';
import { Sun, Moon, Globe, Menu, X } from 'lucide-react';
export default function Header() {
const t = useTranslations('Header');
const locale = useLocale();
const pathname = usePathname();
const router = useRouter();
const [theme, setTheme] = useState<'light' | 'dark'>('dark');
const [mobileMenuOpen, setMobileMenuOpen] = useState(false);
useEffect(() => {
// Check local storage or document class to sync initial state
const isDark = document.documentElement.classList.contains('dark');
setTheme(isDark ? 'dark' : 'light');
}, []);
const toggleTheme = () => {
if (theme === 'dark') {
document.documentElement.classList.remove('dark');
localStorage.setItem('theme', 'light');
setTheme('light');
} else {
document.documentElement.classList.add('dark');
localStorage.setItem('theme', 'dark');
setTheme('dark');
}
};
const toggleLanguage = () => {
const nextLocale = locale === 'en' ? 'fa' : 'en';
router.replace(pathname, { locale: nextLocale });
};
const navItems = [
{ key: 'about', href: '#about' },
{ key: 'expertise', href: '#expertise' },
{ key: 'projects', href: '#projects' },
{ key: 'writing', href: '#writing' },
{ key: 'contact', href: '#contact' },
];
return (
<header className="sticky top-0 z-50 w-full border-b border-sand/30 dark:border-charcoal/50 bg-warm-white/80 dark:bg-near-black/80 backdrop-blur-md transition-colors duration-300">
<div className="max-w-[1200px] mx-auto px-6 h-16 flex items-center justify-between">
{/* Name / Logo */}
<a
href="#"
className="text-lg font-bold tracking-tight text-teal-brand hover:opacity-85 transition-opacity"
>
{locale === 'fa' ? 'آرسام صباغ' : 'Arsam Sabbagh'}
</a>
{/* Desktop Nav Links */}
<nav className="hidden md:flex items-center space-x-6 rtl:space-x-reverse">
{navItems.map((item) => (
<a
key={item.key}
href={item.href}
className="text-sm font-medium text-charcoal/70 dark:text-warm-white/70 hover:text-teal-brand dark:hover:text-teal-brand transition-colors"
>
{t(`nav.${item.key}`)}
</a>
))}
</nav>
{/* Action Controls */}
<div className="hidden md:flex items-center space-x-4 rtl:space-x-reverse">
{/* Language Switcher */}
<button
onClick={toggleLanguage}
className="flex items-center gap-1.5 px-3 py-1.5 rounded-full border border-sand dark:border-charcoal text-xs font-semibold hover:border-teal-brand dark:hover:border-teal-brand hover:text-teal-brand transition-all cursor-pointer"
aria-label="Toggle language"
>
<Globe className="w-3.5 h-3.5" />
<span>{locale === 'en' ? 'فارسی' : 'English'}</span>
</button>
{/* Theme Switcher */}
<button
onClick={toggleTheme}
className="p-2 rounded-full border border-sand dark:border-charcoal hover:border-teal-brand dark:hover:border-teal-brand hover:text-teal-brand transition-all cursor-pointer"
aria-label="Toggle theme"
>
{theme === 'dark' ? (
<Sun className="w-4 h-4 text-terracotta" />
) : (
<Moon className="w-4 h-4 text-teal-brand" />
)}
</button>
</div>
{/* Mobile controls & toggle */}
<div className="flex items-center space-x-2 rtl:space-x-reverse md:hidden">
<button
onClick={toggleTheme}
className="p-2 rounded-full border border-sand dark:border-charcoal hover:text-teal-brand cursor-pointer"
aria-label="Toggle theme"
>
{theme === 'dark' ? <Sun className="w-4 h-4 text-terracotta" /> : <Moon className="w-4 h-4 text-teal-brand" />}
</button>
<button
onClick={toggleLanguage}
className="p-2 rounded-full border border-sand dark:border-charcoal hover:text-teal-brand cursor-pointer"
aria-label="Toggle language"
>
<Globe className="w-4 h-4" />
</button>
<button
onClick={() => setMobileMenuOpen(!mobileMenuOpen)}
className="p-2 text-charcoal dark:text-warm-white cursor-pointer"
aria-label="Toggle menu"
>
{mobileMenuOpen ? <X className="w-5 h-5" /> : <Menu className="w-5 h-5" />}
</button>
</div>
</div>
{/* Mobile Menu Panel */}
{mobileMenuOpen && (
<div className="md:hidden border-t border-sand/20 dark:border-charcoal/50 bg-warm-white dark:bg-near-black w-full py-4 px-6 animate-in fade-in slide-in-from-top-4 duration-200">
<nav className="flex flex-col space-y-4">
{navItems.map((item) => (
<a
key={item.key}
href={item.href}
onClick={() => setMobileMenuOpen(false)}
className="text-base font-semibold text-charcoal/80 dark:text-warm-white/80 hover:text-teal-brand dark:hover:text-teal-brand transition-colors"
>
{t(`nav.${item.key}`)}
</a>
))}
</nav>
</div>
)}
</header>
);
}