From aec4bdcb19064063e0bdca3e60d1b71210079615 Mon Sep 17 00:00:00 2001 From: annasba07 Date: Wed, 19 Nov 2025 17:43:21 -0800 Subject: [PATCH 1/2] feat(cli): add animated spinner for WaitingForConfirmation state MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the static '⠏' character with an animated spinner during the "Waiting for user confirmation" state. This provides better visual feedback that the CLI is still active and awaiting input. Changes: - Update GeminiRespondingSpinner to show animated spinner for both Responding and WaitingForConfirmation states - Remove static fallback from LoadingIndicator - Update tests to reflect new behavior Fixes #13395 --- .../ui/components/GeminiRespondingSpinner.tsx | 5 ++++- .../ui/components/LoadingIndicator.test.tsx | 19 ++++++++----------- .../src/ui/components/LoadingIndicator.tsx | 8 +------- 3 files changed, 13 insertions(+), 19 deletions(-) diff --git a/packages/cli/src/ui/components/GeminiRespondingSpinner.tsx b/packages/cli/src/ui/components/GeminiRespondingSpinner.tsx index 8565ae5d3d4..1edf697fd7c 100644 --- a/packages/cli/src/ui/components/GeminiRespondingSpinner.tsx +++ b/packages/cli/src/ui/components/GeminiRespondingSpinner.tsx @@ -30,7 +30,10 @@ export const GeminiRespondingSpinner: React.FC< > = ({ nonRespondingDisplay, spinnerType = 'dots' }) => { const streamingState = useStreamingContext(); const isScreenReaderEnabled = useIsScreenReaderEnabled(); - if (streamingState === StreamingState.Responding) { + if ( + streamingState === StreamingState.Responding || + streamingState === StreamingState.WaitingForConfirmation + ) { return ( ({ - GeminiRespondingSpinner: ({ - nonRespondingDisplay, - }: { - nonRespondingDisplay?: string; - }) => { + GeminiRespondingSpinner: () => { const streamingState = React.useContext(StreamingContext)!; - if (streamingState === StreamingState.Responding) { + if ( + streamingState === StreamingState.Responding || + streamingState === StreamingState.WaitingForConfirmation + ) { return MockRespondingSpinner; - } else if (nonRespondingDisplay) { - return {nonRespondingDisplay}; } return null; }, @@ -76,7 +73,7 @@ describe('', () => { expect(output).toContain('(esc to cancel, 5s)'); }); - it('should render spinner (static), phrase but no time/cancel when streamingState is WaitingForConfirmation', () => { + it('should render animated spinner, phrase but no time/cancel when streamingState is WaitingForConfirmation', () => { const props = { currentLoadingPhrase: 'Confirm action', elapsedTime: 10, @@ -86,7 +83,7 @@ describe('', () => { StreamingState.WaitingForConfirmation, ); const output = lastFrame(); - expect(output).toContain('⠏'); // Static char for WaitingForConfirmation + expect(output).toContain('MockRespondingSpinner'); // Animated spinner for WaitingForConfirmation expect(output).toContain('Confirm action'); expect(output).not.toContain('(esc to cancel)'); expect(output).not.toContain(', 10s'); @@ -172,7 +169,7 @@ describe('', () => { , ); output = lastFrame(); - expect(output).toContain('⠏'); + expect(output).toContain('MockRespondingSpinner'); expect(output).toContain('Please Confirm'); expect(output).not.toContain('(esc to cancel)'); expect(output).not.toContain(', 15s'); diff --git a/packages/cli/src/ui/components/LoadingIndicator.tsx b/packages/cli/src/ui/components/LoadingIndicator.tsx index bd0b7e81f9b..bf809fff47a 100644 --- a/packages/cli/src/ui/components/LoadingIndicator.tsx +++ b/packages/cli/src/ui/components/LoadingIndicator.tsx @@ -53,13 +53,7 @@ export const LoadingIndicator: React.FC = ({ > - + {primaryText && ( From 69a077603e01fa83a3945e873f98f97e897e2d83 Mon Sep 17 00:00:00 2001 From: annasba07 Date: Sat, 22 Nov 2025 17:26:43 -0500 Subject: [PATCH 2/2] fix(cli): use appropriate screen reader text for confirmation state Address accessibility feedback: use distinct alt text for screen readers when in WaitingForConfirmation state vs Responding state. - Add SCREEN_READER_WAITING_FOR_CONFIRMATION constant - Update GeminiRespondingSpinner to use state-appropriate alt text --- .../src/ui/components/GeminiRespondingSpinner.tsx | 13 +++++++++---- packages/cli/src/ui/textConstants.ts | 3 +++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/packages/cli/src/ui/components/GeminiRespondingSpinner.tsx b/packages/cli/src/ui/components/GeminiRespondingSpinner.tsx index 1edf697fd7c..cc9b0fe96a5 100644 --- a/packages/cli/src/ui/components/GeminiRespondingSpinner.tsx +++ b/packages/cli/src/ui/components/GeminiRespondingSpinner.tsx @@ -13,6 +13,7 @@ import { StreamingState } from '../types.js'; import { SCREEN_READER_LOADING, SCREEN_READER_RESPONDING, + SCREEN_READER_WAITING_FOR_CONFIRMATION, } from '../textConstants.js'; import { theme } from '../semantic-colors.js'; @@ -30,16 +31,20 @@ export const GeminiRespondingSpinner: React.FC< > = ({ nonRespondingDisplay, spinnerType = 'dots' }) => { const streamingState = useStreamingContext(); const isScreenReaderEnabled = useIsScreenReaderEnabled(); - if ( - streamingState === StreamingState.Responding || - streamingState === StreamingState.WaitingForConfirmation - ) { + if (streamingState === StreamingState.Responding) { return ( ); + } else if (streamingState === StreamingState.WaitingForConfirmation) { + return ( + + ); } else if (nonRespondingDisplay) { return isScreenReaderEnabled ? ( {SCREEN_READER_LOADING} diff --git a/packages/cli/src/ui/textConstants.ts b/packages/cli/src/ui/textConstants.ts index 53236cfed6f..4d6fcd2352a 100644 --- a/packages/cli/src/ui/textConstants.ts +++ b/packages/cli/src/ui/textConstants.ts @@ -11,3 +11,6 @@ export const SCREEN_READER_MODEL_PREFIX = 'Model: '; export const SCREEN_READER_LOADING = 'loading'; export const SCREEN_READER_RESPONDING = 'responding'; + +export const SCREEN_READER_WAITING_FOR_CONFIRMATION = + 'waiting for confirmation';