diff --git a/web/packages/ui/package.json b/web/packages/ui/package.json index 59f1f0148e..c2887d3360 100644 --- a/web/packages/ui/package.json +++ b/web/packages/ui/package.json @@ -7,8 +7,10 @@ "exports": { "./components/Header.astro": "./src/components/Header.astro", "./components/Footer.astro": "./src/components/Footer.astro", + "./components/FontPreload.astro": "./src/components/FontPreload.astro", "./components/Logo.astro": "./src/components/Logo.astro", "./components/RssPill.astro": "./src/components/RssPill.astro", + "./components/starlight/Head.astro": "./src/components/starlight/Head.astro", "./components/starlight/Header.astro": "./src/components/starlight/Header.astro", "./components/starlight/Footer.astro": "./src/components/starlight/Footer.astro", "./components/starlight/SocialIcons.astro": "./src/components/starlight/SocialIcons.astro", diff --git a/web/packages/ui/src/assets/fonts/inter-latin-wght-italic.woff2 b/web/packages/ui/src/assets/fonts/inter-latin-wght-italic.woff2 new file mode 100644 index 0000000000..2f06c65192 Binary files /dev/null and b/web/packages/ui/src/assets/fonts/inter-latin-wght-italic.woff2 differ diff --git a/web/packages/ui/src/components/FontPreload.astro b/web/packages/ui/src/components/FontPreload.astro new file mode 100644 index 0000000000..8fbc911a8a --- /dev/null +++ b/web/packages/ui/src/components/FontPreload.astro @@ -0,0 +1,11 @@ +--- +// Preload the two brand fonts every page renders text in, so the browser +// fetches them with the HTML instead of after the stylesheet. `?url` gives the +// same hashed, base-prefixed file the @font-face rules in fonts.css point at. +// The italic face is left to load on demand. +import interUrl from '../assets/fonts/inter-latin-wght-normal.woff2?url'; +import monoUrl from '../assets/fonts/jetbrains-mono-latin-wght-normal.woff2?url'; +--- + + + diff --git a/web/packages/ui/src/components/starlight/Head.astro b/web/packages/ui/src/components/starlight/Head.astro new file mode 100644 index 0000000000..97967a784f --- /dev/null +++ b/web/packages/ui/src/components/starlight/Head.astro @@ -0,0 +1,14 @@ +--- +// Mirrors @astrojs/starlight 0.39.2 Head.astro; re-sync on every Starlight upgrade. +// +// Starlight's head tags (what its own Head component renders: route data from +// Astro.locals.starlightRoute.head), plus the brand-font preloads. Rendered +// directly rather than wrapping Starlight's Head, which this package can't +// import without depending on @astrojs/starlight. +import FontPreload from '../FontPreload.astro'; + +const { head } = Astro.locals.starlightRoute; +--- + +{head.map(({ tag: Tag, attrs, content }) => )} + diff --git a/web/packages/ui/src/styles/fonts.css b/web/packages/ui/src/styles/fonts.css index 43a4da6590..d9413f0e5d 100644 --- a/web/packages/ui/src/styles/fonts.css +++ b/web/packages/ui/src/styles/fonts.css @@ -1,6 +1,6 @@ /* * Self-hosted brand fonts: Inter and JetBrains Mono, the faces --font-sans and - * --font-mono in tokens.css name. Latin subset only, as variable fonts + * --font-mono in tokens.css name (Inter in normal and italic). Latin subset only, as variable fonts * (weights 100-900), served from this package so no page requests a font from * a third party. font-display: swap keeps text visible while they load. * Files and their SIL Open Font License texts: ../assets/fonts/. @@ -16,6 +16,17 @@ U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } +@font-face { + font-family: 'Inter'; + font-style: italic; + font-display: swap; + font-weight: 100 900; + src: url('../assets/fonts/inter-latin-wght-italic.woff2') format('woff2'); + unicode-range: + U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, + U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} + @font-face { font-family: 'JetBrains Mono'; font-style: normal; diff --git a/web/sites/api/astro.config.mjs b/web/sites/api/astro.config.mjs index f998b929f3..a2bb929b2f 100644 --- a/web/sites/api/astro.config.mjs +++ b/web/sites/api/astro.config.mjs @@ -43,6 +43,7 @@ export default defineConfig({ '@wheels-dev/ui/styles/starlight-theme.css', ], components: { + Head: '@wheels-dev/ui/components/starlight/Head.astro', Header: '@wheels-dev/ui/components/starlight/Header.astro', Footer: '@wheels-dev/ui/components/starlight/Footer.astro', SocialIcons: '@wheels-dev/ui/components/starlight/SocialIcons.astro', diff --git a/web/sites/blog/src/layouts/BaseLayout.astro b/web/sites/blog/src/layouts/BaseLayout.astro index fbdd2fed11..60ae0b7068 100644 --- a/web/sites/blog/src/layouts/BaseLayout.astro +++ b/web/sites/blog/src/layouts/BaseLayout.astro @@ -1,6 +1,7 @@ --- import Header from '@wheels-dev/ui/components/Header.astro'; import Footer from '@wheels-dev/ui/components/Footer.astro'; +import FontPreload from '@wheels-dev/ui/components/FontPreload.astro'; import NewsletterSignup from '../components/NewsletterSignup.astro'; import '@wheels-dev/ui/styles/tokens.css'; import '@wheels-dev/ui/styles/base.css'; @@ -18,6 +19,7 @@ const { title, description = 'News, tutorials, and release announcements for Whe + {title} diff --git a/web/sites/guides/astro.config.mjs b/web/sites/guides/astro.config.mjs index 64ea8a8c47..1da1f4dda7 100644 --- a/web/sites/guides/astro.config.mjs +++ b/web/sites/guides/astro.config.mjs @@ -209,6 +209,7 @@ const config = defineConfig({ '@wheels-dev/ui/styles/starlight-theme.css', ], components: { + Head: '@wheels-dev/ui/components/starlight/Head.astro', Header: '@wheels-dev/ui/components/starlight/Header.astro', Footer: '@wheels-dev/ui/components/starlight/Footer.astro', SocialIcons: '@wheels-dev/ui/components/starlight/SocialIcons.astro', diff --git a/web/sites/landing/src/layouts/BaseLayout.astro b/web/sites/landing/src/layouts/BaseLayout.astro index 11426b037f..84612b4362 100644 --- a/web/sites/landing/src/layouts/BaseLayout.astro +++ b/web/sites/landing/src/layouts/BaseLayout.astro @@ -1,6 +1,7 @@ --- import Header from '@wheels-dev/ui/components/Header.astro'; import Footer from '@wheels-dev/ui/components/Footer.astro'; +import FontPreload from '@wheels-dev/ui/components/FontPreload.astro'; import '@wheels-dev/ui/styles/tokens.css'; import '@wheels-dev/ui/styles/base.css'; @@ -17,6 +18,7 @@ const { title, description = 'Wheels — a CFML MVC framework.', current = 'land + {title} diff --git a/web/sites/packages/src/components/PackageCard.astro b/web/sites/packages/src/components/PackageCard.astro index 4ca7bc378b..8d24b4300a 100644 --- a/web/sites/packages/src/components/PackageCard.astro +++ b/web/sites/packages/src/components/PackageCard.astro @@ -77,6 +77,7 @@ const homepage = /^https?:\/\//.test(pkg.homepage) ? pkg.homepage : ''; .install { display: flex; align-items: center; gap: 0.5rem; } .install code { flex: 1; + min-width: 0; font-size: 0.8125rem; padding: 0.25rem 0.5rem; background: var(--color-surface-2, #f3f3f3); diff --git a/web/sites/packages/src/layouts/BaseLayout.astro b/web/sites/packages/src/layouts/BaseLayout.astro index 558f8eeda3..992f84b600 100644 --- a/web/sites/packages/src/layouts/BaseLayout.astro +++ b/web/sites/packages/src/layouts/BaseLayout.astro @@ -1,6 +1,7 @@ --- import Header from '@wheels-dev/ui/components/Header.astro'; import Footer from '@wheels-dev/ui/components/Footer.astro'; +import FontPreload from '@wheels-dev/ui/components/FontPreload.astro'; import '@wheels-dev/ui/styles/tokens.css'; import '@wheels-dev/ui/styles/base.css'; @@ -16,6 +17,7 @@ const { title, description = 'Wheels packages registry' } = Astro.props; + {title} diff --git a/web/sites/packages/src/pages/index.astro b/web/sites/packages/src/pages/index.astro index 13fad5f509..c3ecb3cf50 100644 --- a/web/sites/packages/src/pages/index.astro +++ b/web/sites/packages/src/pages/index.astro @@ -103,14 +103,14 @@ const packages = await listAll(); } .package-grid { display: grid; - grid-template-columns: 1fr; + grid-template-columns: minmax(0, 1fr); gap: 1rem; } @media (min-width: 640px) { - .package-grid { grid-template-columns: repeat(2, 1fr); } + .package-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } } @media (min-width: 960px) { - .package-grid { grid-template-columns: repeat(3, 1fr); } + .package-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } } .count-line { margin-top: 1.5rem; color: var(--color-fg-muted, #555); font-size: 0.875rem; } diff --git a/web/tests/visual-baselines/packages-index.png b/web/tests/visual-baselines/packages-index.png index 8e7a936e71..abf5bc73a8 100644 Binary files a/web/tests/visual-baselines/packages-index.png and b/web/tests/visual-baselines/packages-index.png differ