-
Notifications
You must be signed in to change notification settings - Fork 186
Fix keyboard help dialog row overlap #122
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -836,27 +836,56 @@ describe("UI components", () => { | |
| expect(frame).toContain("beta"); | ||
| }); | ||
|
|
||
| test("HelpDialog renders the grouped keyboard help modal", async () => { | ||
| test("HelpDialog renders every keyboard shortcut row without overlap", async () => { | ||
| const theme = resolveTheme("midnight", null); | ||
| const frame = await captureFrame( | ||
| <HelpDialog | ||
| canRefresh={true} | ||
| terminalHeight={20} | ||
| terminalHeight={28} | ||
| terminalWidth={76} | ||
| theme={theme} | ||
| onClose={() => {}} | ||
| />, | ||
| 76, | ||
| 20, | ||
| 28, | ||
| ); | ||
|
|
||
| expect(frame).toContain("Keyboard help"); | ||
| expect(frame).toContain("[Esc]"); | ||
| expect(frame).toContain("Navigation"); | ||
| expect(frame).toContain("View"); | ||
| expect(frame).toContain("Review"); | ||
| expect(frame).toContain("F10"); | ||
| expect(frame).toContain("reload / quit"); | ||
| const expectedRows = [ | ||
| "Keyboard help", | ||
| "[Esc]", | ||
| "Navigation", | ||
| "↑ / ↓ move line-by-line", | ||
| "Space / f page down (alt: f)", | ||
| "b page up", | ||
| "Shift+Space page up (alt)", | ||
| "d / u half page down / up", | ||
| "[ / ] previous / next hunk", | ||
| "Home / End jump to top / bottom", | ||
|
Comment on lines
+839
to
+863
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
The updated test validates that content renders without overlap when the terminal is large enough ( Consider adding a companion test that renders at a smaller terminal height (e.g.,
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fair point. I kept this PR focused on the overlap regression path and asserted the full visible help content that was previously getting corrupted. I’d rather cover the small-terminal scroll fallback in a separate follow-up test than broaden this fix further. |
||
| "View", | ||
| "1 / 2 / 0 split / stack / auto", | ||
| "s / t sidebar / theme", | ||
| "a toggle AI notes", | ||
| "l / w / m lines / wrap / metadata", | ||
| "Review", | ||
| "/ focus file filter", | ||
| "Tab swap files / filter focus", | ||
| "F10 open menus", | ||
| "r / q reload / quit", | ||
| ] as const; | ||
|
|
||
| for (const expectedRow of expectedRows) { | ||
| expect(frame).toContain(expectedRow); | ||
| } | ||
|
|
||
| const lines = frame.split("\n"); | ||
| const blankModalRow = /│\s+│/; | ||
| const viewHeaderIndex = lines.findIndex((line) => line.includes("│ View")); | ||
| const reviewHeaderIndex = lines.findIndex((line) => line.includes("│ Review")); | ||
|
|
||
| expect(lines[viewHeaderIndex - 1]).toMatch(blankModalRow); | ||
| expect(lines[reviewHeaderIndex - 1]).toMatch(blankModalRow); | ||
| expect(frame).not.toContain("linese/Awrapt/smetadata"); | ||
| expect(frame).not.toContain("reloade/uquit"); | ||
| }); | ||
|
|
||
| test("DiffSectionPlaceholder preserves offscreen section chrome without mounting rows", async () => { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
modalFrameChromeRowCountmay be off by oneThe comment says the 6 accounts for "border rows, title row, padding, and one blank spacer row," but tracing through
ModalFrame's JSX I can only identify 5 rows of overhead:border: true)paddingTop: 1on the header boxpaddingBottom: 1on the content boxThere is no explicit blank spacer element in
ModalFrame. If the real chrome overhead is 5,requiredModalHeightis overestimated by 1 — the modal will be 1 row taller than necessary in normal conditions, andshouldScrollwill trigger one terminal row earlier than it needs to. For example, withcontentRowCount = 18andterminalHeight = 25:requiredModalHeight=24,modalHeight=23,shouldScroll=true← unnecessary scrollboxrequiredModalHeight=23,modalHeight=23,shouldScroll=false← all content fitsIt would be worth double-checking the opentui
borderand padding accounting, and if the actual overhead is indeed 5, updating the constant and comment:There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I checked this against the actual rendered frame instead of just the JSX structure. With one fewer chrome row, the dialog still overlaps content (for example
Review/ m), so6is intentional here even though the visible structure looks like5rows at a glance.