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; +--- + + + +{/* 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/*";