Skip to content

fix(web): keep the packages grid inside the page; add italic Inter and font preloads - #4347

Merged
bpamiri merged 3 commits into
developfrom
peter/web-fonts-followup
Oct 5, 2026
Merged

bpamiri merged 3 commits into
developfrom
peter/web-fonts-followup

Conversation

@bpamiri

@bpamiri bpamiri commented Oct 5, 2026

Copy link
Copy Markdown
Collaborator

Summary

A follow-up to #4341 with three small changes.

1. The packages index grid stays inside the page. The third card column ran past the viewport edge, visible in the packages-index baseline both before and after #4341. There were two causes:

  • Grid tracks: repeat(3, 1fr) tracks are minmax(auto, 1fr), so a column can't shrink below its content's min-content width.
  • Command box: the card's install command sits in a .install flex row, where the <code> box has white-space: nowrap; overflow-x: auto. But a flex item's default min-width: auto let the longest command (wheels packages add wheels-legacy-adapter) set the card's minimum width.

The fix:

  • sites/packages/src/pages/index.astro: grid tracks become minmax(0, 1fr) at all three breakpoints.
  • sites/packages/src/components/PackageCard.astro: .install code gets min-width: 0, so the command scrolls inside its box instead of widening the card.

2. Italic Inter face (rev1-r1's note on #4341). The guides use italics, which were synthesized from the upright face. inter-latin-wght-italic.woff2 (52 KB) comes from @fontsource-variable/inter@5.3.0, the same release as the existing files: the shipped normal face is SHA-256-identical to that package's. It gets a matching @font-face (font-style: italic, font-weight: 100 900, swap, Latin unicode-range).

3. Preloads for the two main font files (also from rev1-r1's notes):

  • packages/ui/src/components/FontPreload.astro: emits <link rel="preload" as="font" type="font/woff2" crossorigin> for the normal Inter and JetBrains Mono files. It uses ?url imports, so the hrefs are the same hashed, base-prefixed assets the @font-face rules load. The italic face loads on demand.
  • Landing, blog and packages: each BaseLayout.astro includes it right after the viewport meta.
  • Guides and API: a new Starlight Head override (packages/ui/src/components/starlight/Head.astro) renders Starlight's head tags exactly as its own Head does (Astro.locals.starlightRoute.head), plus the preloads. It renders them directly because @wheels-dev/ui can't import @astrojs/starlight/components/Head.astro without depending on Starlight; the build fails to resolve it. It's registered in both astro.config.mjs files.

The diff is minimal on purpose (26 changed lines across 9 files, plus 3 new files). The packages-site files were never Prettier-formatted, so I edited them by hand instead of reformatting them.

Verification

  • pnpm build (all sites). Every site's built index.html carries both preloads, for example href="/_astro/inter-latin-wght-normal.Dx4kXJAl.woff2", matching the @font-face URL. On guides and API, each page keeps its <title> and description/og tags, so Starlight's head tags still render.
  • The italic face is emitted, and the CSS has @font-face{font-family:Inter;font-style:italic;…}.
  • Offline docs bundle: with WHEELS_DOCS_BASE=/wheels/guides/, the preloads are /wheels/guides/_astro/…woff2.
  • prettier --check is clean on the new and Prettier-formatted files.
  • Visual baselines: the packages-index baseline should change (the grid fix), and pages with italic text may change too. After CI, I'll check the diffs and refresh only the baselines that change.

🤖 Generated with Claude Code

…d font preloads

The packages index's third card column ran past the viewport: plain 1fr
grid tracks and the card's flex command box couldn't shrink below the
longest install command. Use minmax(0, 1fr) tracks and min-width: 0 on the
command box, which already scrolls.

Add the latin italic Inter face, so italics are no longer synthesized, and
preload the two main woff2 files on every site (a FontPreload component in
the layouts and a Starlight Head override for guides and api).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@bpamiri

bpamiri commented Oct 5, 2026

Copy link
Copy Markdown
Collaborator Author

rev1-r3 review @ 515cd1c: code APPROVE (final sign-off after PR CI, and after any baseline refresh is confirmed images-only)

  • The italic face is exactly Fontsource's. inter-latin-wght-italic.woff2 is SHA-256 7291b597…, identical to @fontsource-variable/inter@5.3.0/files/inter-latin-wght-italic.woff2, the same release as the existing two files. Its @font-face mirrors the normal one with font-style: italic. The existing Inter OFL text covers it.
  • The preloads point at the right files. FontPreload.astro takes its hrefs from ?url imports of the same two files fonts.css loads, so Vite emits one hashed asset per file and the preload and @font-face URLs match, base prefix included. It has as="font" type="font/woff2" crossorigin. crossorigin is required even for same-origin fonts, or the browser fetches the font twice. The italic face is correctly left to load on demand.
  • The Starlight Head override is faithful today. The lockfile pins @astrojs/starlight@0.39.2, and that version's own components/Head.astro is exactly const { head } = Astro.locals.starlightRoute; followed by {head.map(({ tag: Tag, attrs, content }) => <Tag {...attrs} set:html={content} />)}. The override renders the same thing, then <FontPreload />. It's registered in both guides and api configs.
    • Not blocking: because it re-implements Starlight's Head instead of wrapping it, a future Starlight upgrade that adds tags to its Head won't reach these two sites. A one-line comment naming the Starlight version it mirrors (0.39.2), or a check in whichever process bumps Starlight, would make that drift visible.
  • The packages grid fix is right. repeat(n, minmax(0, 1fr)) at all three breakpoints lets the tracks shrink below their min-content width. min-width: 0 on the flex item .install code stops the longest install command from setting the card's minimum width, so it scrolls inside its box as overflow-x: auto intends.
  • Layouts. FontPreload goes right after the viewport <meta> in the landing, blog and packages BaseLayouts, early in <head>, where a preload helps most.

If the visual-baseline refresh pushes new images to this branch, send me the head and I'll confirm the delta is images only.

@bpamiri

bpamiri commented Oct 5, 2026

Copy link
Copy Markdown
Collaborator Author

Review @ 515cd1c: APPROVE on content (web). Merge gated on PR CI and the baselines that change

  • Packages grid overflow. grid-template-columns: minmax(0, 1fr) on all three breakpoints, plus min-width: 0 on the flex code in PackageCard, is the standard fix. A 1fr track's minimum is auto (the content's min-content width), so a long unbreakable install command pushed the track wider than the viewport. minmax(0, …) and min-width: 0 let it shrink, and the box scrolls instead.
  • Italic face. inter-latin-wght-italic.woff2 is a genuine WOFF2 (51,832 bytes). Its @font-face mirrors the upright one (font-style: italic, 100 900, the same latin unicode-range, swap). The existing Inter-OFL.txt already names Inter-Italic[opsz,wght].ttf, so the licence covers it. This resolves my feat(web): self-host the Inter and JetBrains Mono brand fonts #4341 INFO.
  • Preloads.
    • FontPreload.astro imports the two upright files with ?url, so Vite returns the same hashed, base-prefixed asset the @font-face url() resolves to: one download, not two.
    • It emits <link rel="preload" as="font" type="font/woff2" crossorigin>. crossorigin is required for font preloads; without it the preload isn't reused.
    • It's added to the blog, landing and packages layouts, and the italic face is deliberately left to load on demand.
  • Starlight Head override. It renders exactly what Starlight's own Head does. I checked the installed @astrojs/starlight@0.39.2/components/Head.astro: its whole body is {head.map(({ tag: Tag, attrs, content }) => <Tag {...attrs} set:html={content} />)}, the same as the override, plus <FontPreload />. Guides and API now get the preloads with no other head change.

INFO: the override copies Starlight's Head instead of wrapping it, so a future Starlight release that adds to its Head (meta, theme script) won't reach these two sites until the copy is updated. A one-line comment naming the Starlight version it mirrors, or a check when bumping @astrojs/starlight, would keep that visible. It doesn't block.

Baselines: after CI, refresh only the ones that change, as you planned. The bot's refresh commit runs no checks, so push an empty commit afterwards for CI on the final head.

@github-actions github-actions Bot added dependencies Pull requests that update a dependency file javascript Pull requests that update javascript code labels Oct 5, 2026
github-actions Bot and others added 2 commits October 5, 2026 15:20
Manually triggered baseline refresh via
.github/workflows/refresh-visual-baselines.yml
targeting branch peter/web-fonts-followup.

Run when an intentional content/layout change makes the visual-regression
check fail. The new PNG(s) under web/tests/visual-baselines/ are now the
expected rendering.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@bpamiri

bpamiri commented Oct 5, 2026

Copy link
Copy Markdown
Collaborator Author

rev1-r3 re-review @ 802c5ab: code APPROVE (final sign-off after PR CI on this head)

The delta since 515cd1c61 has no code change:

  • 3ae169077 (github-actions bot) touches only web/tests/visual-baselines/packages-index.png. I looked at the new image: three columns fit inside the page, and the long install commands are clipped inside their boxes (scrollable) instead of widening the cards. That's the intended grid fix.
  • 802c5ab9c adds a two-line comment to starlight/Head.astro, "Mirrors @astrojs/starlight 0.39.2 Head.astro; re-sync on every Starlight upgrade." That covers my drift note.

@bpamiri

bpamiri commented Oct 5, 2026

Copy link
Copy Markdown
Collaborator Author

Re-ack @ 802c5ab: APPROVE. Since 515cd1c there are two commits: the bot's packages-index.png refresh (3ae1690) and a two-line comment in starlight/Head.astro naming the Starlight version it mirrors ("Mirrors @astrojs/starlight 0.39.2 Head.astro; re-sync on every Starlight upgrade."), which resolves my INFO. There's no code change. I looked at the refreshed baseline: the grid now fits three columns, and long wheels packages add … commands stay inside their boxes instead of widening the page, which is the intended fix. Because the comment commit was pushed by a person, CI runs on this head (17 pending when checked). Merge once it's green, Visual regression included.

@bpamiri

bpamiri commented Oct 5, 2026

Copy link
Copy Markdown
Collaborator Author

rev1-r3 review @ 802c5ab: APPROVE (final; PR CI checked)

PR CI on this head: 20 pass, 2 skipped, 0 failing or pending, with Visual regression passing against the refreshed packages-index baseline. The code is as I approved it at 515cd1c61. The only later changes are the baseline image (the intended grid fix) and the Starlight-version comment in Head.astro.

@bpamiri
bpamiri merged commit 58667cc into develop Oct 5, 2026
22 checks passed
@bpamiri
bpamiri deleted the peter/web-fonts-followup branch October 5, 2026 15:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies Pull requests that update a dependency file javascript Pull requests that update javascript code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant