All checks were successful
PR Checks / lint-and-build (pull_request) Successful in 21s
Build and Deploy Next.js Blog to Production / 🔍 Code Quality Checks (push) Successful in 16s
Build and Deploy Next.js Blog to Production / 🏗️ Build and Push Docker Image (push) Successful in 1m4s
Build and Deploy Next.js Blog to Production / 🚀 Deploy to Production (push) Successful in 55s
100 lines
3.7 KiB
TypeScript
100 lines
3.7 KiB
TypeScript
'use client'
|
|
|
|
import { useState, useEffect } from 'react'
|
|
import { Link } from '@/i18n/navigation'
|
|
import Image from 'next/image'
|
|
import { ThemeToggle } from '@/components/theme-toggle'
|
|
import { GlitchButton } from '@/components/effects/glitch-button'
|
|
import LanguageSwitcher from './LanguageSwitcher'
|
|
import { useLocale, useTranslations } from 'next-intl'
|
|
|
|
export function HeroHeader() {
|
|
const locale = useLocale()
|
|
const t = useTranslations('Home')
|
|
const tNav = useTranslations('Navigation')
|
|
|
|
const terminalVersion = t('terminalVersion')
|
|
const blogLabel = tNav('blog')
|
|
const aboutLabel = tNav('about')
|
|
|
|
const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false)
|
|
const [isMobile, setIsMobile] = useState(false)
|
|
useEffect(() => {
|
|
const checkMobile = () => setIsMobile(window.innerWidth < 768)
|
|
checkMobile()
|
|
window.addEventListener('resize', checkMobile)
|
|
return () => window.removeEventListener('resize', checkMobile)
|
|
}, [])
|
|
|
|
return (
|
|
<div className="mb-8 border-b-2 border-slate-300 dark:border-slate-800 pb-4">
|
|
<div className="flex items-center justify-between">
|
|
<div className="flex items-center gap-3">
|
|
<Image src="/logo.png" alt="Logo" width={32} height={32} className="opacity-80" />
|
|
<span className="font-mono text-xs text-slate-500 uppercase tracking-widest">
|
|
{terminalVersion}
|
|
</span>
|
|
</div>
|
|
|
|
{!isMobile && (
|
|
<div className="flex gap-4 items-center">
|
|
<Link
|
|
href="/blog"
|
|
className="font-mono text-xs text-slate-600 dark:text-slate-400 uppercase tracking-wider hover:text-cyan-600 dark:hover:text-cyan-400"
|
|
>
|
|
[{blogLabel}]
|
|
</Link>
|
|
<Link
|
|
href="/about"
|
|
className="font-mono text-xs text-slate-600 dark:text-slate-400 uppercase tracking-wider hover:text-cyan-600 dark:hover:text-cyan-400"
|
|
>
|
|
[{aboutLabel}]
|
|
</Link>
|
|
<ThemeToggle />
|
|
</div>
|
|
)}
|
|
|
|
{isMobile && (
|
|
<div>
|
|
<GlitchButton
|
|
variant="subtle"
|
|
glitchColor="cyan"
|
|
onClick={() => setIsMobileMenuOpen(!isMobileMenuOpen)}
|
|
className="font-mono text-xs uppercase tracking-wider px-3 py-2 border-2 border-slate-400 dark:border-slate-700 bg-white dark:bg-slate-800 text-slate-600 dark:text-slate-300"
|
|
aria-label="Toggle menu"
|
|
aria-expanded={isMobileMenuOpen}
|
|
>
|
|
// {isMobileMenuOpen ? 'X' : 'MENU'}
|
|
</GlitchButton>
|
|
</div>
|
|
)}
|
|
</div>
|
|
|
|
{isMobileMenuOpen && isMobile && (
|
|
<div className="mt-4 pt-4 border-t-2 border-slate-300 dark:border-slate-800">
|
|
<div className="flex flex-col gap-3">
|
|
<Link
|
|
href="/blog"
|
|
className="font-mono text-xs text-slate-600 dark:text-slate-400 uppercase tracking-wider hover:text-cyan-600 dark:hover:text-cyan-400 px-3 py-2 border-2 border-slate-300 dark:border-slate-700"
|
|
onClick={() => setIsMobileMenuOpen(false)}
|
|
>
|
|
[{blogLabel}]
|
|
</Link>
|
|
<Link
|
|
href="/about"
|
|
className="font-mono text-xs text-slate-600 dark:text-slate-400 uppercase tracking-wider hover:text-cyan-600 dark:hover:text-cyan-400 px-3 py-2 border-2 border-slate-300 dark:border-slate-700"
|
|
onClick={() => setIsMobileMenuOpen(false)}
|
|
>
|
|
[{aboutLabel}]
|
|
</Link>
|
|
<div className="flex items-center gap-4 px-4 py-2">
|
|
<ThemeToggle />
|
|
<LanguageSwitcher />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
)
|
|
}
|