diff --git a/astro.config.mjs b/astro.config.mjs index ff6b14a5..aa7b0c4c 100644 --- a/astro.config.mjs +++ b/astro.config.mjs @@ -53,43 +53,44 @@ 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", SiteTitle: "./src/components/SiteTitle.astro", 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 deleted file mode 100644 index cceaeb0f..00000000 --- a/src/components/Sidebar.astro +++ /dev/null @@ -1,35 +0,0 @@ ---- -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"; - -/** - * 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. - */ - -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/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/styles/custom.css b/src/styles/custom.css index c52bfd29..e4699fb3 100644 --- a/src/styles/custom.css +++ b/src/styles/custom.css @@ -197,3 +197,23 @@ samp { :root[data-theme="light"] .sl-menu-button:has(~ :popover-open) { background-color: var(--sl-color-gray-6); } + +/* ---------- Docs sidebar ---------- + Starlight renders every sidebar group as a collapsible
. The + docs sidebar is short, so its groups act as section labels instead: no + caret, no click target, and the pages stay visible even when a group was + closed from the keyboard or restored closed from session storage. Nested + pages indent half as far as Starlight's default. */ +#starlight__sidebar summary { + pointer-events: none; +} +#starlight__sidebar summary .caret { + display: none; +} +#starlight__sidebar details::details-content { + content-visibility: visible; +} +#starlight__sidebar ul ul li { + margin-inline-start: calc(var(--sl-sidebar-item-padding-inline) / 2); + padding-inline-start: calc(var(--sl-sidebar-item-padding-inline) / 2); +} 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/*";