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
This commit is contained in:
Taylor Mullen
2026-03-10 13:44:26 -07:00
parent 2a12ac49e2
commit e170add9b8
3 changed files with 24 additions and 16 deletions

View File

@@ -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,

View File

@@ -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 (
<Box
@@ -249,13 +249,11 @@ export const Composer = ({ isFocused = true }: { isFocused?: boolean }) => {
marginTop={isNarrow ? 1 : 0}
flexDirection="column"
alignItems={isNarrow ? 'flex-start' : 'flex-end'}
minHeight={1}
minHeight={
showUiDetails && shouldReserveSpaceForShortcutsHint ? 1 : 0
}
>
{showUiDetails && showShortcutsHint ? (
<ShortcutsHint />
) : (
<Text> </Text>
)}
{showUiDetails && showShortcutsHint && <ShortcutsHint />}
</Box>
</Box>
{showMinimalMetaRow && (
@@ -309,7 +307,8 @@ export const Composer = ({ isFocused = true }: { isFocused?: boolean }) => {
</Box>
)}
</Box>
{(showMinimalContextBleedThrough || showShortcutsHint) && (
{(showMinimalContextBleedThrough ||
shouldReserveSpaceForShortcutsHint) && (
<Box
marginTop={isNarrow && showMinimalBleedThroughRow ? 1 : 0}
flexDirection={isNarrow ? 'column' : 'row'}
@@ -329,7 +328,7 @@ export const Composer = ({ isFocused = true }: { isFocused?: boolean }) => {
}
marginTop={showMinimalContextBleedThrough && isNarrow ? 1 : 0}
>
{showShortcutsHint ? <ShortcutsHint /> : <Text> </Text>}
{showShortcutsHint && <ShortcutsHint />}
</Box>
</Box>
)}

View File

@@ -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
"
`;