From 2a12ac49e2e2e44e9d3f59d49855ac560b449d94 Mon Sep 17 00:00:00 2001 From: Taylor Mullen Date: Wed, 4 Mar 2026 00:57:35 -0800 Subject: [PATCH] fix(cli): stabilize prompt layout to prevent jumping when typing - Added minHeight and spacer text to shortcuts hint container - Ensures the line occupied by the hint remains in the layout even when the hint is hidden during typing - Updated tests and snapshots --- .../cli/src/ui/components/Composer.test.tsx | 23 +-------------- packages/cli/src/ui/components/Composer.tsx | 28 ++++++++++--------- .../__snapshots__/Composer.test.tsx.snap | 6 ++-- 3 files changed, 20 insertions(+), 37 deletions(-) diff --git a/packages/cli/src/ui/components/Composer.test.tsx b/packages/cli/src/ui/components/Composer.test.tsx index 999b1531f9..ad7bc11535 100644 --- a/packages/cli/src/ui/components/Composer.test.tsx +++ b/packages/cli/src/ui/components/Composer.test.tsx @@ -820,18 +820,7 @@ describe('Composer', () => { }); describe('Shortcuts Hint', () => { - it('restores shortcuts hint after 200ms debounce when buffer is empty', async () => { - const { lastFrame } = await renderComposer( - createMockUIState({ - buffer: { text: '' } as unknown as TextBuffer, - cleanUiDetailsVisible: false, - }), - ); - - expect(lastFrame({ allowEmpty: true })).toContain('ShortcutsHint'); - }); - - it('does not show shortcuts hint immediately when buffer has text', async () => { + it('hides shortcuts hint when text is typed in buffer', async () => { const uiState = createMockUIState({ buffer: { text: 'hello' } as unknown as TextBuffer, cleanUiDetailsVisible: false, @@ -901,16 +890,6 @@ describe('Composer', () => { expect(lastFrame()).not.toContain('ShortcutsHint'); }); - it('hides shortcuts hint when text is typed in buffer', async () => { - const uiState = createMockUIState({ - buffer: { text: 'hello' } as unknown as TextBuffer, - }); - - const { lastFrame } = await renderComposer(uiState); - - expect(lastFrame()).not.toContain('ShortcutsHint'); - }); - it('hides shortcuts hint while loading in minimal mode', async () => { const uiState = createMockUIState({ cleanUiDetailsVisible: false, diff --git a/packages/cli/src/ui/components/Composer.tsx b/packages/cli/src/ui/components/Composer.tsx index 51c879e772..2c6792cdd7 100644 --- a/packages/cli/src/ui/components/Composer.tsx +++ b/packages/cli/src/ui/components/Composer.tsx @@ -249,8 +249,13 @@ export const Composer = ({ isFocused = true }: { isFocused?: boolean }) => { marginTop={isNarrow ? 1 : 0} flexDirection="column" alignItems={isNarrow ? 'flex-start' : 'flex-end'} + minHeight={1} > - {showUiDetails && showShortcutsHint && } + {showUiDetails && showShortcutsHint ? ( + + ) : ( + + )} {showMinimalMetaRow && ( @@ -309,6 +314,7 @@ export const Composer = ({ isFocused = true }: { isFocused?: boolean }) => { marginTop={isNarrow && showMinimalBleedThroughRow ? 1 : 0} flexDirection={isNarrow ? 'column' : 'row'} alignItems={isNarrow ? 'flex-start' : 'flex-end'} + minHeight={1} > {showMinimalContextBleedThrough && ( { terminalWidth={uiState.terminalWidth} /> )} - {showShortcutsHint && ( - - - - )} + + {showShortcutsHint ? : } + )} diff --git a/packages/cli/src/ui/components/__snapshots__/Composer.test.tsx.snap b/packages/cli/src/ui/components/__snapshots__/Composer.test.tsx.snap index 452663d719..6bd8ee6b10 100644 --- a/packages/cli/src/ui/components/__snapshots__/Composer.test.tsx.snap +++ b/packages/cli/src/ui/components/__snapshots__/Composer.test.tsx.snap @@ -10,13 +10,15 @@ Footer `; exports[`Composer > Snapshots > matches snapshot in minimal UI mode 1`] = ` -" ShortcutsHint +" + ShortcutsHint InputPrompt: Type your message or @path/to/file " `; exports[`Composer > Snapshots > matches snapshot in minimal UI mode while loading 1`] = ` -" LoadingIndicator +" + LoadingIndicator InputPrompt: Type your message or @path/to/file " `;