- Create Header component with logo, nav, theme toggle, language switcher - Create Sidebar component with doc navigation from config - Create Footer component - Create MobileNav component with hamburger menu - Create navigation config file (docsConfig) - Integrate all layout components into [locale]/layout.tsx - Add framer-motion for mobile nav animations - All tests passing, build successful
68 lines
2.3 KiB
TypeScript
68 lines
2.3 KiB
TypeScript
"use client"
|
|
|
|
import * as React from "react"
|
|
import { Link } from "@/i18n/routing"
|
|
import { useTranslations } from "next-intl"
|
|
import { ThemeToggle } from "@/components/theme-toggle"
|
|
import LanguageSwitcher from "@/components/LanguageSwitcher"
|
|
import { docsConfig } from "@/config/navigation"
|
|
import { Menu, X } from "lucide-react"
|
|
import { motion, AnimatePresence } from "framer-motion"
|
|
import { MobileNav } from "./mobile-nav"
|
|
|
|
export function Header() {
|
|
const t = useTranslations("Navigation")
|
|
const [isMobileMenuOpen, setIsMobileMenuOpen] = React.useState(false)
|
|
|
|
return (
|
|
<header className="sticky top-0 z-50 w-full border-b bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60">
|
|
<div className="container flex h-14 items-center px-4 md:px-8">
|
|
<div className="mr-4 hidden md:flex">
|
|
<Link href="/" className="mr-6 flex items-center space-x-2">
|
|
<span className="hidden font-bold sm:inline-block">
|
|
Oh My OpenCode
|
|
</span>
|
|
</Link>
|
|
<nav className="flex items-center space-x-6 text-sm font-medium">
|
|
{docsConfig.mainNav.map((item) => (
|
|
<Link
|
|
key={item.href}
|
|
href={item.href!}
|
|
className="transition-colors hover:text-foreground/80 text-foreground/60"
|
|
>
|
|
{item.title}
|
|
</Link>
|
|
))}
|
|
</nav>
|
|
</div>
|
|
|
|
<div className="flex flex-1 items-center justify-between space-x-2 md:justify-end">
|
|
<div className="w-full flex-1 md:w-auto md:flex-none">
|
|
</div>
|
|
<nav className="flex items-center space-x-2">
|
|
<LanguageSwitcher />
|
|
<ThemeToggle />
|
|
<button
|
|
type="button"
|
|
className="md:hidden p-2"
|
|
onClick={() => setIsMobileMenuOpen(!isMobileMenuOpen)}
|
|
aria-label="Toggle menu"
|
|
>
|
|
{isMobileMenuOpen ? <X size={20} /> : <Menu size={20} />}
|
|
</button>
|
|
</nav>
|
|
</div>
|
|
</div>
|
|
|
|
<AnimatePresence>
|
|
{isMobileMenuOpen && (
|
|
<MobileNav
|
|
open={isMobileMenuOpen}
|
|
setOpen={setIsMobileMenuOpen}
|
|
/>
|
|
)}
|
|
</AnimatePresence>
|
|
</header>
|
|
)
|
|
}
|