Skip to content

feat: dual-font typography, nav + hero refresh, and Heroicons migration#311

Merged
yasinmiran merged 10 commits into
mainfrom
redesign/typography-nav
Jul 10, 2026
Merged

feat: dual-font typography, nav + hero refresh, and Heroicons migration#311
yasinmiran merged 10 commits into
mainfrom
redesign/typography-nav

Conversation

@yasinmiran

Copy link
Copy Markdown
Collaborator

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

  • Bricolage Grotesque for headings, Hanken Grotesk for body/UI.
  • The display font is applied on the global heading layer, so every MDX page
    (news, events, services, projects) inherits it with no per-page edits.
  • Loaded via Astro's Fonts API: self-hosted, preloaded, CLS-safe. Drops the
    render-blocking Google Fonts @import, which also removes the visitor-to-
    Google request (consistent with the self-hosted analytics setup).

Navigation refinement

  • Smaller logo, medium link weight, tighter tracking to match the new fonts.
  • Keeps the magic-pill glider, About dropdown, mobile accordion, focus rings,
    and reduced-motion handling.

Hero

  • Particle field is now connected circular nodes (was unconnected
    triangles), with stronger linking edges: reads as a network graph.
  • Modernized Explore services / Get support CTAs: larger radius, colored
    elevation, 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

  • Migrated the site's hand-inlined SVG icons to @heroicons/react for a
    single consistent icon source. The inline paths were already Heroicons, so
    the look is unchanged and the markup is much leaner.
  • Kept inline (no Heroicon equivalent): brand logos (LinkedIn, GitHub,
    Bluesky), the service-status loading spinner, and the breadcrumb separator.

Fixes

  • Command palette: Escape now closes the palette even after focus leaves
    the search input (clicking the results area used to blur the input and kill
    Escape, while the backdrop click still worked).
  • Button hover jitter: resolved via the scale-based hover above.

Verification

  • astro build passes (184 pages); astro check reports 0 errors.
  • All client islands hydrate; theme toggle and command palette work.
  • Icons spot-checked in light and dark across home, services, research-support,
    and the homepage service cards.

Notes

  • The heading/body pairing is easy to swap in astro.config.mjs +
    tailwind.config.mjs if a different combination is preferred.
  • Pre-existing (not introduced here): services-overview renders an <a>
    inside an <a> (inline links inside a card that is itself a link), which
    triggers a React validateDOMNesting warning. Worth a separate fix.

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.
Copilot AI review requested due to automatic review settings July 10, 2026 12:38

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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/react across 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 thread tailwind.config.mjs Outdated
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.
@yasinmiran
yasinmiran merged commit 23020fc into main Jul 10, 2026
1 check passed
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.

2 participants