fix(cli): stabilize prompt layout to prevent jumping when typing (#21081)

This commit is contained in:
N. Taylor Mullen
2026-03-10 14:29:29 -07:00
committed by GitHub
parent 2a9acdc85e
commit bee5cfdaee
2 changed files with 19 additions and 28 deletions
@@ -831,7 +831,7 @@ describe('Composer', () => {
expect(lastFrame({ allowEmpty: true })).toContain('ShortcutsHint'); 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({ const uiState = createMockUIState({
buffer: { text: 'hello' } as unknown as TextBuffer, buffer: { text: 'hello' } as unknown as TextBuffer,
cleanUiDetailsVisible: false, cleanUiDetailsVisible: false,
@@ -901,16 +901,6 @@ describe('Composer', () => {
expect(lastFrame()).not.toContain('ShortcutsHint'); 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 () => { it('hides shortcuts hint while loading in minimal mode', async () => {
const uiState = createMockUIState({ const uiState = createMockUIState({
cleanUiDetailsVisible: false, cleanUiDetailsVisible: false,
+18 -17
View File
@@ -171,10 +171,10 @@ export const Composer = ({ isFocused = true }: { isFocused?: boolean }) => {
return () => clearTimeout(timeout); return () => clearTimeout(timeout);
}, [canShowShortcutsHint]); }, [canShowShortcutsHint]);
const shouldReserveSpaceForShortcutsHint =
settings.merged.ui.showShortcutsHint && !hideShortcutsHintForSuggestions;
const showShortcutsHint = const showShortcutsHint =
settings.merged.ui.showShortcutsHint && shouldReserveSpaceForShortcutsHint && showShortcutsHintDebounced;
!hideShortcutsHintForSuggestions &&
showShortcutsHintDebounced;
const showMinimalModeBleedThrough = const showMinimalModeBleedThrough =
!hideUiDetailsForSuggestions && Boolean(minimalModeBleedThrough); !hideUiDetailsForSuggestions && Boolean(minimalModeBleedThrough);
const showMinimalInlineLoading = !showUiDetails && showLoadingIndicator; const showMinimalInlineLoading = !showUiDetails && showLoadingIndicator;
@@ -187,7 +187,7 @@ export const Composer = ({ isFocused = true }: { isFocused?: boolean }) => {
!showUiDetails && !showUiDetails &&
(showMinimalInlineLoading || (showMinimalInlineLoading ||
showMinimalBleedThroughRow || showMinimalBleedThroughRow ||
showShortcutsHint); shouldReserveSpaceForShortcutsHint);
return ( return (
<Box <Box
@@ -249,6 +249,9 @@ export const Composer = ({ isFocused = true }: { isFocused?: boolean }) => {
marginTop={isNarrow ? 1 : 0} marginTop={isNarrow ? 1 : 0}
flexDirection="column" flexDirection="column"
alignItems={isNarrow ? 'flex-start' : 'flex-end'} alignItems={isNarrow ? 'flex-start' : 'flex-end'}
minHeight={
showUiDetails && shouldReserveSpaceForShortcutsHint ? 1 : 0
}
> >
{showUiDetails && showShortcutsHint && <ShortcutsHint />} {showUiDetails && showShortcutsHint && <ShortcutsHint />}
</Box> </Box>
@@ -304,11 +307,13 @@ export const Composer = ({ isFocused = true }: { isFocused?: boolean }) => {
</Box> </Box>
)} )}
</Box> </Box>
{(showMinimalContextBleedThrough || showShortcutsHint) && ( {(showMinimalContextBleedThrough ||
shouldReserveSpaceForShortcutsHint) && (
<Box <Box
marginTop={isNarrow && showMinimalBleedThroughRow ? 1 : 0} marginTop={isNarrow && showMinimalBleedThroughRow ? 1 : 0}
flexDirection={isNarrow ? 'column' : 'row'} flexDirection={isNarrow ? 'column' : 'row'}
alignItems={isNarrow ? 'flex-start' : 'flex-end'} alignItems={isNarrow ? 'flex-start' : 'flex-end'}
minHeight={1}
> >
{showMinimalContextBleedThrough && ( {showMinimalContextBleedThrough && (
<ContextUsageDisplay <ContextUsageDisplay
@@ -317,18 +322,14 @@ export const Composer = ({ isFocused = true }: { isFocused?: boolean }) => {
terminalWidth={uiState.terminalWidth} terminalWidth={uiState.terminalWidth}
/> />
)} )}
{showShortcutsHint && ( <Box
<Box marginLeft={
marginLeft={ showMinimalContextBleedThrough && !isNarrow ? 1 : 0
showMinimalContextBleedThrough && !isNarrow ? 1 : 0 }
} marginTop={showMinimalContextBleedThrough && isNarrow ? 1 : 0}
marginTop={ >
showMinimalContextBleedThrough && isNarrow ? 1 : 0 {showShortcutsHint && <ShortcutsHint />}
} </Box>
>
<ShortcutsHint />
</Box>
)}
</Box> </Box>
)} )}
</Box> </Box>