forked from bots-garden/ori
| ✨ Workspace panel, selectors, previews, desktop app, sandbox template, resizable file tree, light/dark theme | 1 | /** |
| 2 | * WorkingIndicator shows that the agent is busy: a spinner next to a whimsical | |
| 3 | * phrase that rotates every few seconds, in the spirit of Claude's own | |
| 4 | * "Pondering…" status line. | |
| 5 | * | |
| 6 | * @example | |
| 7 | * {turnActive && <WorkingIndicator />} | |
| 8 | */ | |
| 9 | ||
| 10 | import { useEffect, useState } from "react"; | |
| 11 | ||
| 12 | /** The rotating status phrases; exported so tests can assert against them. */ | |
| 13 | export const workingPhrases = [ | |
| 14 | "Pondering…", | |
| 15 | "Connecting the dots…", | |
| 16 | "Brewing ideas…", | |
| 17 | "Reading between the lines…", | |
| 18 | "Sketching a plan…", | |
| 19 | "Turning gears…", | |
| 20 | "Chasing a thought…", | |
| 21 | "Polishing the answer…", | |
| 22 | ]; | |
| 23 | ||
| 24 | /** How long each phrase stays on screen, in milliseconds. */ | |
| 25 | export const phraseIntervalMs = 2500; | |
| 26 | ||
| 27 | export function WorkingIndicator() { | |
| 28 | const [index, setIndex] = useState(0); | |
| 29 | ||
| 30 | useEffect(() => { | |
| 31 | const timer = setInterval( | |
| 32 | () => setIndex((current) => (current + 1) % workingPhrases.length), | |
| 33 | phraseIntervalMs, | |
| 34 | ); | |
| 35 | return () => clearInterval(timer); | |
| 36 | }, []); | |
| 37 | ||
| 38 | return ( | |
| 39 | <output className="working"> | |
| 40 | <span className="spinner" aria-hidden /> | |
| 41 | <span className="working-phrase">{workingPhrases[index]}</span> | |
| 42 | </output> | |
| 43 | ); | |
| 44 | } |