Progressive nav collapse — Tools group → "More ▾" dropdown before hamburger¶
Motivation¶
The top navigation collapsed to the hamburger drawer at a single breakpoint (1320 px), meaning the entire nav disappeared in one step when a user resized the window from a wide desktop to a 13" laptop / external monitor at 1280 px. The Tools group (Lab Tools, Terminal, API) is the lowest-priority cluster — primary entry points (Dashboard, New Search, Recent searches) deserve to stay visible longer.
User-facing change¶
- Tier A — ≥1320 px (unchanged): full horizontal nav with Monitor / BLAST / Tools groups inline.
- Tier B — 720–1320 px (new): the Tools group (Lab Tools,
Terminal, API) collapses into a
More ▾dropdown anchored at the right of the nav. Monitor + BLAST stay first-class horizontally. The trigger picks up the.activehighlight + a small dot when the current route lives inside the dropdown (e.g. you are on/docsand theMorechip glows so you still know "you are here"). - Tier C — <720 px (unchanged behaviour, moved breakpoint): the existing hamburger drawer takes over. Every nav item is listed vertically as before.
The dropdown closes on outside click, on Escape, and when the user
selects any item inside (so the page transition isn't blocked by an
open popover).
API / IaC diff summary¶
| Layer | File | Change |
|---|---|---|
| Hook | web/src/hooks/useMediaQuery.ts (new) | Shared SSR-safe useMediaQuery(query) hook. Two existing call sites (useGettingStartedReadiness, visibilityHooks) keep their inline copies for now — they can migrate in a follow-up. |
| Component | web/src/components/NavMoreDropdown.tsx (new) | Glass dropdown for nav overflow. Click-outside + Escape close. MutationObserver on its children watches React Router's .active class so the trigger reflects "you are on a route inside this menu". |
| Layout | web/src/components/Layout.tsx | Added useMediaQuery calls → isCompactNav / isMobileNav / useToolsDropdown flags. Tools group is rendered either inline (Tier A) or inside NavMoreDropdown (Tier B). Tier C continues to render the inline variant (the drawer stacks it vertically — no nested dropdown). |
| Styles | web/src/components/Layout.css | Hamburger media-query breakpoint moved from max-width: 1320px to max-width: 720px. New .layout__nav-more, .layout__nav-more-trigger, .layout__nav-more-panel, .layout__nav-more-dot rules. |
No backend change. No new dependency.
Validation evidence¶
cd web && npx tsc -p tsconfig.json --noEmiton the changed files → clean.cd web && npx eslint src/components/Layout.tsx src/components/NavMoreDropdown.tsx src/hooks/useMediaQuery.ts→ clean.cd web && npm run build→ ✓ built in 9.71s (the existing chunk-size warning is unrelated).- DevTools responsive mode walkthrough at 1920 → 1320 → 1100 → 800 → 600 px:
- 1920–1320 px: full nav (Tier A).
- 1320 → 720 px: Tools group disappears from inline,
More ▾appears on the right. Clicking it opens a panel with Lab Tools (when enabled) / Terminal (when enabled) / API. Navigating to API →Morechip highlights with a dot. ESC / outside click closes the panel. - Below 720 px: hamburger appears, nav becomes the vertical drawer with every item (drawer renders the inline branch, not the dropdown).
Follow-ups (not in this PR)¶
- The two existing inline
useMediaQuery-style hooks (useGettingStartedReadiness,SidecarsCard/visibilityHooks) can migrate to the new shared hook in a tidy-up commit — left alone here to keep the diff focused on the responsive nav behaviour. - If "API" turns out to be heavily used at Tier B, lifting it out of the dropdown (and only collapsing Lab Tools + Terminal) is a one-line JSX change.