diff --git a/packages/cli/src/ui/components/AskUserDialog.test.tsx b/packages/cli/src/ui/components/AskUserDialog.test.tsx
index 5810a9f922..320ba321f5 100644
--- a/packages/cli/src/ui/components/AskUserDialog.test.tsx
+++ b/packages/cli/src/ui/components/AskUserDialog.test.tsx
@@ -962,5 +962,70 @@ describe('AskUserDialog', () => {
expect(lastFrame()).toMatchSnapshot();
});
+
+ it('truncates long content when availableTerminalHeight is small', async () => {
+ const longContent = Array.from(
+ { length: 30 },
+ (_, i) => `Line ${i + 1}`,
+ ).join('\n');
+ const questionWithLongContent: Question[] = [
+ {
+ question: 'Approve this plan?',
+ header: 'Plan',
+ options: [{ label: 'Yes', description: '' }],
+ content: longContent,
+ },
+ ];
+
+ const { lastFrame } = renderWithProviders(
+ ,
+ {
+ width: 120,
+ uiState: {
+ availableTerminalHeight: 15,
+ },
+ },
+ );
+
+ await waitFor(() => {
+ expect(lastFrame()).toMatchSnapshot();
+ });
+ });
+
+ it('does not truncate content when availableTerminalHeight is undefined', () => {
+ const content = Array.from(
+ { length: 10 },
+ (_, i) => `Line ${i + 1}`,
+ ).join('\n');
+ const questionWithContent: Question[] = [
+ {
+ question: 'Approve this plan?',
+ header: 'Plan',
+ options: [{ label: 'Yes', description: '' }],
+ content,
+ },
+ ];
+
+ const { lastFrame } = renderWithProviders(
+ ,
+ {
+ width: 120,
+ uiState: {
+ availableTerminalHeight: undefined,
+ },
+ },
+ );
+
+ expect(lastFrame()).not.toContain('lines hidden');
+ expect(lastFrame()).toMatchSnapshot();
+ });
});
});
diff --git a/packages/cli/src/ui/components/AskUserDialog.tsx b/packages/cli/src/ui/components/AskUserDialog.tsx
index 886698a408..269f5e9353 100644
--- a/packages/cli/src/ui/components/AskUserDialog.tsx
+++ b/packages/cli/src/ui/components/AskUserDialog.tsx
@@ -31,6 +31,17 @@ import { useTabbedNavigation } from '../hooks/useTabbedNavigation.js';
import { DialogFooter } from './shared/DialogFooter.js';
import { MaxSizedBox } from './shared/MaxSizedBox.js';
+// Width reduction for content inside the dialog border/padding
+const CONTENT_WIDTH_REDUCTION = 4;
+
+// Height consumed by dialog chrome surrounding the content area:
+// - Border top/bottom: 2
+// - Question text + marginBottom: 2
+// - Footer (keyboard hints): 2
+// - Options/input minimum: 4
+// - Buffer for tab header when present: 2
+const DIALOG_CHROME_HEIGHT = 12;
+
interface AskUserDialogState {
answers: { [key: string]: string };
isEditingCustomOption: boolean;
@@ -283,11 +294,16 @@ const TextQuestionView: React.FC = ({
{progressHeader}
{question.content && (
-
+
@@ -722,11 +738,16 @@ const ChoiceQuestionView: React.FC = ({
{progressHeader}
{question.content && (
-
+
diff --git a/packages/cli/src/ui/components/__snapshots__/AskUserDialog.test.tsx.snap b/packages/cli/src/ui/components/__snapshots__/AskUserDialog.test.tsx.snap
index 53f1e9d821..36b53636ae 100644
--- a/packages/cli/src/ui/components/__snapshots__/AskUserDialog.test.tsx.snap
+++ b/packages/cli/src/ui/components/__snapshots__/AskUserDialog.test.tsx.snap
@@ -11,6 +11,28 @@ exports[`AskUserDialog > Question content field > does not render content when c
╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯"
`;
+exports[`AskUserDialog > Question content field > does not truncate content when availableTerminalHeight is undefined 1`] = `
+"╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
+│ Line 1 │
+│ Line 2 │
+│ Line 3 │
+│ Line 4 │
+│ Line 5 │
+│ Line 6 │
+│ Line 7 │
+│ Line 8 │
+│ Line 9 │
+│ Line 10 │
+│ │
+│ Approve this plan? │
+│ │
+│ ● 1. Yes │
+│ 2. Enter a custom value │
+│ │
+│ Enter to select · ↑/↓ to navigate · Esc to cancel │
+╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯"
+`;
+
exports[`AskUserDialog > Question content field > renders content in a choice question 1`] = `
"╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ Plan Details │
@@ -44,6 +66,21 @@ exports[`AskUserDialog > Question content field > renders content in a text ques
╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯"
`;
+exports[`AskUserDialog > Question content field > truncates long content when availableTerminalHeight is small 1`] = `
+"╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
+│ ... first 28 lines hidden ... │
+│ Line 29 │
+│ Line 30 │
+│ │
+│ Approve this plan? │
+│ │
+│ ● 1. Yes │
+│ 2. Enter a custom value │
+│ │
+│ Enter to select · ↑/↓ to navigate · Esc to cancel │
+╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯"
+`;
+
exports[`AskUserDialog > Question content field > uses customOptionPlaceholder for the Other option 1`] = `
"╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ Approve this? │