diff options
Diffstat (limited to 'packages/cli/src/ui/components/LoadingIndicator.tsx')
| -rw-r--r-- | packages/cli/src/ui/components/LoadingIndicator.tsx | 57 |
1 files changed, 39 insertions, 18 deletions
diff --git a/packages/cli/src/ui/components/LoadingIndicator.tsx b/packages/cli/src/ui/components/LoadingIndicator.tsx index 6e1bc758..7ac356dd 100644 --- a/packages/cli/src/ui/components/LoadingIndicator.tsx +++ b/packages/cli/src/ui/components/LoadingIndicator.tsx @@ -12,6 +12,8 @@ import { useStreamingContext } from '../contexts/StreamingContext.js'; import { StreamingState } from '../types.js'; import { GeminiRespondingSpinner } from './GeminiRespondingSpinner.js'; import { formatDuration } from '../utils/formatters.js'; +import { useTerminalSize } from '../hooks/useTerminalSize.js'; +import { isNarrowWidth } from '../utils/isNarrowWidth.js'; interface LoadingIndicatorProps { currentLoadingPhrase?: string; @@ -27,6 +29,8 @@ export const LoadingIndicator: React.FC<LoadingIndicatorProps> = ({ thought, }) => { const streamingState = useStreamingContext(); + const { columns: terminalWidth } = useTerminalSize(); + const isNarrow = isNarrowWidth(terminalWidth); if (streamingState === StreamingState.Idle) { return null; @@ -34,28 +38,45 @@ export const LoadingIndicator: React.FC<LoadingIndicatorProps> = ({ const primaryText = thought?.subject || currentLoadingPhrase; + const cancelAndTimerContent = + streamingState !== StreamingState.WaitingForConfirmation + ? `(esc to cancel, ${elapsedTime < 60 ? `${elapsedTime}s` : formatDuration(elapsedTime * 1000)})` + : null; + return ( - <Box marginTop={1} paddingLeft={0} flexDirection="column"> + <Box paddingLeft={0} flexDirection="column"> {/* Main loading line */} - <Box> - <Box marginRight={1}> - <GeminiRespondingSpinner - nonRespondingDisplay={ - streamingState === StreamingState.WaitingForConfirmation - ? '⠏' - : '' - } - /> + <Box + width="100%" + flexDirection={isNarrow ? 'column' : 'row'} + alignItems={isNarrow ? 'flex-start' : 'center'} + > + <Box> + <Box marginRight={1}> + <GeminiRespondingSpinner + nonRespondingDisplay={ + streamingState === StreamingState.WaitingForConfirmation + ? '⠏' + : '' + } + /> + </Box> + {primaryText && ( + <Text color={Colors.AccentPurple}>{primaryText}</Text> + )} + {!isNarrow && cancelAndTimerContent && ( + <Text color={Colors.Gray}> {cancelAndTimerContent}</Text> + )} </Box> - {primaryText && <Text color={Colors.AccentPurple}>{primaryText}</Text>} - <Text color={Colors.Gray}> - {streamingState === StreamingState.WaitingForConfirmation - ? '' - : ` (esc to cancel, ${elapsedTime < 60 ? `${elapsedTime}s` : formatDuration(elapsedTime * 1000)})`} - </Text> - <Box flexGrow={1}>{/* Spacer */}</Box> - {rightContent && <Box>{rightContent}</Box>} + {!isNarrow && <Box flexGrow={1}>{/* Spacer */}</Box>} + {!isNarrow && rightContent && <Box>{rightContent}</Box>} </Box> + {isNarrow && cancelAndTimerContent && ( + <Box> + <Text color={Colors.Gray}>{cancelAndTimerContent}</Text> + </Box> + )} + {isNarrow && rightContent && <Box>{rightContent}</Box>} </Box> ); }; |
