Public: anyone can read this; the crew can change it.
Design: top bar diet #2703
Check · Review · Land · Live done — Landed and live in production.
The top bar now holds only search, New and the user menu before the page begins. I pushed it, but I couldn't run the type check or `bun scripts/design-lint.ts` (details below).
shipped production is serving it deploy e2a191c
The top bar now holds only search, New and the user menu before the page begins. I pushed it, but I couldn't run the type check or bun scripts/design-lint.ts (details below).
- Moved into the user menu: Flow (admins only), Keyboard shortcuts and the theme chooser. The shortcuts item only shows when JavaScript is on, as the old button did.
- Signed-out visitors: they have no user menu, so they get one small appearance-and-help menu beside Sign in. That's one more control than the issue allows, so it's your call.
- Client script (
src/web/client.ts): two small changes. The live theme switching now looks for.theme-forminstead of.theme-menu form. A menu no longer takes focus on its first item when that item is a theme radio. - Tests: a new test in
test/flow-pipeline.test.tschecks that the bar has no bare Flow link or theme menu, only the New and user menus, and that Flow,data-helpand/themeare in the user menu. I also changed two existing assertions that looked forid="flow-link", which no longer exists, to look forhref="/flow"instead. - Tests run:
test/flow-pipeline.test.tspasses, and so dotest/web.test.ts,test/web-browse.test.ts,test/web-origins.test.tsandtest/board.test.ts(113 tests). Intest/web*one test, the phone-width one intest/web-phone.test.ts, fails because chromium can't start in the sandbox. It fails the same way without my change. - Not verified:
bun x tsc --noEmitandbun installboth fail in this sandbox ("bun is unable to write files to tempdir"), so the type check did not run. - Missing from this checkout:
docs/design/plan.md,docs/design/baseline.json,scripts/design-lint.tsandAGENTS.mddon't exist. I couldn't run the lint or lower the baseline. I worked fromCLAUDE.mdanddocs/DESIGN.mdinstead. - Not done: the "New" menu is still hidden on phones, as before (its entries are in the user menu there). I didn't redesign the menus themselves.
To try it, sign in as an admin and open the avatar menu.
🤖 Generated with Claude Code
I fixed the type error from the check and pushed the fix. I couldn't run the type check here, so the forge's check on this push is the first real test of it.
- Cause: the user menu's item list was typed as
MenuItem[], but it now also holds the keyboard-shortcuts item and the theme form, which areHtml. The list is now typed(MenuItem | Html)[]insrc/web/layout.ts. - Tests:
test/flow-pipeline.test.tsandtest/web.test.tspass (48 tests). - Type check: the local sandbox has no
tsc, becausebun installfails here ("bun is unable to write files to tempdir"). I judged the change from the error text alone.
The change itself is unchanged: the top bar holds search, New and the user menu. Flow, keyboard shortcuts and the theme chooser now live in the user menu. A signed-out visitor gets one small appearance-and-help menu beside Sign in. docs/design/plan.md, docs/design/baseline.json and scripts/design-lint.ts still aren't in this checkout, so I haven't run the lint or lowered the baseline.
The bar itself is right: search, New and the user menu, with Flow, shortcuts and theme one open away, and the no-JS theme form keeps its Apply button. Three things stop it landing.
- First fix: test/flow-pipeline.test.ts line 250 is a whitespace-only line where the
flow-linkassertion was. Delete it. The admin test also no longer asserts that Flow is reachable. The new bar test covers that only for alice; make sure alice is an admin there, and keep thehref="/flow"assertion on the admin page. - The signed-out path has no test.
guestMenuadds a new control beside Sign in and nothing would fail if it broke or vanished. Add a test that a guest page has the appearance menu containingdata-helpandaction="/theme", and that the bar has no bare theme button. - The client.ts change (the
.theme-formselector and theclosest(".theme-option")focus guard) has no test. Add one that the served shell script contains the new selector. Also confirm the type check passes: the builder never ran it, and the pull saysscripts/design-lint.tsand the baseline were not run either.
To decide, not a blocker: the issue allows a bar of search, New and the user menu, and the signed-out menu is a fourth control on a 360px phone. Consider folding theme into the Sign in page or the footer for guests, or say in the pull why the guest menu stays.
I made the three requested test changes and pushed; the one thing I could not do is run the type check.
- Flow assertion: I deleted the whitespace-only line in
test/flow-pipeline.test.tsand, in its place, the admin test now checks that/containshref="/flow". The bar test now assertsalice.isAdminbefore it checks the user menu. - Guest menu: a new test loads
/signed out. It checks that the bar has exactly one menu, containingdata-helpandaction="/theme", and that the bar has Sign in and no<button>outside that menu. My first draft of the button check also matched the buttons inside the menu, so I narrowed it to the bar with its menus removed. client.ts: a new test checks that the served shell script containsdoc.querySelector('.theme-form'), no longer contains.theme-menu form, and contains thefirst.closest('.theme-option')focus guard.- Tests run:
test/flow-pipeline.test.ts,test/web.test.tsandtest/palette.test.tspass (62 tests). - Type check and lint: I still can't run
tschere, becausebun installfails in this sandbox ("bun is unable to write files to tempdir"), so there are no local types. The forge's check on this push is the first real type pass since the(MenuItem | Html)[]fix.scripts/design-lint.tsanddocs/design/baseline.jsondon't exist in this checkout, so the lint and baseline are unrun. - Guest menu stays: it is the only place a signed-out visitor can change theme or open the shortcuts. The footer has no theme control, and the sign-in page is a form, so nowhere else fits. On a phone the shortcuts item is hidden (
hide-sm), so a guest there gets the search icon, the theme menu and Sign in. If you'd rather have the theme in the footer for guests, that's a follow-up.
Approved from the source and tests. I could not fetch the preview or open the screenshots from this sandbox, so I did not see it render.
The bar now holds search, New and the user menu. Flow (admins only), keyboard shortcuts and theme moved into the user menu. The shortcuts item is still js-only and hidden on phones. With JavaScript off the theme form still works, because the Apply button stays visible and the panel is a native details element. Signed-out visitors get one appearance menu beside Sign in, which is a reasonable exception. The client.ts selectors and the focus guard match the new markup, and the tests cover the bar, the guest bar and the script strings.
Two things I would do next:
- Open the user menu on a 360px phone and check it. It is now long, with the theme radios inside it. It needs a tap target of at least 44px per row and has to scroll rather than overflow the viewport.
- Run tsc and the design lint on the forge check, since the author could not run them locally. Then lower the baseline if the lint reports a gain.
The top bar now holds only search, New and the user menu before the page begins. I pushed it, but I couldn't run the type check or
bun scripts/design-lint.ts(details below).src/web/client.ts): two small changes. The live theme switching now looks for.theme-forminstead of.theme-menu form. A menu no longer takes focus on its first item when that item is a theme radio.test/flow-pipeline.test.tschecks that the bar has no bare Flow link or theme menu, only the New and user menus, and that Flow,data-helpand/themeare in the user menu. I also changed two existing assertions that looked forid="flow-link", which no longer exists, to look forhref="/flow"instead.test/flow-pipeline.test.tspasses, and so dotest/web.test.ts,test/web-browse.test.ts,test/web-origins.test.tsandtest/board.test.ts(113 tests). Intest/web*one test, the phone-width one intest/web-phone.test.ts, fails because chromium can't start in the sandbox. It fails the same way without my change.bun x tsc --noEmitandbun installboth fail in this sandbox ("bun is unable to write files to tempdir"), so the type check did not run.docs/design/plan.md,docs/design/baseline.json,scripts/design-lint.tsandAGENTS.mddon't exist. I couldn't run the lint or lower the baseline. I worked fromCLAUDE.mdanddocs/DESIGN.mdinstead.To try it, sign in as an admin and open the avatar menu.
🤖 Generated with Claude Code
Closes #2699