Level up the thinking orb and make the whole thinking UI/UX feel alive - #22
Conversation
The liquid orb becomes a layered composition instead of a bare canvas:
a breathing bloom halo painted outside the canvas square (both
renderers), a rotating conic liquid sphere under a fixed glass sheen as
a rich fallback that stands in from first paint until WebGPU's first
frame, and a scale-in entrance. Reduced motion keeps a still, lit
sphere.
The three thinking surfaces — transcript line, packaged-chat cursor,
and activity bar — now share one vocabulary in thinking-status.ts: a
single elapsed-seconds hook anchored to wall-clock time and an
escalating label ("Thinking" → "Still thinking" → "Working through it"
→ "Still working") so a long wait visibly stays alive everywhere it is
drawn, with the seconds count still appearing after 5s. The cursor and
transcript line also gain a motion-safe fade/slide entrance.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PKhN2rgAuEbGHyiLvpPY52
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b8ae13f02e
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const started = Date.now(); | ||
| setSeconds(0); |
There was a problem hiding this comment.
Anchor status timers to the turn instead of each mount
When a channel turn runs for at least 45 seconds and a tool finishes, shouldShowThinking remounts the transcript's Thinking component while the activity bar remains mounted for the entire in-flight turn. Each hook instance captures a fresh start here, so the two simultaneously visible surfaces can report contradictory states such as “Thinking” in the transcript and “Still working · 45s” in the bar. Pass a shared turn start time or otherwise preserve elapsed time across thinking-line remounts.
Useful? React with 👍 / 👎.
| * looks like one product wherever it happens. */} | ||
| <LiquidThinkingOrb /> | ||
| <span className="tool-line-running">Thinking…</span> | ||
| <span className="tool-line-running">{thinkingStatusText(seconds)}</span> |
There was a problem hiding this comment.
Keep per-second elapsed ticks out of the live region
For screen-reader users during waits longer than five seconds, this text changes every second inside an element with both role="status" and aria-live="polite", which can repeatedly announce or queue the entire status instead of providing occasional progress feedback. Keep the visible seconds in a separate aria-hidden element, as the activity bar does, and reserve the live region for milestone label changes.
Useful? React with 👍 / 👎.
Summary
Two commits that level up the model-thinking experience end to end.
Commit 1 — the orb and the thinking vocabulary.
liquid-thinking-orb.tsx+styles.css) becomes a layered composition instead of a bare canvas: a breathing bloom halo painted outside the canvas square under both renderers (the WebGPU shader clips at its square, so this is the only layer that can throw light past the sphere's limb), a much richer CSS fallback sphere — a rotating conic liquid body under a fixed specular glass sheen, replacing the old static two-gradient pulse — that stands in from first paint until WebGPU's first frame and permanently where WebGPU is absent, and a quick scale-in entrance. No WGSL changes; the render loop and device sharing are untouched.thinking-status.ts: a single wall-clock-anchored elapsed hook and an escalating label ("Thinking" → 8s "Still thinking" → 20s "Working through it" → 45s "Still working"), with the seconds count after 5s on all three (the packaged-chat cursor was previously a static "Thinking…").Commit 2 — the orb as one continuous character, and five new surfaces.
--orb-sizevariable) where the anonymous step spinner was. The thinking line yields exactly when a tool starts (shouldShowThinking), so to the reader the orb moves into the work instead of handing off to a spinner. The now-unused.step-spinnerCSS is removed.lib/tab-status.ts): a pulsing orb-blue favicon dot and "●" title prefix while a turn runs; if the answer lands while the tab is hidden, the dot becomes a green check and the title says "✓" until the person next looks. No notification permission involved; a turn starting cancels a stale unseen check.data-testid="transcript-receipt") takes the thinking line's slot until the next turn starts. Turns under 10s earn no receipt; ≥90s bills in minutes.busy's falling edge and removed after 1.6s so remounts can never replay it.scrollToMessage— sampled down past 20 marks, hidden belowmd.AnimatePresenceinstead of popping between frames.All new movement is transform/opacity only, and reduced motion is respected on every piece. Existing testids and roles are preserved.
Change type
Safety and compatibility
Distributed-system behavior
Frontend-only presentation change; no server code touched.
visibilitychangelistener in the browser tab only).Validation
bun run format:checkbun run lint— exits 0; its 24 printed warnings are pre-existing on a clean treebun run typecheck— run for commit 1 (app package); skipped for commit 2 at the author's request to ship quickly — please let CI confirmbun run test— 46/46 channel/app component tests pass, including newthinking-statusandchat-messagescases; 4 server DB integration tests fail in this environment for lack of a Postgres instance, unchanged by this PRbun run build— run for commit 1; commit 2 rides on CI🤖 Generated with Claude Code
https://claude.ai/code/session_01PKhN2rgAuEbGHyiLvpPY52