kaisoft-web/src/components/Header.tsx

116 lines
5.4 KiB
TypeScript

import { useState } from 'react'
import { useTranslation } from 'react-i18next'
import { LANGUAGES } from '../i18n'
interface Props {
theme: 'light' | 'dark'
onToggleTheme: () => void
}
export default function Header({ theme, onToggleTheme }: Props) {
const { t, i18n } = useTranslation()
const [langOpen, setLangOpen] = useState(false)
const [menuOpen, setMenuOpen] = useState(false)
const currentLang = LANGUAGES.find(l => l.code === i18n.language) ?? LANGUAGES[0]
const navLinks = [
{ href: '#about', label: t('nav_about') },
{ href: '#games', label: t('nav_games') },
{ href: '#partnership', label: t('nav_partnership') },
{ href: '#contact', label: t('nav_contact') },
]
return (
<header className="sticky top-0 z-50 bg-white/80 dark:bg-gray-950/80 backdrop-blur border-b border-gray-200 dark:border-gray-800">
<div className="max-w-6xl mx-auto px-4 h-16 flex items-center justify-between">
{/* Logo */}
<a href="#" className="flex items-center font-bold text-xl tracking-tight">
<span className="text-orange-500">Kai</span><span className="text-gray-900 dark:text-white">Soft</span>
</a>
{/* Desktop nav */}
<nav className="hidden md:flex items-center gap-6">
{navLinks.map(l => (
<a key={l.href} href={l.href}
className="text-sm font-medium text-gray-600 dark:text-gray-300 hover:text-orange-500 dark:hover:text-orange-400 transition-colors">
{l.label}
</a>
))}
</nav>
{/* Controls */}
<div className="flex items-center gap-2">
{/* Language selector */}
<div className="relative">
<button
onClick={() => setLangOpen(o => !o)}
className="flex items-center gap-1 px-3 py-1.5 rounded-lg text-sm font-medium text-gray-600 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-800 transition-colors">
<span>{currentLang.label}</span>
<svg className="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7" />
</svg>
</button>
{langOpen && (
<div className="absolute right-0 mt-1 w-44 bg-white dark:bg-gray-900 border border-gray-200 dark:border-gray-700 rounded-xl shadow-lg overflow-hidden z-50">
<div className="max-h-72 overflow-y-auto">
{LANGUAGES.map(lang => (
<button key={lang.code}
onClick={() => { i18n.changeLanguage(lang.code); setLangOpen(false) }}
className={`w-full text-left px-4 py-2.5 text-sm transition-colors
${lang.code === i18n.language
? 'bg-orange-50 dark:bg-orange-900/20 text-orange-600 dark:text-orange-400 font-semibold'
: 'text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-800'}`}>
{lang.label}
</button>
))}
</div>
</div>
)}
</div>
{/* Dark mode toggle */}
<button onClick={onToggleTheme}
className="p-2 rounded-lg text-gray-500 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-800 transition-colors"
aria-label="Toggle theme">
{theme === 'dark' ? (
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2}
d="M12 3v1m0 16v1m9-9h-1M4 12H3m15.364-6.364l-.707.707M6.343 17.657l-.707.707M17.657 17.657l-.707-.707M6.343 6.343l-.707-.707M12 8a4 4 0 100 8 4 4 0 000-8z" />
</svg>
) : (
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2}
d="M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z" />
</svg>
)}
</button>
{/* Mobile menu toggle */}
<button onClick={() => setMenuOpen(o => !o)}
className="md:hidden p-2 rounded-lg text-gray-500 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-800 transition-colors">
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
{menuOpen
? <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
: <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 6h16M4 12h16M4 18h16" />}
</svg>
</button>
</div>
</div>
{/* Mobile nav */}
{menuOpen && (
<nav className="md:hidden border-t border-gray-200 dark:border-gray-800 bg-white dark:bg-gray-950">
{navLinks.map(l => (
<a key={l.href} href={l.href}
onClick={() => setMenuOpen(false)}
className="block px-4 py-3 text-sm font-medium text-gray-700 dark:text-gray-300 hover:text-orange-500 dark:hover:text-orange-400 hover:bg-gray-50 dark:hover:bg-gray-900 transition-colors">
{l.label}
</a>
))}
</nav>
)}
</header>
)
}