diff --git a/packages/cli/src/ui/AppContainer.tsx b/packages/cli/src/ui/AppContainer.tsx index 03e001546b..c3607c7041 100644 --- a/packages/cli/src/ui/AppContainer.tsx +++ b/packages/cli/src/ui/AppContainer.tsx @@ -1754,7 +1754,8 @@ Logging in with Google... Restarting Gemini CLI to continue. if (!isAlternateBuffer) { refreshStatic(); } - return true; + // Return false to allow other components (e.g. ToolConfirmationMessage) to also handle expansion. + return false; } else if ( (keyMatchers[Command.FOCUS_SHELL_INPUT](key) || keyMatchers[Command.UNFOCUS_BACKGROUND_SHELL_LIST](key)) && diff --git a/packages/cli/src/ui/components/messages/ToolConfirmationMessage.tsx b/packages/cli/src/ui/components/messages/ToolConfirmationMessage.tsx index 113852cb8d..e440d43d65 100644 --- a/packages/cli/src/ui/components/messages/ToolConfirmationMessage.tsx +++ b/packages/cli/src/ui/components/messages/ToolConfirmationMessage.tsx @@ -176,7 +176,8 @@ export const ToolConfirmationMessage: React.FC< callId, expanded: !isMcpToolDetailsExpanded, }); - return true; + // Return false to let the global app container also expand its view. + return false; } if (keyMatchers[Command.ESCAPE](key)) { handleConfirm(ToolConfirmationOutcome.Cancel); diff --git a/packages/cli/src/ui/components/shared/MaxSizedBox.test.tsx b/packages/cli/src/ui/components/shared/MaxSizedBox.test.tsx index d21cebe971..6d25efffb9 100644 --- a/packages/cli/src/ui/components/shared/MaxSizedBox.test.tsx +++ b/packages/cli/src/ui/components/shared/MaxSizedBox.test.tsx @@ -6,7 +6,7 @@ import { render, renderWithProviders } from '../../../test-utils/render.js'; import { OverflowProvider } from '../../contexts/OverflowContext.js'; -import { MaxSizedBox } from './MaxSizedBox.js'; +import { MaxSizedBox, ceilHeight } from './MaxSizedBox.js'; import { MarkdownDisplay } from '../../utils/MarkdownDisplay.js'; import { Box, Text } from 'ink'; import { act } from 'react'; @@ -316,4 +316,17 @@ describe('', () => { expect(lastFrame()).toMatchSnapshot(); unmount(); }); + + describe('ceilHeight', () => { + it('should round up fractional heights to next integer', () => { + expect(ceilHeight(2.1)).toBe(3); + expect(ceilHeight(2.9)).toBe(3); + expect(ceilHeight(2.0)).toBe(2); + expect(ceilHeight(0.1)).toBe(1); + }); + + it('should handle zero correctly', () => { + expect(ceilHeight(0)).toBe(0); + }); + }); }); diff --git a/packages/cli/src/ui/components/shared/MaxSizedBox.tsx b/packages/cli/src/ui/components/shared/MaxSizedBox.tsx index 0e3869a3f0..e659ce94b1 100644 --- a/packages/cli/src/ui/components/shared/MaxSizedBox.tsx +++ b/packages/cli/src/ui/components/shared/MaxSizedBox.tsx @@ -28,6 +28,9 @@ export interface MaxSizedBoxProps { additionalHiddenLinesCount?: number; } +/** Ensures that fractional heights are correctly identified as overflowing. */ +export const ceilHeight = (height: number): number => Math.ceil(height); + /** * A React component that constrains the size of its children and provides * content-aware truncation when the content exceeds the specified `maxHeight`. @@ -55,7 +58,8 @@ export const MaxSizedBox: React.FC = ({ const observer = new ResizeObserver((entries) => { const entry = entries[0]; if (entry) { - setContentHeight(Math.round(entry.contentRect.height)); + // Use ceilHeight to ensure that fractional heights (e.g. from zooming) that exceed the limit are correctly identified as overflowing. + setContentHeight(ceilHeight(entry.contentRect.height)); } }); observer.observe(node);