From cf879f0b58d85c3ac37c7e135263cd11fac7d525 Mon Sep 17 00:00:00 2001 From: wenshao Date: Wed, 8 Apr 2026 20:54:07 +0800 Subject: [PATCH] =?UTF-8?q?refactor(footer):=20match=20upstream=20layout?= =?UTF-8?q?=20=E2=80=94=20status=20line=20+=20hints=20coexist?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Restructure footer to match Claude Code's layout: - Left column: status line (top, truncated) + hints/mode (bottom) - Both rows coexist instead of being mutually exclusive - Status line uses wrap="truncate" to guarantee single line - Approval mode returns to the hints row (inline, not separate row) - Left column uses flexShrink for narrow terminals --- packages/cli/src/ui/components/Footer.tsx | 85 +++++++------------ .../__snapshots__/Footer.test.tsx.snap | 7 +- 2 files changed, 37 insertions(+), 55 deletions(-) diff --git a/packages/cli/src/ui/components/Footer.tsx b/packages/cli/src/ui/components/Footer.tsx index 61f8eda4f..75824a8f7 100644 --- a/packages/cli/src/ui/components/Footer.tsx +++ b/packages/cli/src/ui/components/Footer.tsx @@ -52,13 +52,9 @@ export const Footer: React.FC = () => { const contextWindowSize = config.getContentGeneratorConfig()?.contextWindowSize; - // Left section priority: high-priority messages > status line > hint. - // Approval mode indicator is rendered as a separate row below when non-default. - const isNonDefaultMode = - showAutoAcceptIndicator !== undefined && - showAutoAcceptIndicator !== ApprovalMode.DEFAULT; - - const leftContent = uiState.ctrlCPressedOnce ? ( + // Left bottom row: high-priority messages > approval mode > hint. + // Matches upstream layout where status line and hints coexist vertically. + const leftBottomContent = uiState.ctrlCPressedOnce ? ( {t('Press Ctrl+C again to exit.')} ) : uiState.ctrlDPressedOnce ? ( {t('Press Ctrl+D again to exit.')} @@ -68,10 +64,9 @@ export const Footer: React.FC = () => { -- INSERT -- ) : uiState.shellModeActive ? ( - ) : statusLineText ? ( - - {statusLineText} - + ) : showAutoAcceptIndicator !== undefined && + showAutoAcceptIndicator !== ApprovalMode.DEFAULT ? ( + ) : ( {t('? for shortcuts')} ); @@ -110,51 +105,35 @@ export const Footer: React.FC = () => { }); } - // Status line is inlined in the footer's left section. - // Approval mode indicator renders as a separate row below when non-default. + // Layout matches upstream: left column has status line (top) + hints/mode + // (bottom), right section has indicators. Status line and hints coexist. return ( - - - {/* Left Section — shrinks to accommodate right items */} - - {leftContent} - - - {/* Right Section — never compressed */} - - {rightItems.map(({ key, node }, index) => ( - - {index > 0 && | } - {node} - - ))} - + + {/* Left column — status line on top, hints/mode on bottom */} + + {statusLineText && ( + + {statusLineText} + + )} + {leftBottomContent} - {/* Approval mode indicator — shown as separate row when non-default */} - {isNonDefaultMode && ( - - - - )} + {/* Right Section — never compressed */} + + {rightItems.map(({ key, node }, index) => ( + + {index > 0 && | } + {node} + + ))} + ); }; diff --git a/packages/cli/src/ui/components/__snapshots__/Footer.test.tsx.snap b/packages/cli/src/ui/components/__snapshots__/Footer.test.tsx.snap index 13017da60..633f0bba7 100644 --- a/packages/cli/src/ui/components/__snapshots__/Footer.test.tsx.snap +++ b/packages/cli/src/ui/components/__snapshots__/Footer.test.tsx.snap @@ -1,5 +1,8 @@ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html -exports[`