MCPcopy
hub / github.com/claude-code-best/claude-code / BriefSpinner

Function BriefSpinner

src/components/Spinner.tsx:412–483  ·  view source on GitHub ↗
({ mode, overrideMessage }: BriefSpinnerProps)

Source from the content-addressed store, hash-verified

410};
411
412function BriefSpinner({ mode, overrideMessage }: BriefSpinnerProps): React.ReactNode {
413 const settings = useSettings();
414 const reducedMotion = settings.prefersReducedMotion ?? false;
415 const [randomVerb] = useState(() => sample(getSpinnerVerbs()) ?? 'Working');
416 const verb = overrideMessage ?? randomVerb;
417 const connStatus = useAppState(s => s.remoteConnectionStatus);
418
419 // Track CLI activity so OS/IDE "busy" indicators fire in brief mode too
420 useEffect(() => {
421 const operationId = 'spinner-' + mode;
422 activityManager.startCLIActivity(operationId);
423 return () => {
424 activityManager.endCLIActivity(operationId);
425 };
426 }, [mode]);
427
428 // Drive both dot cycle and shimmer from the shared clock. The viewport
429 // ref is unused — the spinner unmounts on turn end so viewport-based
430 // pausing isn't needed.
431 const [, time] = useAnimationFrame(reducedMotion ? null : 120);
432
433 // Local tasks + remote tasks are mutually exclusive (viewer mode has an
434 // empty local AppState.tasks; local mode has remoteBackgroundTaskCount=0).
435 // Summing avoids a mode branch.
436 const runningCount = useAppState(s => count(Object.values(s.tasks), isBackgroundTask) + s.remoteBackgroundTaskCount);
437
438 // Connection trouble overrides the verb — `claude assistant` is a pure viewer,
439 // nothing useful is happening while the WS is down.
440 const showConnWarning = connStatus === 'reconnecting' || connStatus === 'disconnected';
441 const connText = connStatus === 'reconnecting' ? 'Reconnecting' : 'Disconnected';
442
443 // Dots padded to a fixed 3 columns so the right-aligned count doesn't
444 // jitter as the cycle advances.
445 const dotFrame = Math.floor(time / 300) % 3;
446 const dots = reducedMotion ? '… ' : '.'.repeat(dotFrame + 1).padEnd(3);
447
448 // Shimmer: reverse-sweep highlight across the verb. Skip for connection
449 // warnings (shimmer reads as "working"; Reconnecting/Disconnected is not).
450 const verbWidth = useMemo(() => stringWidth(verb), [verb]);
451 const glimmerIndex =
452 reducedMotion || showConnWarning ? -100 : computeGlimmerIndex(Math.floor(time / SHIMMER_INTERVAL_MS), verbWidth);
453 const { before, shimmer, after } = computeShimmerSegments(verb, glimmerIndex);
454
455 const { columns } = useTerminalSize();
456 const rightText = runningCount > 0 ? `${runningCount} in background` : '';
457 // Manual right-align via space padding — flexGrow spacers inside
458 // FullscreenLayout's `main` slot don't resolve a width and caused the
459 // diff engine to miss dot-frame updates.
460 const leftWidth = (showConnWarning ? stringWidth(connText) : verbWidth) + 3;
461 const pad = Math.max(1, columns - 2 - leftWidth - stringWidth(rightText));
462
463 return (
464 <Box flexDirection="row" width="100%" marginTop={1} paddingLeft={2}>
465 {showConnWarning ? (
466 <Text color="error">{connText + dots}</Text>
467 ) : (
468 <>
469 {before ? <Text dimColor>{before}</Text> : null}

Callers

nothing calls this directly

Calls 11

useAnimationFrameFunction · 0.90
useSettingsFunction · 0.85
getSpinnerVerbsFunction · 0.85
useAppStateFunction · 0.85
countFunction · 0.85
computeGlimmerIndexFunction · 0.85
computeShimmerSegmentsFunction · 0.85
useTerminalSizeFunction · 0.85
startCLIActivityMethod · 0.80
endCLIActivityMethod · 0.80
maxMethod · 0.80

Tested by

no test coverage detected