feat(header): one plane of chrome, and menus a keyboard can reach - #75
Merged
Conversation
The right third of the header read as three unrelated widgets rather than as a toolbar: the canvas actions, the history pair and the file actions each carried their own soft pill, with hairline separators between them as well -- two devices doing one job. They are one ground now, with rules inside it where one kind of control ends and the next begins. The model picker moved from beside the wordmark into the right cluster, joined with the wizard button into one control -- both are about the machine rather than the canvas, and next to the logo the picker read as branding, leaving the app's one piece of standing information as far as possible from the controls that act on it. The Tools dropdown is gone: the three auxiliary views are rows in the More menu now, which removes a second header menu whose only job was to be mutually exclusive with the first. Every menu in the header closes the same ways. Escape and a window blur run one shared dismissHeaderMenus() across the More menu, the tab overflow list, the save menu and the model picker. The picker's outside click no longer races its own opening click (guardNextClose over a requestAnimationFrame, rather than setTimeout(0)), and a second press of its trigger closes it -- a regression the first rewrite introduced, where the second press was a no-op. The rows are keyboard-reachable. The .ctx-i rows, the model items and the tab overflow listbox carried no focus at all; they now take tabindex, Enter/Space activation, arrow-key roving focus, and aria-selected/aria-disabled where those apply. Focus rings that were mixed from --focus-ring (alpha .08-.14, invisible against the header's ground) are mixed from the accent instead, and bare-key canvas shortcuts stand down while a menu row has focus. The three clusters stand at the same height. The tab strip, the machine pill and the toolbar are all 36px, where the pill was 4px shorter than both its neighbours -- the toolbar had only arrived at 36 incidentally (30px buttons, 2px padding and the new 1px border) and the pill was never raised with it. Around the canvas, the well's radius and sill widen to 14px and all four corners curve. The top two used to be squared on the reasoning that the workspace tabs stand on that edge, but the uncovered quarter is the concave corner each panel appears to have, and the artifact under the tabs was the grid, which is fixed where the grid is -- a short mask ramp at the top of it. css/chrome-polish.css is the finishing layer for this pass: one toolbar plane, tab recessing, section-header focus cues and panel scrollbars. The panel-tab seam it briefly duplicated is consolidated back into css/panels.css as the one declaration for both sidebars, with CLAUDE.md updated to match, and the dead .hdr-tools rule (its element went with the Tools dropdown) is deleted.
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
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.
What this changes
A restructure and finishing pass over the app's persistent chrome — the header and the frame around the canvas.
The header
Every menu closes the same ways
dismissHeaderMenus()injs/ui.jsis one shared closer for all four header menus — More, tab overflow, save, model picker — run by Escape (ahead of the rest of its ladder) and by window blur, so a menu can't sit open behind the window. The model picker's outside-click no longer races its own opening click (guardNextCloseover arequestAnimationFrameinstead ofsetTimeout(0)), and a second press of its trigger closes it.Keyboard access
The menu rows were
<div onclick>s — invisible to Tab and untriggerable without a mouse. They now carrytabindex, Enter/Space activation, ↑/↓ roving focus, andaria-selected/aria-disabledwhere those apply (the tab overflow list is a proper listbox, the model list proper options). Focus rings that were mixed from--focus-ring— an alpha .08–.14 token, invisible against the header's ground — are mixed from the accent instead, and bare-key canvas shortcuts stand down while a menu row has focus.One height
The tab strip, the machine pill and the toolbar all stand at 36px, where the pill was 4px shorter than both neighbours.
Around the canvas
The well's radius and sill widen to 14px and all four corners curve. The top two used to be squared on the reasoning that the workspace tabs stand on that edge — but the uncovered quarter is the concave corner each panel appears to have, and the artifact under the tabs was the grid, which is now masked with a short ramp at its top edge.
css/chrome-polish.cssis new: the finishing layer for this pass (toolbar plane, tab recessing, section-header focus cues, panel scrollbars). The panel-tab seam it briefly duplicated is consolidated back intocss/panels.cssas the one declaration for both sidebars, and CLAUDE.md is updated to match.Verification
npm test— 1946/1946 passingnpm run build— clean