From 85722ed2c45b250405c62426c46b748445f55399 Mon Sep 17 00:00:00 2001 From: Chris Feijoo Date: Wed, 19 Aug 2026 19:04:35 +0200 Subject: [PATCH] FE-1455: Tighten the docs site chrome --- apps/petrinaut-docs/README.md | 28 +++ apps/petrinaut-docs/astro.config.mjs | 41 +++- apps/petrinaut-docs/src/components/Head.astro | 14 ++ .../src/components/SiteTitle.astro | 157 +++++++++++++ apps/petrinaut-docs/src/styles/chrome.css | 207 ++++++++++++++++++ 5 files changed, 445 insertions(+), 2 deletions(-) create mode 100644 apps/petrinaut-docs/src/components/Head.astro create mode 100644 apps/petrinaut-docs/src/components/SiteTitle.astro create mode 100644 apps/petrinaut-docs/src/styles/chrome.css diff --git a/apps/petrinaut-docs/README.md b/apps/petrinaut-docs/README.md index fc9cf0ab92e..0d88a2da978 100644 --- a/apps/petrinaut-docs/README.md +++ b/apps/petrinaut-docs/README.md @@ -64,6 +64,34 @@ output, which would otherwise reach the root-hoisted `cookie@0.7.2` that `express` pins and fail on a missing `parseCookie` export. Nesting keeps Astro on its own `cookie@2.x` without changing hoisting for the rest of the monorepo. +## Chrome overrides + +[`src/styles/chrome.css`](src/styles/chrome.css), registered as Starlight's +`customCss`, narrows both side panels to give the content column more width, +tones down the header, and rounds the corners on markdown images so the embedded +diagrams match the bordered cards beside them. The left nav takes its own +`--pnd-sidebar-width` because Starlight sizes both panels from +`--sl-sidebar-width`, and collapsing the nav has to zero one of them without +flattening the other. The collapse toggle and resize handle come from +`components.SiteTitle`, the header's leftmost slot, next to the rail they act +on — and the fixed header is the one piece of chrome still on screen once the +nav is gone. Both +controls remember their state in `localStorage`, restored by a `head` script so +a collapsed sidebar does not render open and then jump. + +## The code font + +Code renders in JetBrains Mono, requested through Astro's font support in +[`astro.config.mjs`](astro.config.mjs) and emitted by `` in +[`src/components/Head.astro`](src/components/Head.astro). + +A build downloads one variable file covering weights 400 to 700, subsets it to +latin, and writes it beside the other assets, so a reader makes no request to a +font host. The head carries a `preload` link and `font-display: swap`, and Astro +generates a metric-matched fallback, which is what keeps text from shifting when +the file arrives. The downloaded originals are cached under `.astro/`, which is +ignored. + ## Deployment Vercel builds the site from [`vercel.json`](vercel.json), which runs diff --git a/apps/petrinaut-docs/astro.config.mjs b/apps/petrinaut-docs/astro.config.mjs index 389a70fe7f6..9c397b468cf 100644 --- a/apps/petrinaut-docs/astro.config.mjs +++ b/apps/petrinaut-docs/astro.config.mjs @@ -4,7 +4,7 @@ import { fileURLToPath } from "node:url"; import react from "@astrojs/react"; import starlight from "@astrojs/starlight"; -import { defineConfig } from "astro/config"; +import { defineConfig, fontProviders } from "astro/config"; /** * Renders the architecture bundle produced by `@local/petrinaut-arch-docs`. @@ -213,12 +213,29 @@ export default defineConfig({ trailingSlash: "never", build: { format: "file" }, + /* + * One variable file covers every weight the code blocks use, downloaded and + * subset at build time so a reader makes no request to a font host. Italic is + * left out: no code style in the docs uses it. + */ + fonts: [ + { + provider: fontProviders.fontsource(), + name: "JetBrains Mono", + cssVariable: "--pnd-font-mono", + weights: ["400 700"], + styles: ["normal"], + subsets: ["latin"], + fallbacks: ["ui-monospace", "SFMono-Regular", "Menlo", "monospace"], + }, + ], + integrations: [ // Generated layer pages import the bundle's facts and relations cards, and // authored pages may import its diagram components; both are React. react(), starlight({ - title: "Architecture Docs", + title: "Docs", description: "How the Petrinaut packages fit together — generated from annotations in the source.", // The helmet carries the Petrinaut identity, so the title beside it names @@ -229,6 +246,26 @@ export default defineConfig({ replacesTitle: false, }, favicon: "/favicon.ico", + // Narrows both side panels and rounds the images, and styles the collapse + // controls that `components.SiteTitle` renders. See `chrome.css`. + customCss: ["./src/styles/chrome.css"], + components: { + Head: "./src/components/Head.astro", + SiteTitle: "./src/components/SiteTitle.astro", + }, + // Restores the collapsed state before first paint. In the component's own + // script the sidebar would render at full width and then jump. + head: [ + { + tag: "script", + content: `try { + const stored = localStorage.getItem("pnd:sidebar"); + const width = localStorage.getItem("pnd:sidebar-width"); + if (stored === "collapsed") document.documentElement.dataset.pndSidebar = stored; + if (width) document.documentElement.style.setProperty("--pnd-sidebar-open-width", width); +} catch {}`, + }, + ], social: [ { icon: "github", diff --git a/apps/petrinaut-docs/src/components/Head.astro b/apps/petrinaut-docs/src/components/Head.astro new file mode 100644 index 00000000000..8d5b9f56bf2 --- /dev/null +++ b/apps/petrinaut-docs/src/components/Head.astro @@ -0,0 +1,14 @@ +--- +/** + * Starlight's head, plus the font faces and preload links for the code font. + * + * Astro's `` emits both, so the family has to be requested from a + * component in the head rather than from configuration alone. + */ + +import Default from "@astrojs/starlight/components/Head.astro"; +import { Font } from "astro:assets"; +--- + + + diff --git a/apps/petrinaut-docs/src/components/SiteTitle.astro b/apps/petrinaut-docs/src/components/SiteTitle.astro new file mode 100644 index 00000000000..43dd6d405b2 --- /dev/null +++ b/apps/petrinaut-docs/src/components/SiteTitle.astro @@ -0,0 +1,157 @@ +--- +import Default from "@astrojs/starlight/components/SiteTitle.astro"; + +/** + * Adds the desktop sidebar collapse toggle and resize handle beside the title. + * + * They hang off `SiteTitle` because it is the header's leftmost slot, next to + * the rail's edge where the controls act, and the fixed header is the only + * chrome still on screen once the sidebar pane itself is collapsed away. Both + * are display: none unless the page has a sidebar (see `chrome.css`), so the + * splash-template 404 page does not grow controls with nothing to control. + */ +--- + + + + + + + + diff --git a/apps/petrinaut-docs/src/styles/chrome.css b/apps/petrinaut-docs/src/styles/chrome.css new file mode 100644 index 00000000000..a98013bc68a --- /dev/null +++ b/apps/petrinaut-docs/src/styles/chrome.css @@ -0,0 +1,207 @@ +/* + * Chrome overrides for the architecture docs site, registered as Starlight's + * `customCss`. Custom CSS is unlayered, so these rules win over Starlight's + * `@layer starlight.core` without needing extra specificity to fight it. The + * exception is `Page.astro`'s inline `