From bf5ba0a5577e198b1d08a2f2d1ee1419a800e7bf Mon Sep 17 00:00:00 2001 From: Chris Tate Date: Mon, 26 Jan 2026 14:09:17 -0600 Subject: [PATCH] header (#283) --- docs/src/app/layout.tsx | 17 +++-- docs/src/components/header.tsx | 89 ++++++++++++++++++++++ docs/src/components/mobile-nav-context.tsx | 45 +++++++++++ docs/src/components/sidebar.tsx | 77 ++----------------- 4 files changed, 152 insertions(+), 76 deletions(-) create mode 100644 docs/src/components/header.tsx create mode 100644 docs/src/components/mobile-nav-context.tsx diff --git a/docs/src/app/layout.tsx b/docs/src/app/layout.tsx index a1c2c04..9f73c0d 100644 --- a/docs/src/app/layout.tsx +++ b/docs/src/app/layout.tsx @@ -1,6 +1,8 @@ import type { Metadata } from "next"; import { Geist, Geist_Mono } from "next/font/google"; import "./globals.css"; +import { MobileNavProvider } from "@/components/mobile-nav-context"; +import { Header } from "@/components/header"; import { Sidebar } from "@/components/sidebar"; const geist = Geist({ @@ -28,12 +30,15 @@ export default function RootLayout({ -
- -
- {children} -
-
+ +
+
+ +
+ {children} +
+
+ ); diff --git a/docs/src/components/header.tsx b/docs/src/components/header.tsx new file mode 100644 index 0000000..0b03757 --- /dev/null +++ b/docs/src/components/header.tsx @@ -0,0 +1,89 @@ +"use client"; + +import Link from "next/link"; +import { useMobileNav } from "./mobile-nav-context"; + +export function Header() { + const { isOpen, toggle } = useMobileNav(); + + return ( +
+
+
+ + + + + + + + + + + + + agent-browser + + +
+ +
+
+ ); +} diff --git a/docs/src/components/mobile-nav-context.tsx b/docs/src/components/mobile-nav-context.tsx new file mode 100644 index 0000000..a08d8d0 --- /dev/null +++ b/docs/src/components/mobile-nav-context.tsx @@ -0,0 +1,45 @@ +"use client"; + +import { createContext, useContext, useState, useEffect } from "react"; +import { usePathname } from "next/navigation"; + +type MobileNavContextType = { + isOpen: boolean; + setIsOpen: (open: boolean) => void; + toggle: () => void; +}; + +const MobileNavContext = createContext(null); + +export function MobileNavProvider({ children }: { children: React.ReactNode }) { + const [isOpen, setIsOpen] = useState(false); + const pathname = usePathname(); + + useEffect(() => { + setIsOpen(false); + }, [pathname]); + + useEffect(() => { + const handleEscape = (e: KeyboardEvent) => { + if (e.key === "Escape") setIsOpen(false); + }; + document.addEventListener("keydown", handleEscape); + return () => document.removeEventListener("keydown", handleEscape); + }, []); + + const toggle = () => setIsOpen(!isOpen); + + return ( + + {children} + + ); +} + +export function useMobileNav() { + const context = useContext(MobileNavContext); + if (!context) { + throw new Error("useMobileNav must be used within a MobileNavProvider"); + } + return context; +} diff --git a/docs/src/components/sidebar.tsx b/docs/src/components/sidebar.tsx index 663760a..072858a 100644 --- a/docs/src/components/sidebar.tsx +++ b/docs/src/components/sidebar.tsx @@ -2,7 +2,7 @@ import Link from "next/link"; import { usePathname } from "next/navigation"; -import { useState, useEffect } from "react"; +import { useMobileNav } from "./mobile-nav-context"; const navigation = [ { name: "Introduction", href: "/" }, @@ -20,46 +20,10 @@ const navigation = [ export function Sidebar() { const pathname = usePathname(); - const [isOpen, setIsOpen] = useState(false); - - useEffect(() => { - setIsOpen(false); - }, [pathname]); - - useEffect(() => { - const handleEscape = (e: KeyboardEvent) => { - if (e.key === "Escape") setIsOpen(false); - }; - document.addEventListener("keydown", handleEscape); - return () => document.removeEventListener("keydown", handleEscape); - }, []); + const { isOpen, setIsOpen } = useMobileNav(); return ( <> - {/* Mobile header */} -
-
- - agent-browser - - -
-
- {/* Mobile overlay */} {isOpen && (
-
- {/* Desktop header */} -
- - agent-browser - -
- +