From 15ce10f652949e49c1367a07a90a4745cf579880 Mon Sep 17 00:00:00 2001 From: Ruben Arts Date: Mon, 26 Oct 2026 16:04:32 +0100 Subject: [PATCH] Merge the Community section into Docs New visitors had to guess whether Support, Contributing and the community meeting lived under Docs or under Community. The header now has Home, Docs and Packages, and the Docs sidebar groups the pages by what you came to do: use RoboStack, get help, contribute. The slugs are flat, so every URL stays the same. The sidebar groups don't collapse anymore and nested items indent half as far. Starlight has no setting for that, so SidebarList.astro renders the groups itself. src/routeData.ts goes too: it highlighted a "Packages" sidebar link that was removed in #157. --- astro.config.mjs | 30 +++++---- src/components/Header.astro | 3 +- src/components/Sidebar.astro | 24 ++----- src/components/SidebarList.astro | 111 +++++++++++++++++++++++++++++++ src/data/nav.ts | 16 ++--- src/routeData.ts | 17 ----- src/virtual-starlight.d.ts | 6 +- 7 files changed, 141 insertions(+), 66 deletions(-) create mode 100644 src/components/SidebarList.astro delete mode 100644 src/routeData.ts diff --git a/astro.config.mjs b/astro.config.mjs index ff6b14a5..d4dfea4c 100644 --- a/astro.config.mjs +++ b/astro.config.mjs @@ -53,7 +53,6 @@ export default defineConfig({ baseUrl: "https://github.com/RoboStack/robostack.github.io/edit/main/", }, customCss: ["./src/styles/custom.css"], - routeMiddleware: "./src/routeData.ts", components: { Header: "./src/components/Header.astro", Sidebar: "./src/components/Sidebar.astro", @@ -61,35 +60,38 @@ export default defineConfig({ PageTitle: "./src/components/PageTitle.astro", }, sidebar: [ - // One top-level group per header tab (src/components/Header.astro); - // the Sidebar override shows only the current page's group, so these - // group labels never render. List each page in exactly one group, the - // one whose tab nav.ts highlights for it, so the sidebar and the - // header tabs never disagree. Slugs are set explicitly in each page's - // frontmatter to keep the published mixed-case URLs - // (`GettingStarted.html`, `FAQ.html`, ...). + // The sidebar is the Docs section: the frontpage and the distro table + // pages have none. Every page listed here also has to match the Docs + // tab's pattern in src/data/nav.ts, so the header highlights it. + // Slugs are set explicitly in each page's frontmatter to keep the + // published mixed-case URLs (`GettingStarted.html`, `FAQ.html`, ...). { - label: "Docs", + label: "Use RoboStack", items: [ { label: "Getting Started", slug: "GettingStarted" }, { - label: "Alternative to Pixi", + label: "Alternatives to Pixi", items: [ { label: "Micromamba", slug: "micromamba" }, { label: "Conda", slug: "conda" }, ], }, { label: "JupyterRos", slug: "JupyterRos" }, - { label: "FAQ", slug: "FAQ" }, - { label: "RoboStack monorepo", slug: "Monorepo" }, ], }, { - label: "Community", + label: "Get help", items: [ - { label: "Community Meeting", slug: "CommunityMeeting" }, { label: "Support", slug: "support" }, + { label: "Community Meeting", slug: "CommunityMeeting" }, + { label: "FAQ", slug: "FAQ" }, + ], + }, + { + label: "Contribute", + items: [ { label: "Contributing", slug: "Contributing" }, + { label: "RoboStack monorepo", slug: "Monorepo" }, ], }, ], diff --git a/src/components/Header.astro b/src/components/Header.astro index a2dcd859..6d1c60f8 100644 --- a/src/components/Header.astro +++ b/src/components/Header.astro @@ -16,8 +16,7 @@ import { NAV_TABS as tabs } from "../data/nav"; * the logo; from that breakpoint up they move next to the logo in the * single header row. The row heights come from `--sl-nav-height`, set * per breakpoint in custom.css; the logo row keeps the original height via - * `--rs-nav-row`. The tabs live in src/data/nav.ts, shared with the Sidebar - * override. + * `--rs-nav-row`. The tabs live in src/data/nav.ts. */ const shouldRenderSearch = diff --git a/src/components/Sidebar.astro b/src/components/Sidebar.astro index cceaeb0f..e11058f8 100644 --- a/src/components/Sidebar.astro +++ b/src/components/Sidebar.astro @@ -1,33 +1,19 @@ --- import MobileMenuFooter from "virtual:starlight/components/MobileMenuFooter"; import SidebarPersister from "@astrojs/starlight/components/SidebarPersister.astro"; -import SidebarSublist from "@astrojs/starlight/components/SidebarSublist.astro"; -import { NAV_TABS } from "../data/nav"; +import SidebarList from "./SidebarList.astro"; /** - * Override of Starlight's Sidebar: the header tabs are the top level of the - * navigation, so the sidebar only shows the pages of the current section. - * The section comes from the shared nav.ts patterns - the same ones that - * pick the active header tab - and names the matching top-level group in - * `astro.config.mjs`. Pages outside any section fall back to the full - * sidebar. The distro table pages opt out of the sidebar entirely; their - * in-page distro tabs are the sub-navigation. + * Override of Starlight's Sidebar that shows every group expanded, without + * the collapse toggles (see SidebarList.astro). The persister still restores + * the sidebar's scroll position between pages. */ - const { sidebar } = Astro.locals.starlightRoute; -const pathname = Astro.url.pathname; - -const tab = NAV_TABS.find((t) => t.match.test(pathname)); -const section = sidebar.find( - (entry) => entry.type === "group" && entry.label === tab?.label, -); - -const entries = section && section.type === "group" ? section.entries : sidebar; --- - +
diff --git a/src/components/SidebarList.astro b/src/components/SidebarList.astro new file mode 100644 index 00000000..be93959a --- /dev/null +++ b/src/components/SidebarList.astro @@ -0,0 +1,111 @@ +--- +import type { StarlightRouteData } from "@astrojs/starlight/route-data"; + +/** + * The sidebar's link tree for the Sidebar override. Starlight's own + * SidebarSublist renders every group as a `
` toggle; here a group is + * a plain label over its links, so no section can be folded away. Badges and + * custom link attributes are not rendered: the sidebar config uses neither. + */ +interface Props { + entries: StarlightRouteData["sidebar"]; + nested?: boolean; +} + +const { entries, nested } = Astro.props; +--- + +
    + {entries.map((entry) => ( +
  • + {entry.type === "link" ? ( + + {entry.label} + + ) : ( + + {entry.label} + + + )} +
  • + ))} +
+ +{/* Copied from Starlight's SidebarSublist.astro, minus the summary and caret + rules, and kept in its cascade layer so the result looks the same. The + group label takes the padding the summary had, and nested lists indent + half as far as Starlight's. */} + diff --git a/src/data/nav.ts b/src/data/nav.ts index 51486ada..953bf659 100644 --- a/src/data/nav.ts +++ b/src/data/nav.ts @@ -1,11 +1,9 @@ import { DISTROS, newestRelease } from "./distros"; /** - * The site's top-level sections: one header tab each (Header.astro), and - - * for tabs whose label matches a top-level sidebar group in astro.config.mjs - * - the sidebar shows that group's pages (Sidebar.astro). `match` decides - * both the active tab and which section a page belongs to, so a page's - * slug should match exactly the tab whose sidebar group lists it. + * The site's top-level sections, one header tab each (Header.astro). `match` + * decides which tab is active for a page. Every docs page in the sidebar in + * `astro.config.mjs` has to match the Docs pattern. */ export interface NavTab { label: string; @@ -18,7 +16,8 @@ export const NAV_TABS: NavTab[] = [ { label: "Docs", href: "/GettingStarted.html", - match: /^\/(GettingStarted|micromamba|conda|JupyterRos|FAQ|Monorepo)/, + match: + /^\/(GettingStarted|micromamba|conda|JupyterRos|FAQ|support|CommunityMeeting|Contributing|Monorepo)/, }, { label: "Packages", @@ -26,9 +25,4 @@ export const NAV_TABS: NavTab[] = [ // Active on every distro table page (/noetic.html, /lyrical.html, ...). match: new RegExp(`^/(${DISTROS.map((d) => d.name).join("|")})(\\.html)?$`), }, - { - label: "Community", - href: "/CommunityMeeting.html", - match: /^\/(CommunityMeeting|support|Contributing)/, - }, ]; diff --git a/src/routeData.ts b/src/routeData.ts deleted file mode 100644 index a76efbf6..00000000 --- a/src/routeData.ts +++ /dev/null @@ -1,17 +0,0 @@ -/* Starlight highlights a sidebar link only on an exact URL match, so the - * "Packages" entry (which points at one distro page) would lose its active - * state on every other distro page. Mark it current on all of them. */ - -import { defineRouteMiddleware } from "@astrojs/starlight/route-data"; -import { DISTROS } from "./data/distros"; - -const DISTRO_PATHS = new Set(DISTROS.map((distro) => `/${distro.name}.html`)); - -export const onRequest = defineRouteMiddleware((context) => { - if (!DISTRO_PATHS.has(context.url.pathname)) return; - for (const entry of context.locals.starlightRoute.sidebar) { - if (entry.type === "link" && DISTRO_PATHS.has(entry.href)) { - entry.isCurrent = true; - } - } -}); diff --git a/src/virtual-starlight.d.ts b/src/virtual-starlight.d.ts index 519e01a0..ebcf4468 100644 --- a/src/virtual-starlight.d.ts +++ b/src/virtual-starlight.d.ts @@ -1,4 +1,4 @@ -/* Starlight's internals import `virtual:starlight/*` modules that only exist - * inside Astro's runtime. svelte-check follows the import chain from - * routeData.ts into them and cannot resolve the specifiers, so declare them. */ +/* The component overrides import `virtual:starlight/*` modules that only + * exist inside Astro's runtime. The type checkers cannot resolve the + * specifiers, so declare them. */ declare module "virtual:starlight/*";