From 43fa859f920253b4e8dbc48c903a368aee032b76 Mon Sep 17 00:00:00 2001 From: NriotHrreion Date: Thu, 10 Sep 2026 15:55:21 +0800 Subject: [PATCH 1/6] feat(website): use collapsible nav for docs-navigation --- .../src/components/docs-navigation.tsx | 110 ++++++++++++++---- apps/website/src/components/navbar.tsx | 9 +- apps/website/src/layouts/base-layout.astro | 25 ++-- apps/website/src/pages/docs/[...slug].astro | 8 +- 4 files changed, 113 insertions(+), 39 deletions(-) diff --git a/apps/website/src/components/docs-navigation.tsx b/apps/website/src/components/docs-navigation.tsx index be6b2ee..0c0b28d 100644 --- a/apps/website/src/components/docs-navigation.tsx +++ b/apps/website/src/components/docs-navigation.tsx @@ -1,7 +1,11 @@ +import { useEffect, useState } from "react"; +import { createPortal } from "react-dom"; import { - GlNav, + GlCollapsibleNav, + GlCollapsibleNavToggle, GlNavButton, GlNavItem, + GlNavProvider, GlSubNav, GlSubNavButton, GlSubNavItem, @@ -18,6 +22,9 @@ type DocsNavigationProps = { entries: DocsNavigationEntry[]; }; +const DESKTOP_NAV_QUERY = "(min-width: 1200px)"; +const NAVBAR_TOGGLE_TARGET_ID = "documentation-navigation-toggle-target"; + function formatGroupLabel(group: string) { return group .split("-") @@ -26,9 +33,41 @@ function formatGroupLabel(group: string) { } export function DocsNavigation({ currentId, entries }: DocsNavigationProps) { + const [isOpen, setIsOpen] = useState(false); + const [toggleTarget, setToggleTarget] = useState(null); const rootEntries = entries.filter(({ id }) => !id.includes("/")); const groupedEntries = new Map(); + useEffect(() => { + const desktopQuery = window.matchMedia(DESKTOP_NAV_QUERY); + const syncOpenState = () => setIsOpen(desktopQuery.matches); + + syncOpenState(); + desktopQuery.addEventListener("change", syncOpenState); + + return () => desktopQuery.removeEventListener("change", syncOpenState); + }, []); + + useEffect(() => { + let targetObserver: MutationObserver | undefined; + + const findToggleTarget = () => { + const target = document.getElementById(NAVBAR_TOGGLE_TARGET_ID); + if(!target) return; + + setToggleTarget(target); + targetObserver?.disconnect(); + }; + + findToggleTarget(); + if(!document.getElementById(NAVBAR_TOGGLE_TARGET_ID)) { + targetObserver = new MutationObserver(findToggleTarget); + targetObserver.observe(document.body, { childList: true, subtree: true }); + } + + return () => targetObserver?.disconnect(); + }, []); + entries.forEach((entry) => { const [group] = entry.id.split("/"); @@ -40,29 +79,52 @@ export function DocsNavigation({ currentId, entries }: DocsNavigationProps) { }); return ( - - {rootEntries.map((entry) => ( - - {entry.title} - - ))} - - {[...groupedEntries].map(([group, groupEntries]) => { - const containsCurrentPage = groupEntries.some(({ id }) => id === currentId); - - return ( - - {formatGroupLabel(group)} - - {groupEntries.map((entry) => ( - - {entry.title} - - ))} - + + {toggleTarget ? createPortal( + , + toggleTarget, + ) : null} + + + {rootEntries.map((entry) => ( + + + {entry.title} + - ); - })} - + ))} + + {[...groupedEntries].map(([group, groupEntries]) => { + const containsCurrentPage = groupEntries.some(({ id }) => id === currentId); + + return ( + + + {formatGroupLabel(group)} + + + {groupEntries.map((entry) => ( + + {entry.title} + + ))} + + + ); + })} + + + + + + ); } diff --git a/apps/website/src/components/navbar.tsx b/apps/website/src/components/navbar.tsx index 51263cb..9572b8d 100644 --- a/apps/website/src/components/navbar.tsx +++ b/apps/website/src/components/navbar.tsx @@ -81,6 +81,7 @@ export function Navbar() {
+ - setLang(value as any)}> + setLang(value as any)}> {/** @todo */} - English + + English + diff --git a/apps/website/src/layouts/base-layout.astro b/apps/website/src/layouts/base-layout.astro index 2ab76e6..efe2343 100644 --- a/apps/website/src/layouts/base-layout.astro +++ b/apps/website/src/layouts/base-layout.astro @@ -1,4 +1,5 @@ --- +import { ClientRouter } from "astro:transitions"; import "../styles/global.css"; import { GlLink } from "gitlab-ui-react"; import { Navbar } from "../components/navbar"; @@ -25,18 +26,24 @@ const currentYear = new Date().getFullYear(); {title} + diff --git a/apps/website/src/pages/docs/[...slug].astro b/apps/website/src/pages/docs/[...slug].astro index 273bb85..1ac985f 100644 --- a/apps/website/src/pages/docs/[...slug].astro +++ b/apps/website/src/pages/docs/[...slug].astro @@ -48,16 +48,16 @@ const tableOfContents = headings.filter(({ depth }) => depth >= 2 && depth <= 3)
-
-