justsisyphus 58459e692b feat(website): add layout with header, sidebar, footer and navigation
- 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
2026-01-24 14:25:05 +09:00

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>
)
}