Skip to content

feat(nav): add shared top bar with search and menu - #44

Merged
yungsamd17 merged 5 commits into
mainfrom
feat/nav-toolbar
Oct 21, 2026
Merged

yungsamd17 merged 5 commits into
mainfrom
feat/nav-toolbar

Conversation

@yungsamd17

@yungsamd17 yungsamd17 commented Sep 29, 2026 •

Copy link
Copy Markdown
Member

Every page except the home page now gets a sticky top bar rendered by BaseLayout: back link, page header, search, and a menu. Home gets a floating search button instead, so the landing page stays a clean hero. The old per-page headers, and the script that measured whether the back-link label would collide with the title, are both gone.

Search (/ or Cmd/Ctrl-K) indexes tools, projects, pages, and /design/ sections straight from the existing registries — there is no separate index to keep in sync, so a new tool or section is searchable as soon as it's registered.

Before / after

Page headers Menu and search
Page headers, before and after: home page, tools listing, tool page Menu and search, before and after: scrolled bar, hamburger menu, search on desktop and mobile

What changed, in short:

  • Page header — a static centred h1 on each page becomes one sticky bar rendered by BaseLayout.
  • Back link — the label was measured at runtime and collapsed to the arrow by a script; it now collapses in CSS under 580px, so BackLinkFit.astro and back-link.ts are deleted. The control is a rounded-square button with the same accent hover/press as the rest of the bar.
  • Bar — invisible at scroll top (page-coloured, no rule), then blur + hairline fade in. Every bar is 900px; the page column keeps its own measure, so on the tools and projects listings the bar deliberately overhangs the cards. Previously the bar was 680px on tools and 900px on projects, so it jumped 110px between them.
  • Home page — no toolbar at all, just a floating search button.
  • Tool pages — 640px panels become 680px so all four standard tools match; Icon Maker keeps 900px.
  • Search — / or Cmd/Ctrl-K over tools, projects, pages, and /design sections. Verdana input, one line box whether empty or filled, ✕ clears and is hidden with no query. Design sections stay out of the menu and are reachable by search, so the menu stays short enough to scan in one glance.
  • Text selection — default blue becomes the accent tint site-wide (it was accent only on /tools/).

Touched

  • src/components/ — new TopBar.astro, SearchDialog.astro, SearchFab.astro; BackLinkFit.astro removed
  • src/layouts/BaseLayout.astro — renders the bar (or the FAB) and the dialog once for every page
  • src/scripts/topbar.ts — new: menu disclosure, search, scroll-aware bar, global keys; back-link.ts removed
  • src/data/nav.ts — new: site links and /design/ sections, shared by the menu, search, and the /design/ pill nav
  • src/icons.ts — bars, search, xmark glyphs
  • src/pages/** — pages pass barTitle/backHref/barWidth instead of hand-rolling headers; /tools/, /projects/, and three tool pages adjusted to the 680 column
  • src/styles/global.css — bar + menu + search + FAB styles; chrome tokens promoted here; accent ::selection site-wide
  • src/styles/tool.css, src/styles/design.css — retired .back-link/.tool-header/.ds-hero; anchor offset for the sticky bar
  • docs/, README.md, AGENTS.md — architecture map, the bar/content measure rule, and the token table

Merge with main

main moved ahead while this PR was open (PR #45 and the tool-card polish commit), so the branch now carries a merge of main (97f49b5). The conflicts were resolved like this:

  • src/components/BackLinkFit.astro and src/scripts/back-link.ts — deleted. The bar measures nothing at runtime, so the fit component and its script have no callers left. This also retires main's resize-reflow fix on back-link.ts, which only existed to throttle that script.
  • src/styles/tool.css — dropped the .back-link fit rules along with the component; the bar's back label is styled in global.css.
  • src/pages/design.astro — kept ColorField from main, dropped the BackLinkFit import; the colour specimens use the shared picker.
  • AGENTS.md, docs/README.md — merged both sides: the top-bar entries stay, and main's ColorField, color-picker and range-fill entries are added alongside them.

Nothing from either side was dropped: main's colour picker, the slider fill trails and the 100svh mobile-scroll fix all survive the merge, and the bar is unchanged.

One extra fix

Merging surfaced a regression that was already on main: PR #45 gated .tool-item:hover behind @media (hover: hover) so the accent wash and the arrow nudge would not stick after a tap on touch, but the later tool-card polish commit rewrote both rules and dropped the gate. This branch restores the gate in its own commit — the :focus-visible rule stays outside the media query, so keyboard focus still moves the arrow.

Notes for review

  • The bar and the page column are separate widths. Every bar is 900px; the column below keeps its own measure (680px on the tools/projects listings and tool pages, 900px on the design/policy pages and Icon Maker). So the bar overhangs the content on most pages — that's deliberate, and it's documented in AGENTS.md so it doesn't get "fixed" later.
  • The header size is hand-tuned, not measured. Aldrich's baseline lands level with the icon row and a 1px translateY is the optical correction; the comment in global.css records the measured numbers so it isn't re-derived.
  • Search still works with JavaScript off in the sense that nothing throws — but the bar's menu and search are progressive enhancements, so they need JS. Nothing else on the site depends on it.

Testing

  • npx astro check — 0 errors
  • npm run build — 12 pages, clean
  • Menu: open/close, Escape, click-away, scroll lock released, / and design sections reachable
  • Search: / and Cmd/Ctrl-K, arrow navigation, Enter opens the active result, Escape and backdrop close
  • Search on a same-page result (a /design/ section) closes the dialog as well as navigating
  • Clear button hidden when empty, clears when there is a query, focus stays in the field
  • Focus stays in the dialog (Tab trap) and never lands in a page input on close
  • Bar: transparent at scroll top, blur + hairline fade in on scroll
  • Back link present on every page that should have one, desktop and mobile, and navigates
  • Bar and content measures measured at 412 / 700 / 768 / 900 / 1280px
  • No console errors on desktop, Pixel 7, or iPhone 13 emulation
  • All internal search result links resolve (no 404s)
  • Scrolled through all 9 pages and every tool
  • Re-ran npx astro check and npm run build on the merged branch — 0 errors, 12 pages, clean
  • Hover gate re-applied: .tool-item:hover and the arrow nudge are behind @media (hover: hover); :focus-visible still moves the arrow outside the query

Built with space-bunny-free in the OpenCode harness, running in T3 Code.

Replace the per-page headers with one sticky top bar rendered by
BaseLayout: back link, page header, search, and a menu on every page
except the home page, which gets a floating search button instead.

- TopBar/SearchDialog/SearchFab components plus src/scripts/topbar.ts
  for the menu disclosure, client-side search, and scroll-aware bar
- Search indexes tools, projects, pages, and /design/ sections straight
  from the existing registries, so there is no separate index to keep in
  sync; "/" and Cmd/Ctrl-K open it, arrows navigate, Enter opens, Esc closes
- src/data/nav.ts is the single source for site links and design sections,
  shared by the menu, search, and the /design/ pill nav
- Retire BackLinkFit.astro and back-link.ts: a three-slot 1fr auto 1fr
  grid gives the back label room to breathe, so it no longer needs
  measuring, and the label can collapse in CSS instead of by script
- Promote the shared chrome tokens (surface ladder, border, radius,
  motion) into global.css so the bar and footer never depend on tool.css
- Accent-red ::selection site-wide, replacing the copy scoped to /tools/
- /design/ gains live specimens for the bar, menu, FAB, and search field,
  plus updated token and typography tables
The bar and the content are now independent widths rather than one
number driving both. Every page with a bar runs it at 900px; the page
column below keeps whatever its own shell uses. On the tools and
projects listings the bar is therefore deliberately wider than the
cards, and on the tool pages it is wider than the panels.

The bar's 20px side padding still matches the page columns, so wherever
the two measures do match — the design, policy, and Icon Maker pages —
they still line up exactly.
…680 column

Those three pinned maxWidth={640} on ToolLayout, overriding its 680
default, so they were 40px narrower than Case Converter for no stated
reason. Dropping the override puts all four standard tools on one
measure; Icon Maker keeps its 900 column.
@github-actions

Copy link
Copy Markdown

✅ PR Checks passed

Typecheck (npx astro check) and production build both green.

@yungsamd17 yungsamd17 self-assigned this Sep 29, 2026
Brings the top-bar branch up to date with main (PR #45 and the tool-card
polish commit).

Conflict resolutions:

- src/components/BackLinkFit.astro, src/scripts/back-link.ts — deleted.
  The bar measures nothing at runtime; the label collapses in CSS under
  580px, so the fit component and its script have no callers left. This
  also retires main's resize-reflow fix on back-link.ts, which only
  existed to throttle that script.
- src/styles/tool.css — dropped the .back-link fit rules along with the
  component; the bar's back label is styled in global.css.
- src/pages/design.astro — kept ColorField (main) and dropped the
  BackLinkFit import; the colour specimens now use the shared picker.
- AGENTS.md, docs/README.md — merged both sides: the top-bar entries
  stay, and main's ColorField, color-picker and range-fill entries are
  added alongside them.
PR #45 gated `.tool-item:hover` behind `@media (hover: hover)` so the
accent wash and the 3px arrow nudge would not stick after a tap on
touch. The later tool-card polish commit rewrote both rules and
dropped the gate, so the fix was lost on main.

Put the gate back around the wash and the arrow nudge. The
`:focus-visible` rule stays outside the media query, so keyboard
focus still moves the arrow.
@yungsamd17
yungsamd17 merged commit bb63b21 into main Oct 21, 2026
2 checks passed
@yungsamd17
yungsamd17 deleted the feat/nav-toolbar branch October 26, 2026 15:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant