Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 16 additions & 14 deletions astro.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -53,43 +53,45 @@ 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" },
],
},
],
Expand Down
3 changes: 1 addition & 2 deletions src/components/Header.astro
Original file line number Diff line number Diff line change
Expand Up @@ -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 =
Expand Down
24 changes: 5 additions & 19 deletions src/components/Sidebar.astro
Original file line number Diff line number Diff line change
@@ -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;
---

<SidebarPersister>
<SidebarSublist sublist={entries} />
<SidebarList entries={sidebar} />
</SidebarPersister>

<div class="md:sl-hidden">
Expand Down
111 changes: 111 additions & 0 deletions src/components/SidebarList.astro
Original file line number Diff line number Diff line change
@@ -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 `<details>` 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 {
Comment on lines +4 to +10

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As far as I can see the purpose of this is to add another level of nesting to the sidebar. I don't think that is worth vendoring yet another starlight component

Image

entries: StarlightRouteData["sidebar"];
nested?: boolean;
}

const { entries, nested } = Astro.props;
---

<ul class:list={{ "top-level": !nested }}>
{entries.map((entry) => (
<li>
{entry.type === "link" ? (
<a
href={entry.href}
aria-current={entry.isCurrent ? "page" : undefined}
class:list={{ large: !nested }}
>
{entry.label}
</a>
) : (
<Fragment>
<span class="group-label large">{entry.label}</span>
<Astro.self entries={entry.entries} nested />
</Fragment>
)}
</li>
))}
</ul>

{/* 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. */}
<style>
@layer starlight.core {
ul {
--sl-sidebar-item-padding-inline: 0.5rem;
list-style: none;
padding: 0;
}

li {
overflow-wrap: anywhere;
}

ul ul li {
margin-inline-start: calc(var(--sl-sidebar-item-padding-inline) / 2);
border-inline-start: 1px solid var(--sl-color-hairline-light);
padding-inline-start: calc(var(--sl-sidebar-item-padding-inline) / 2);
}

.large {
font-size: var(--sl-text-lg);
font-weight: 600;
color: var(--sl-color-white);
}

.top-level > li + li {
margin-top: 0.75rem;
}

.group-label {
display: block;
padding: 0.2em var(--sl-sidebar-item-padding-inline);
line-height: 1.4;
}

a {
display: block;
border-radius: 0.25rem;
text-decoration: none;
color: var(--sl-color-gray-2);
padding: 0.3em var(--sl-sidebar-item-padding-inline);
line-height: 1.4;
}

a:hover,
a:focus {
color: var(--sl-color-white);
}

[aria-current="page"],
[aria-current="page"]:hover,
[aria-current="page"]:focus {
font-weight: 600;
color: var(--sl-color-text-invert);
background-color: var(--sl-color-text-accent);
}

@media (min-width: 50rem) {
.top-level > li + li {
margin-top: 0.5rem;
}
.large {
font-size: var(--sl-text-base);
}
a {
font-size: var(--sl-text-sm);
}
}
}
</style>
16 changes: 5 additions & 11 deletions src/data/nav.ts
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -18,17 +16,13 @@ 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",
href: `/${newestRelease().name}.html`,
// 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)/,
},
];
17 changes: 0 additions & 17 deletions src/routeData.ts

This file was deleted.

6 changes: 3 additions & 3 deletions src/virtual-starlight.d.ts
Original file line number Diff line number Diff line change
@@ -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/*";
Loading