From e170add9b82bd3f869730d3101988643968dc023 Mon Sep 17 00:00:00 2001 From: Taylor Mullen Date: Tue, 10 Mar 2026 13:44:26 -0700 Subject: [PATCH] fix(cli): stabilize prompt layout using minHeight instead of spacer text - Use minHeight on shortcut hint containers to reserve space without unintended blank lines - Fix jumping in minimal mode by ensuring the meta row stays mounted when space is reserved - Restore missing test case for shortcut hint restoration - Update snapshots to reflect corrected layout --- .../cli/src/ui/components/Composer.test.tsx | 11 +++++++++ packages/cli/src/ui/components/Composer.tsx | 23 +++++++++---------- .../__snapshots__/Composer.test.tsx.snap | 6 ++--- 3 files changed, 24 insertions(+), 16 deletions(-) diff --git a/packages/cli/src/ui/components/Composer.test.tsx b/packages/cli/src/ui/components/Composer.test.tsx index ad7bc11535..9c9fcbdd45 100644 --- a/packages/cli/src/ui/components/Composer.test.tsx +++ b/packages/cli/src/ui/components/Composer.test.tsx @@ -820,6 +820,17 @@ 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('hides shortcuts hint when text is typed in buffer', async () => { const uiState = createMockUIState({ buffer: { text: 'hello' } as unknown as TextBuffer, diff --git a/packages/cli/src/ui/components/Composer.tsx b/packages/cli/src/ui/components/Composer.tsx index 2c6792cdd7..a43d12606b 100644 --- a/packages/cli/src/ui/components/Composer.tsx +++ b/packages/cli/src/ui/components/Composer.tsx @@ -171,10 +171,10 @@ export const Composer = ({ isFocused = true }: { isFocused?: boolean }) => { return () => clearTimeout(timeout); }, [canShowShortcutsHint]); + const shouldReserveSpaceForShortcutsHint = + settings.merged.ui.showShortcutsHint && !hideShortcutsHintForSuggestions; const showShortcutsHint = - settings.merged.ui.showShortcutsHint && - !hideShortcutsHintForSuggestions && - showShortcutsHintDebounced; + shouldReserveSpaceForShortcutsHint && showShortcutsHintDebounced; const showMinimalModeBleedThrough = !hideUiDetailsForSuggestions && Boolean(minimalModeBleedThrough); const showMinimalInlineLoading = !showUiDetails && showLoadingIndicator; @@ -187,7 +187,7 @@ export const Composer = ({ isFocused = true }: { isFocused?: boolean }) => { !showUiDetails && (showMinimalInlineLoading || showMinimalBleedThroughRow || - showShortcutsHint); + shouldReserveSpaceForShortcutsHint); return ( { marginTop={isNarrow ? 1 : 0} flexDirection="column" alignItems={isNarrow ? 'flex-start' : 'flex-end'} - minHeight={1} + minHeight={ + showUiDetails && shouldReserveSpaceForShortcutsHint ? 1 : 0 + } > - {showUiDetails && showShortcutsHint ? ( - - ) : ( - - )} + {showUiDetails && showShortcutsHint && } {showMinimalMetaRow && ( @@ -309,7 +307,8 @@ export const Composer = ({ isFocused = true }: { isFocused?: boolean }) => { )} - {(showMinimalContextBleedThrough || showShortcutsHint) && ( + {(showMinimalContextBleedThrough || + shouldReserveSpaceForShortcutsHint) && ( { } marginTop={showMinimalContextBleedThrough && isNarrow ? 1 : 0} > - {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 6bd8ee6b10..452663d719 100644 --- a/packages/cli/src/ui/components/__snapshots__/Composer.test.tsx.snap +++ b/packages/cli/src/ui/components/__snapshots__/Composer.test.tsx.snap @@ -10,15 +10,13 @@ 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 " `;