Skip to content

feat(docs-site): widen the content column and add a mermaid lightbox - #577

Merged
JArmandoAnaya merged 1 commit into
mainfrom
feat/docs-mermaid-lightbox
Aug 13, 2026
Merged

feat(docs-site): widen the content column and add a mermaid lightbox#577
JArmandoAnaya merged 1 commit into
mainfrom
feat/docs-mermaid-lightbox

Conversation

@JArmandoAnaya

Copy link
Copy Markdown
Contributor

Two dogfooding findings on the documentation site: the prose column was at Starlight's default
45rem, and every mermaid diagram was drawn at that width. Fifteen of the forty-two pages carry a
diagram and all of them are architecture pages, where the diagram is the page's point — at
column width the large ones are unreadable.

What changed

--sl-content-width: 50rem, on the bare :root. Measured at a fixed viewport, toggling only
the token:

Viewport 45rem 50rem Gained
1024 692px 692px 0
1280 632px 632px 0
1440 720px 772px +52
1920 720px 800px +80

It is a ceiling, so below ~1400 it does nothing — the pane is already space-constrained by the
sidebar and the table of contents and never reaches even the old value. That is stated rather than
hidden; see "Found, not fixed". No overlap and no horizontal body scroll at 1280, 1024 or 390, each
measured rather than eyeballed.

A magnifier on every diagram, opening it in a shared <dialog> at 92vw × 88vh with wheel-zoom
about the cursor and drag-pan, clamped to [1, 8] and reset to fit on every open. The SVG is
cloned with mermaid's width/height attributes and inline max-width: Npx cleared, so the
viewBox fits it while preserving the ratio. Themed only with Starlight tokens — no hex.

No new dependency, no change to how diagrams are authored, no per-diagram configuration, no
frontmatter touched.

The constraint that shaped it

Head.astro's draw() reassigns node.textContent on every redraw, and it redraws on every
theme toggle
— so a button injected inside the <pre> is destroyed. pre.mermaid also scrolls
horizontally, so an absolutely-positioned child would slide out of view on exactly the wide
diagrams that need the button most. The wrapper is therefore emitted at build time by the remark
transform
, not injected in the browser.

Proven load-bearing with a control pair — identical markers, one in each place, across a real
toggle: { survivedInPre: false, survivedInFigure: true }.

Two things the browser corrected

  1. The dialog opened hard against the top-left. A modal <dialog> is centred by the UA's
    margin: auto, and Starlight's reset zeroes margins on everything. Measured x: 0, y: 0 where
    58, 60 was expected. Fixed with an explicit margin: auto.
  2. figure.querySelector("svg") picked the diagram only by document order — the figure also
    contains the magnifier's own inline-SVG icon, and the bare selector was correct purely because
    the button is appended after the <pre>. Now scoped to pre.mermaid svg. Prepending the
    button flips the bare selector to "the button icon" and leaves the scoped one on the diagram.

Test plan

No automated coverage: docs-site has no unit or e2e suite, and standing up a browser harness for
the documentation site is a larger decision than this change. Everything below was verified
interactively in chromium against the dev server.

Check Result
Tab reaches the button matchesFocusVisible: true, opacity: 1
Enter opens :modal, 1325×880 at viewport 1440×1000 (= 92vw × 88vh)
Esc closes, focus returns focusReturnedTo: mermaid-zoom, isTheMagnifier: true
Backdrop vs content click content → still open; dialog-target → closed
Magnification on-page 738×871275×151, 1.73×, fits stage
Zoom holds the cursor point wheel at 75% width → translate(-271.299px, 0px) scale(1.82212)
Pan tracks exactly drag (-100, -40)translate(-371.299px, -40px)
Both clamps zoom out → exactly scale(1), translate(0,0); 40 notches in → scale(8)
Theme toggle with diagrams on screen button count stays 1 across light → dark → light
prefers-reduced-motion: reduce animationName: "none"; otherwise 0.12s
Touch context (hasTouch, isMobile) hover: none matches, opacity: 1 without hovering

Mutation check. The wheel listener's { passive: false } is the one guard whose absence is
silent. Committed first, then mutated to { passive: true } and re-measured in the browser:
defaultPrevented true with it, false without. Reverted; tree confirmed clean.

Gates

Only docs-site/ was touched. It is its own pnpm workspace root, not a frontend/* member, ships
in no Python package and no image, and the browser suites drive frontend/app only — so the
acceptance set is the docs group plus every repo gate that actually scans docs-site.

  • bash scripts/check.sh docsexit 0 (build; projection deterministic, 42 pages; 3682
    internal links across 43 pages all resolve)
  • node --test tests/scripts/{docs_sidebar,docs_links,cooldown}.test.mjsexit 0, 20 pass
  • uv run pytest tests/architecture/test_tracked_file_sizes.py -qexit 0

Not run: python, frontend, generated, browser — nothing in this diff is reachable from them.

The build's two warnings (deprecated markdown.remarkPlugins, sitemap's missing site) are
pre-existing on main and unrelated.

Found, not fixed

  • The widening is inert at or below ~1400px, per the table above. If the goal is a wider column
    on a 13–14" laptop, the lever is the sidebar/ToC widths or the pane's gutters — a real layout
    change, deliberately out of scope here.
  • The other Robomous documentation sites now differ on content width. visionset.css states
    its values are shared verbatim across the family; the header now records this token as a
    deliberate exception rather than drift.
  • .playwright-mcp/ is not in .gitignore. The Playwright MCP tooling writes snapshots and
    console logs into the repo root it runs from. Cleaned up by hand here; one ignore line would
    settle it permanently.
  • Astro deprecation: markdown.remarkPlugins — the key astro.config.mjs uses to register the
    mermaid transform — wants moving to unified({...}) from @astrojs/markdown-remark.

The documentation site set its prose at Starlight's default 45rem and drew
every mermaid diagram at that width. Fifteen of the forty-two pages carry a
diagram and all of them are architecture pages, where the diagram is the
page's point — and at column width the large ones are unreadable.

Two changes, one file each plus the styles:

- `--sl-content-width` goes to 50rem. It is a max-width, so it binds only
  where there is room: measured at 1440 the column gains 52px and at 1920 the
  full 80px, while at 1280 and below the pane is already space-constrained and
  nothing moves.

- Every diagram gets a magnifier button opening it in a `<dialog>` at
  92vw x 88vh, with wheel-zoom about the cursor and drag-pan for the graphs
  that do not fit even there. One dialog is created lazily and reused; the
  diagram's SVG is cloned into it with mermaid's width, height and inline
  max-width cleared so the viewBox fits it to the box.

The wrapper the button hangs off is emitted by the remark transform rather
than injected in the browser, and that is load-bearing: the redraw that
follows every theme toggle reassigns the `<pre>`'s text content, so a button
inside it is destroyed. Verified with a control pair — a marker in the `<pre>`
does not survive a toggle, one in the wrapper does.

Two things the browser corrected: a modal dialog is centred by the UA's
`margin: auto`, which Starlight's reset zeroes, so the dialog opened against
the top-left until the margin was restored explicitly; and the clone must be
found through `pre.mermaid svg`, since the figure also contains the
magnifier's own icon and a bare `figure svg` picked the diagram only by
document order.

No new dependency, no change to how diagrams are authored, no per-diagram
configuration.
@JArmandoAnaya
JArmandoAnaya merged commit 68ed18a into main Aug 13, 2026
15 checks passed
@JArmandoAnaya
JArmandoAnaya deleted the feat/docs-mermaid-lightbox branch August 13, 2026 20:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant