feat: dual-font typography, nav + hero refresh, and Heroicons migration#311
Merged
Conversation
Replace the site's hand-inlined SVG icons with the @heroicons/react library so all UI icons come from one consistent source. The previous inline paths were Heroicons already, so the visual result is unchanged while the markup gets far leaner. Brand logos (LinkedIn, GitHub, Bluesky), the service-status loading spinner, and the breadcrumb separator have no Heroicon equivalent and stay inline.
Introduce a dual-font system: Bricolage Grotesque for headings and Hanken Grotesk for body and UI. The display font is applied on the global heading layer, so all MDX content (news, events, services, projects) inherits it with no per-page changes. Load both faces through Astro's Fonts API (self-hosted, preloaded, CLS-safe) and drop the render-blocking Google Fonts @import. This also removes the visitor-to-Google request, matching the site's self-hosted analytics posture.
Shrink the oversized logo, lighten nav link weight to medium, and tighten letter tracking so the bar sits better with the new fonts. The magic-pill glider, About dropdown, mobile accordion, focus rings, and reduced-motion handling are all preserved. Nav icons also move to @heroicons/react.
Render the hero particle field as connected circular nodes instead of unconnected triangles, and strengthen the linking edges so it reads as a network graph. Modernize the Explore services and Get support buttons with a larger radius, colored elevation, a leading support icon, and a hover that scales instead of translating. The translate lifted the button out from under the cursor near its bottom edge and caused a hover jitter loop; scaling keeps the pointer inside the box. The scale is gated behind motion-safe for reduced-motion users.
Escape was handled only by the search input's onKeyDown, which requires the input to be focused. Clicking the results area blurs the input, so Escape stopped working there while the backdrop click still dismissed. Add a document-level Escape listener that runs while the palette is open, so it closes regardless of what holds focus. Also migrates the result-type icons to @heroicons/react.
There was a problem hiding this comment.
Pull request overview
This PR implements a visual refresh centered on typography, navigation, and the hero section, while also standardizing icons across the site by migrating inline SVGs/react-icons usages to @heroicons/react. It also includes a functional fix to ensure the command palette reliably closes on Escape.
Changes:
- Introduce a dual-font system via Astro’s experimental Fonts API and Tailwind font families (body + display).
- Migrate many inline SVG icons to
@heroicons/reactacross pages, layouts, and components. - Refresh hero visuals (particle rendering + CTA styling) and improve command palette Escape-to-close behavior.
Reviewed changes
Copilot reviewed 36 out of 37 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| tailwind.config.mjs | Switch Tailwind sans to CSS-variable-driven body font and add a display font family. |
| src/styles/global.scss | Remove Google Fonts @import and apply font-display to heading elements globally. |
| astro.config.mjs | Configure Astro experimental Fonts API for body/display fonts. |
| src/layouts/base.astro | Add <Font> preload tags for the configured CSS variables. |
| src/pages/training/index.astro | Replace multiple inline SVGs with Heroicons components. |
| src/pages/services/index.astro | Replace inline SVG “Learn more”/“Web” icons with Heroicons. |
| src/pages/research-support.astro | Replace inline SVG icons (CTA + feature lists) with Heroicons. |
| src/pages/news/index.astro | Replace inline SVG icons in cards with Heroicons. |
| src/pages/funding-and-projects/index.astro | Replace search/meta/CTA SVG icons with Heroicons. |
| src/pages/events/index.astro | Replace event card/empty-state SVG icons with Heroicons. |
| src/pages/about/everyone.astro | Replace navigation/action SVG icons with Heroicons. |
| src/layouts/page.astro | Replace content meta/back/external-link SVG icons with Heroicons. |
| src/components/site-banner.astro | Replace banner icons with Heroicons. |
| src/components/share-buttons.tsx | Replace share button SVG icons with Heroicons. |
| src/components/service-status.tsx | Replace status summary SVG icons with Heroicons. |
| src/components/service-status-summary.tsx | Replace arrow SVG icon with Heroicons. |
| src/components/sections/services-overview.tsx | Replace service card icons and arrow icons with Heroicons. |
| src/components/sections/org-hero.astro | Replace “back” SVG icon with a Heroicon. |
| src/components/sections/org-contact.astro | Replace contact/link/callout/location SVG icons with Heroicons. |
| src/components/sections/latest-news.astro | Replace multiple CTA/navigation SVG icons with Heroicons. |
| src/components/project-filters.tsx | Replace filter UI SVG icons with Heroicons. |
| src/components/pricing.tsx | Replace feature-list check SVG icon with a Heroicon. |
| src/components/people.astro | Replace CTA arrow SVG icon with a Heroicon. |
| src/components/particle-field.tsx | Adjust connection rendering and switch particles from triangles to circular nodes. |
| src/components/navigation.tsx | Replace search icon SVG with Heroicon and tweak nav typography/spacing. |
| src/components/nav-mobile-accordion.tsx | Replace chevron SVG with Heroicon. |
| src/components/nav-dropdown.tsx | Replace chevron SVG with Heroicon and tweak dropdown link typography/spacing. |
| src/components/nav-about-menu.tsx | Replace arrow SVG icon with Heroicon. |
| src/components/listing-filters.tsx | Replace filter UI SVG icons with Heroicons. |
| src/components/highlights-carousel.tsx | Replace carousel control/play-pause SVG icons with Heroicons. |
| src/components/hero.tsx | Update hero CTA styling, migrate icons to Heroicons, and adjust scroll cue icon implementation. |
| src/components/featured-news.astro | Replace react-icons arrow with Heroicon. |
| src/components/command-palette.tsx | Replace icon path map with Heroicon components and add document-level Escape handling when open. |
| src/components/carousel.tsx | Replace react-icons + inline close SVG with Heroicons. |
| src/components/callout.tsx | Replace inline SVG variant icons with Heroicons. |
| package.json | Add @heroicons/react dependency. |
| pnpm-lock.yaml | Lockfile updates for @heroicons/react addition. |
Files not reviewed (1)
- pnpm-lock.yaml: Generated file
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+11
to
+12
| sans: ['var(--font-body)', ...defaultTheme.fontFamily.sans], | ||
| display: ['var(--font-display)', ...defaultTheme.fontFamily.sans], |
The /admin page renders its own HTML shell (not base.astro) and never mounts the <Font> components, so --font-body was undefined there. A bare var() with no fallback is invalid-at-computed-value-time, which dropped the whole font-family to the initial serif. Add an inline fallback so any page without the font vars degrades to system sans instead.
banner-pulse is defined in the component's scoped <style>, which compiles to a selector requiring the Astro scope attribute. A Heroicon React component's SVG never receives that attribute, so the pulse silently stopped matching. Render the megaphone as an inline SVG (it carries the scope attribute) to restore the animation.
The fixed-header spacer must match the -mt/pt-[84px] offsets the hero and org pages use to sit under the nav. Shrinking it to 76px left the hero overshooting its reserved space by 8px.
Heroicons render at stroke-width 1.5; the selected-filter checkmark was originally 3, so pass it explicitly to keep the checked state legible at 12px. Also update a comment that still named the old font.
…ilds Switch the Fonts API from the Google provider to the local provider and commit the two variable woff2 files (Hanken Grotesk, Bricolage Grotesque) under src/assets/fonts. The build no longer fetches from Google at build time, so CI and offline builds are reproducible. Runtime output is unchanged: same self-hosted, preloaded, latin-subset variable fonts, headings at Bricolage 700 and body at Hanken 400 (verified). Pin Astro to ~5.18.1 so the experimental Fonts API cannot change shape on a minor bump.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
A visual-redesign increment focused on typography and the nav/hero, plus a
codebase-wide icon cleanup and two bug fixes. Content (MDX), routes, and the
asset pipeline are untouched.
Typography: self-hosted dual-font system
(news, events, services, projects) inherits it with no per-page edits.
render-blocking Google Fonts
@import, which also removes the visitor-to-Google request (consistent with the self-hosted analytics setup).
Navigation refinement
and reduced-motion handling.
Hero
triangles), with stronger linking edges: reads as a network graph.
Explore services/Get supportCTAs: larger radius, coloredelevation, a leading support icon, and a jitter-free hover (scale rather than
translate, which slid the button out from under the cursor near its edge).
Icon library migration
single consistent icon source. The inline paths were already Heroicons, so
the look is unchanged and the markup is much leaner.
Bluesky), the service-status loading spinner, and the breadcrumb separator.
Fixes
the search input (clicking the results area used to blur the input and kill
Escape, while the backdrop click still worked).
Verification
astro buildpasses (184 pages);astro checkreports 0 errors.and the homepage service cards.
Notes
astro.config.mjs+tailwind.config.mjsif a different combination is preferred.services-overviewrenders an<a>inside an
<a>(inline links inside a card that is itself a link), whichtriggers a React
validateDOMNestingwarning. Worth a separate fix.