feat(ux) Expandable (ctrl-O) and scrollable approvals in alternate buffer mode. (#17640)

This commit is contained in:
Jacob Richman
2026-01-27 16:06:24 -08:00
committed by GitHub
parent ff6547857e
commit d165b6d4e7
34 changed files with 1177 additions and 496 deletions
@@ -16,6 +16,8 @@ import { theme } from '../../semantic-colors.js';
import { useConfig } from '../../contexts/ConfigContext.js';
import { isShellTool, isThisShellFocused } from './ToolShared.js';
import { ASK_USER_DISPLAY_NAME } from '@google/gemini-cli-core';
import { ShowMoreLines } from '../ShowMoreLines.js';
import { useUIState } from '../../contexts/UIStateContext.js';
interface ToolGroupMessageProps {
groupId: number;
@@ -26,6 +28,8 @@ interface ToolGroupMessageProps {
activeShellPtyId?: number | null;
embeddedShellFocused?: boolean;
onShellInputSubmit?: (input: string) => void;
borderTop?: boolean;
borderBottom?: boolean;
}
// Helper to identify Ask User tools that are in progress (have their own dialog UI)
@@ -45,6 +49,8 @@ export const ToolGroupMessage: React.FC<ToolGroupMessageProps> = ({
isFocused = true,
activeShellPtyId,
embeddedShellFocused,
borderTop: borderTopOverride,
borderBottom: borderBottomOverride,
}) => {
// Filter out in-progress Ask User tools (they have their own AskUserDialog UI)
const toolCalls = useMemo(
@@ -53,6 +59,7 @@ export const ToolGroupMessage: React.FC<ToolGroupMessageProps> = ({
);
const config = useConfig();
const { constrainHeight } = useUIState();
const isEventDriven = config.isEventDrivenSchedulerEnabled();
@@ -110,8 +117,12 @@ export const ToolGroupMessage: React.FC<ToolGroupMessageProps> = ({
);
// If all tools are hidden (e.g. group only contains confirming or pending tools),
// render nothing in the history log.
if (visibleToolCalls.length === 0) {
// render nothing in the history log unless we have a border override.
if (
visibleToolCalls.length === 0 &&
borderTopOverride === undefined &&
borderBottomOverride === undefined
) {
return null;
}
@@ -161,7 +172,10 @@ export const ToolGroupMessage: React.FC<ToolGroupMessageProps> = ({
: toolAwaitingApproval
? ('low' as const)
: ('medium' as const),
isFirst,
isFirst:
borderTopOverride !== undefined
? borderTopOverride && isFirst
: isFirst,
borderColor,
borderDimColor,
};
@@ -225,20 +239,25 @@ export const ToolGroupMessage: React.FC<ToolGroupMessageProps> = ({
We have to keep the bottom border separate so it doesn't get
drawn over by the sticky header directly inside it.
*/
visibleToolCalls.length > 0 && (
(visibleToolCalls.length > 0 || borderBottomOverride !== undefined) && (
<Box
height={0}
width={terminalWidth}
borderLeft={true}
borderRight={true}
borderTop={false}
borderBottom={true}
borderBottom={borderBottomOverride ?? true}
borderColor={borderColor}
borderDimColor={borderDimColor}
borderStyle="round"
/>
)
}
{(borderBottomOverride ?? true) && visibleToolCalls.length > 0 && (
<Box paddingX={1}>
<ShowMoreLines constrainHeight={constrainHeight} />
</Box>
)}
</Box>
);
};