feat(ui): add menu bar visibility toggle#476
Conversation
Greptile SummaryThis PR adds a menu bar visibility toggle for keyboard-driven review sessions. Users can now hide the top chrome via
Confidence Score: 5/5The change is additive and defaults to the existing behavior (menu bar on), so no existing session is disrupted. The full config pipeline is wired correctly with safe fallbacks, keyboard dispatch guards against double-firing, and two new integration tests cover the core toggle and bootstrap flows end-to-end. The only code worth a second look is the cross-parameter default in DiffPane, which is valid but fragile — it is a style issue, not a runtime concern. DiffPane.tsx — the showTopChrome default references another destructured param and would silently misbehave if parameter order changed. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[User action] --> B{Source}
B -->|Shift-M key| C[isUppercaseMKey]
B -->|View > Menu bar| D[toggleMenuBar in appMenus]
B -->|config file menu_bar=false| E[initialShowMenuBar in bootstrap]
C --> F[toggleMenuBar]
D --> F
E --> G[showMenuBar state initialized false]
F --> H[setShowMenuBar toggle]
H --> I{showMenuBar}
G --> I
I -->|true| J[MenuBar rendered at row 0]
I -->|false| K[MenuBar hidden]
J --> L[diffPaneScreenTop = 1]
K --> M[diffPaneScreenTop = 0]
J --> N[DiffPane showTopChrome=true]
K --> O[DiffPane showTopChrome=false]
J --> P[SidebarPane showTopChrome=true]
K --> Q[SidebarPane showTopChrome=false]
J --> R[MenuDropdown top=1]
K --> S[MenuDropdown top=0]
N --> T[border top + paddingTop=1]
O --> U[no border + paddingTop=0]
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
A[User action] --> B{Source}
B -->|Shift-M key| C[isUppercaseMKey]
B -->|View > Menu bar| D[toggleMenuBar in appMenus]
B -->|config file menu_bar=false| E[initialShowMenuBar in bootstrap]
C --> F[toggleMenuBar]
D --> F
E --> G[showMenuBar state initialized false]
F --> H[setShowMenuBar toggle]
H --> I{showMenuBar}
G --> I
I -->|true| J[MenuBar rendered at row 0]
I -->|false| K[MenuBar hidden]
J --> L[diffPaneScreenTop = 1]
K --> M[diffPaneScreenTop = 0]
J --> N[DiffPane showTopChrome=true]
K --> O[DiffPane showTopChrome=false]
J --> P[SidebarPane showTopChrome=true]
K --> Q[SidebarPane showTopChrome=false]
J --> R[MenuDropdown top=1]
K --> S[MenuDropdown top=0]
N --> T[border top + paddingTop=1]
O --> U[no border + paddingTop=0]
Prompt To Fix All With AIFix the following 1 code review issue. Work through them one at a time, proposing concise fixes.
---
### Issue 1 of 1
src/ui/components/panes/DiffPane.tsx:194
The default `showTopChrome = !pagerMode` relies on the sequential evaluation of destructuring parameters — `pagerMode` must stay above `showTopChrome` in this list for the expression to work correctly. If the parameters are ever reordered, `pagerMode` will be `undefined` at the point of evaluation, silently flipping the default to `true`. An explicit `false` default keeps the intent self-contained and doesn't depend on declaration order.
```suggestion
showTopChrome = false,
```
Reviews (1): Last reviewed commit: "fix(ui): hide menu chrome separator with..." | Re-trigger Greptile |
Summary
This adds a dedicated way to hide Hunk's top menu bar for keyboard-driven review sessions. When the menu bar is hidden, the diff/sidebar layout moves up and reclaims that first terminal row for review content.
The default stays unchanged: Hunk still shows the menu bar unless a user opts out. That keeps the current UI discoverable for new users while giving experienced users a lower-chrome mode on short terminals.
Refs #459.
Demo
2026.06.22.23.08.16.mp4
How to use it
menu_bar = falsein~/.config/hunk/config.tomlor.hunk/config.tomlto start with the menu bar hiddenShift-Mduring a session to toggle the menu bar on or offView > Menu barwhen the menu is visibleBehavior
Hiding the menu bar also hides the separator/chrome row beneath it, so the review content moves all the way to the top.
Hiding the menu bar does not disable menus.
F10still opens the keyboard menu, and when the bar is hidden the dropdown appears at the top row instead of leaving an empty chrome row behind.Lowercase
mcontinues to toggle hunk metadata.Shift-Mis only for the menu bar.Testing
bun run formatbun run format:checkbun run typecheckbun test src/core/config.test.ts src/ui/lib/ui-lib.test.ts src/ui/AppHost.interactions.test.tsx src/ui/components/ui-components.test.tsxbun run test:tty-smokebun run src/main.tsx -- diff <before> <after>