From 9ef4691de6a9362f6ba04d9495e253b0a8d898f5 Mon Sep 17 00:00:00 2001 From: Jack Wotherspoon Date: Tue, 5 May 2026 11:48:18 -0400 Subject: [PATCH] fix(cli): prevent settings dialog border clipping by using maxHeight The settings dialog's bottom border was being clipped because height="100%" forced the dialog to expand beyond its calculated available height, pushing siblings (like the exit warning) into the overflow. This change: 1. Replaces height="100%" with maxHeight={availableHeight} in BaseSettingsDialog. 2. Adds a regression test case in SettingsDialog.test.tsx to verify border integrity under height constraints. 3. Updates snapshots to include the new test case. The use of maxHeight ensures the dialog fits within terminal bounds while also allowing it to shrink-to-fit shorter content lists, avoiding unnecessary whitespace. --- .../src/ui/components/SettingsDialog.test.tsx | 30 +++++++++ ...rectly-when-height-is-constrained.snap.svg | 63 +++++++++++++++++++ .../SettingsDialog.test.tsx.snap | 18 ++++++ .../components/shared/BaseSettingsDialog.tsx | 2 +- 4 files changed, 112 insertions(+), 1 deletion(-) create mode 100644 packages/cli/src/ui/components/__snapshots__/SettingsDialog-SettingsDialog-Initial-Rendering-should-render-the-bottom-border-correctly-when-height-is-constrained.snap.svg diff --git a/packages/cli/src/ui/components/SettingsDialog.test.tsx b/packages/cli/src/ui/components/SettingsDialog.test.tsx index 9887415a57b..cd16572ddc2 100644 --- a/packages/cli/src/ui/components/SettingsDialog.test.tsx +++ b/packages/cli/src/ui/components/SettingsDialog.test.tsx @@ -326,6 +326,36 @@ describe('SettingsDialog', () => { }); unmount(); }); + + it('should render the bottom border correctly when height is constrained', async () => { + const settings = createMockSettings(); + const onSelect = vi.fn(); + const constrainedHeight = 15; + + const renderResult = await renderDialog(settings, onSelect, { + availableTerminalHeight: constrainedHeight, + }); + + await renderResult.waitUntilReady(); + + await waitFor(() => { + const output = renderResult.lastFrame(); + const lines = output.trim().split('\n'); + + // Verify height constraint + expect(lines.length).toBeLessThanOrEqual(constrainedHeight); + + // Verify bottom border existence in the last line of the output + const lastLine = lines[lines.length - 1]; + // 'round' border characters: ─, ╰, ╯ + expect(lastLine).toMatch(/[─╰╯]/); + }); + + // SVG snapshot ensures visual layout and border rendering are preserved + await expect(renderResult).toMatchSvgSnapshot(); + + renderResult.unmount(); + }); }); describe('Setting Descriptions', () => { diff --git a/packages/cli/src/ui/components/__snapshots__/SettingsDialog-SettingsDialog-Initial-Rendering-should-render-the-bottom-border-correctly-when-height-is-constrained.snap.svg b/packages/cli/src/ui/components/__snapshots__/SettingsDialog-SettingsDialog-Initial-Rendering-should-render-the-bottom-border-correctly-when-height-is-constrained.snap.svg new file mode 100644 index 00000000000..d3f10b6af8e --- /dev/null +++ b/packages/cli/src/ui/components/__snapshots__/SettingsDialog-SettingsDialog-Initial-Rendering-should-render-the-bottom-border-correctly-when-height-is-constrained.snap.svg @@ -0,0 +1,63 @@ + + + + + ╭──────────────────────────────────────────────────────────────────────────────────────────────────╮ + + + + > Settings + + + + + ╭──────────────────────────────────────────────────────────────────────────────────────────────╮ + + + ╰─ + + S + earch to filter + ─────────────────────────────────────────────────────────────────────────────╯ + + + + + + + + + + Vim Mode + + + false + + + + + Enable Vim keybindings + + + + + Apply To + + + + + + + User Settings + + + + (Use Enter to select, Ctrl+L to reset, Tab to change focus, Esc to close) + + + + ╰──────────────────────────────────────────────────────────────────────────────────────────────────╯ + + \ No newline at end of file diff --git a/packages/cli/src/ui/components/__snapshots__/SettingsDialog.test.tsx.snap b/packages/cli/src/ui/components/__snapshots__/SettingsDialog.test.tsx.snap index a7f994ed68d..a4b19e00f9f 100644 --- a/packages/cli/src/ui/components/__snapshots__/SettingsDialog.test.tsx.snap +++ b/packages/cli/src/ui/components/__snapshots__/SettingsDialog.test.tsx.snap @@ -46,6 +46,24 @@ exports[`SettingsDialog > Initial Rendering > should render settings list with v ╰──────────────────────────────────────────────────────────────────────────────────────────────────╯" `; +exports[`SettingsDialog > Initial Rendering > should render the bottom border correctly when height is constrained 1`] = ` +"╭──────────────────────────────────────────────────────────────────────────────────────────────────╮ +│ │ +│ > Settings │ +│ │ +│ ╭──────────────────────────────────────────────────────────────────────────────────────────────╮ │ +│ ╰─Search to filter─────────────────────────────────────────────────────────────────────────────╯ │ +│ ▲ │ +│ ● Vim Mode false │ +│ ▼ Enable Vim keybindings │ +│ │ +│ Apply To │ +│ ● User Settings │ +│ (Use Enter to select, Ctrl+L to reset, Tab to change focus, Esc to close) │ +│ │ +╰──────────────────────────────────────────────────────────────────────────────────────────────────╯" +`; + exports[`SettingsDialog > Snapshot Tests > should render 'accessibility settings enabled' correctly 1`] = ` "╭──────────────────────────────────────────────────────────────────────────────────────────────────╮ │ │ diff --git a/packages/cli/src/ui/components/shared/BaseSettingsDialog.tsx b/packages/cli/src/ui/components/shared/BaseSettingsDialog.tsx index 804633fe15f..25dbb1d8b48 100644 --- a/packages/cli/src/ui/components/shared/BaseSettingsDialog.tsx +++ b/packages/cli/src/ui/components/shared/BaseSettingsDialog.tsx @@ -425,7 +425,7 @@ export function BaseSettingsDialog({ flexDirection="row" padding={1} width="100%" - height="100%" + maxHeight={availableHeight} > {/* Title */}