fix(cli): collapse input area during approvals and selector overlays (#776)

Co-authored-by: Letta <noreply@letta.com>
This commit is contained in:
Charles Packer
2026-02-01 17:21:49 -08:00
committed by GitHub
parent 5598c09d08
commit 44da9bb1db
2 changed files with 78 additions and 63 deletions

View File

@@ -10076,6 +10076,9 @@ Plan file path: ${planFilePath}`;
bashRunning={bashRunning}
onBashInterrupt={handleBashInterrupt}
inputEnabled={inputEnabled}
collapseInputWhenDisabled={
pendingApprovals.length > 0 || anySelectorOpen
}
permissionMode={uiPermissionMode}
onPermissionModeChange={handlePermissionModeChange}
onExit={handleExit}

View File

@@ -193,6 +193,7 @@ export function Input({
bashRunning = false,
onBashInterrupt,
inputEnabled = true,
collapseInputWhenDisabled = false,
permissionMode: externalMode,
onPermissionModeChange,
onExit,
@@ -225,6 +226,7 @@ export function Input({
bashRunning?: boolean;
onBashInterrupt?: () => void;
inputEnabled?: boolean;
collapseInputWhenDisabled?: boolean;
permissionMode?: PermissionMode;
onPermissionModeChange?: (mode: PermissionMode) => void;
onExit?: () => void;
@@ -259,8 +261,18 @@ export function Input({
const [isAutocompleteActive, setIsAutocompleteActive] = useState(false);
const [cursorPos, setCursorPos] = useState<number | undefined>(undefined);
const [currentCursorPosition, setCurrentCursorPosition] = useState(0);
// Terminal width (reactive to window resizing)
const columns = useTerminalWidth();
const contentWidth = Math.max(0, columns - 2);
const interactionEnabled = visible && inputEnabled;
const hideFooter = interactionEnabled && value.startsWith("/");
const reserveInputSpace = !collapseInputWhenDisabled;
const hideFooter = !interactionEnabled || value.startsWith("/");
const inputRowLines = useMemo(() => {
return Math.max(1, getVisualLines(value, contentWidth).length);
}, [value, contentWidth]);
const inputChromeHeight = inputRowLines + 3; // top divider + input rows + bottom divider + footer
// Command history
const [history, setHistory] = useState<string[]>([]);
@@ -338,10 +350,6 @@ export function Input({
}
}, [interactionEnabled]);
// Terminal width (reactive to window resizing)
const columns = useTerminalWidth();
const contentWidth = Math.max(0, columns - 2);
// Get server URL (same logic as client.ts)
const settings = settingsManager.getSettings();
const serverUrl =
@@ -932,47 +940,49 @@ export function Input({
<QueuedMessages messages={messageQueue} />
)}
<Box flexDirection="column">
{/* Top horizontal divider */}
<Text
dimColor={!isBashMode}
color={isBashMode ? colors.bash.border : undefined}
>
{horizontalLine}
</Text>
{interactionEnabled ? (
<Box flexDirection="column">
{/* Top horizontal divider */}
<Text
dimColor={!isBashMode}
color={isBashMode ? colors.bash.border : undefined}
>
{horizontalLine}
</Text>
{/* Two-column layout for input, matching message components */}
<Box flexDirection="row">
<Box width={2} flexShrink={0}>
<Text color={isBashMode ? colors.bash.prompt : colors.input.prompt}>
{isBashMode ? "!" : ">"}
</Text>
<Text> </Text>
{/* Two-column layout for input, matching message components */}
<Box flexDirection="row">
<Box width={2} flexShrink={0}>
<Text
color={isBashMode ? colors.bash.prompt : colors.input.prompt}
>
{isBashMode ? "!" : ">"}
</Text>
<Text> </Text>
</Box>
<Box flexGrow={1} width={contentWidth}>
<PasteAwareTextInput
value={value}
onChange={setValue}
onSubmit={handleSubmit}
cursorPosition={cursorPos}
onCursorMove={setCurrentCursorPosition}
focus={interactionEnabled && !onEscapeCancel}
onBangAtEmpty={handleBangAtEmpty}
onBackspaceAtEmpty={handleBackspaceAtEmpty}
onPasteError={onPasteError}
/>
</Box>
</Box>
<Box flexGrow={1} width={contentWidth}>
<PasteAwareTextInput
value={value}
onChange={setValue}
onSubmit={handleSubmit}
cursorPosition={cursorPos}
onCursorMove={setCurrentCursorPosition}
focus={interactionEnabled && !onEscapeCancel}
onBangAtEmpty={handleBangAtEmpty}
onBackspaceAtEmpty={handleBackspaceAtEmpty}
onPasteError={onPasteError}
/>
</Box>
</Box>
{/* Bottom horizontal divider */}
<Text
dimColor={!isBashMode}
color={isBashMode ? colors.bash.border : undefined}
>
{horizontalLine}
</Text>
{/* Bottom horizontal divider */}
<Text
dimColor={!isBashMode}
color={isBashMode ? colors.bash.border : undefined}
>
{horizontalLine}
</Text>
{interactionEnabled && (
<InputAssist
currentInput={value}
cursorPosition={currentCursorPosition}
@@ -986,28 +996,30 @@ export function Input({
workingDirectory={process.cwd()}
conversationId={conversationId}
/>
)}
<InputFooter
ctrlCPressed={ctrlCPressed}
escapePressed={escapePressed}
isBashMode={isBashMode}
modeName={modeInfo?.name ?? null}
modeColor={modeInfo?.color ?? null}
showExitHint={ralphActive || ralphPending}
agentName={agentName}
currentModel={currentModel}
isOpenAICodexProvider={
currentModelProvider === OPENAI_CODEX_PROVIDER_NAME
}
isByokProvider={
currentModelProvider?.startsWith("lc-") ||
currentModelProvider === OPENAI_CODEX_PROVIDER_NAME
}
isAutocompleteActive={isAutocompleteActive}
hideFooter={hideFooter}
/>
</Box>
<InputFooter
ctrlCPressed={ctrlCPressed}
escapePressed={escapePressed}
isBashMode={isBashMode}
modeName={modeInfo?.name ?? null}
modeColor={modeInfo?.color ?? null}
showExitHint={ralphActive || ralphPending}
agentName={agentName}
currentModel={currentModel}
isOpenAICodexProvider={
currentModelProvider === OPENAI_CODEX_PROVIDER_NAME
}
isByokProvider={
currentModelProvider?.startsWith("lc-") ||
currentModelProvider === OPENAI_CODEX_PROVIDER_NAME
}
isAutocompleteActive={isAutocompleteActive}
hideFooter={hideFooter}
/>
</Box>
) : reserveInputSpace ? (
<Box height={inputChromeHeight} />
) : null}
</Box>
);
}