Skip to content

feat(ui): replace composer run-status pill with a transcript working spark#104768

Merged
steipete merged 4 commits into
mainfrom
claude/redesign-is-working-indicator-44961a
Jul 12, 2026
Merged

feat(ui): replace composer run-status pill with a transcript working spark#104768
steipete merged 4 commits into
mainfrom
claude/redesign-is-working-indicator-44961a

Conversation

@steipete

@steipete steipete commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

Closes #104765

What Problem This Solves

While the agent works, the composer footer narrates the run as a bordered pill: rounded-full chip, 1px info-blue border, tinted spinner, blue text cycling through "Sending message...", "Preparing model...", " is responding...". It reads like an alert, competes with the composer controls beside it, and duplicates signals the UI already has (the Stop button, streaming text, running tool rows). On mobile the same status renders as an even heavier full-width bordered box above the input. Meanwhile the transcript's pre-reply feedback was a generic three-dot typing bubble that only covered two narrow states.

Why This Change Was Made

The working indicator moves to where the work appears, Claude-style: the transcript's reading indicator becomes a small pulsing brand spark (icons.spark, --accent) rendered where the reply will materialize, and its trigger broadens to the whole "working with nothing visibly streaming" window — pre-first-token, queued sends, reconnects to running sessions (isChatRunWorking in chat-composer.ts, threaded through buildChatItems as runWorking). One indicator concept, one code path: the three-dot bubble is deleted, not kept alongside.

The spark yields whenever something better signals activity: streamed text replaces it, a visible running tool row suppresses it (no stacked indicators), and the initial-load skeleton keeps priority on an empty thread — while background reloads with visible content keep the spark alive. The composer stops narrating: the visible pill and the mobile progress strip are removed. Two things survive on purpose:

  • "Interrupted" keeps a small visible toast in the composer footer (warn-colored text + icon, no pill chrome, desktop and mobile): a killed run leaves no transcript marker, so silence would read as "finished".
  • A persistent sr-only live region in the composer announces working/done/interrupted phases, replacing the old role="status" pill for screen readers — and unlike the old pill it also announces on mobile.

User Impact

While the agent works you see a small pulsing OpenClaw spark in the transcript where the reply will appear, instead of a blue-bordered spinner pill in the composer. The composer footer stays quiet; Stop/Send behavior is unchanged. Aborted runs still show a brief "Interrupted" note, now on mobile too. Reduced-motion users get a static spark.

Working (before → after, light):

before-working-light
spark-working-light

Working (after, dark) + pulse animation:

spark-working-dark
spark-working-animated

Streaming — content replaces the spark (light):

spark-streaming-light

Interrupted toast (desktop + mobile, light):

spark-interrupted-light
spark-mobile-interrupted

Mobile working (before → after, light):

before-mobile
spark-mobile

Evidence

  • Screenshots captured with the deterministic mock-gateway harness (startControlUiE2eServer + installMockGateway) driving a real send → ack → delta → aborted event sequence; light/dark via prefers-color-scheme.
  • pnpm test ui/src/pages/chat/chat-composer.test.ts ui/src/pages/chat/chat-view.test.ts ui/src/pages/chat/components/chat-message.test.ts ui/src/pages/chat/chat-thread.test.ts ui/src/pages/chat/chat-responsive.browser.test.ts — green (Testbox). Run-status contracts rewritten (spark presence, sr-only announcements, interrupted-only toast) and new builder tests pin the spark rules (background reload keeps it, initial-load skeleton wins, running tool rows suppress it, hidden tool calls keep it).
  • ui/src/e2e/chat-composer-redesign.e2e.test.ts — 6 passed locally (Playwright), asserting spark pre-token, spark yielding to streamed text, and no visible composer run status. chat-flow.e2e.test.ts reading-indicator flows pass; its two failures ("workspace files panel", "worktree chat") reproduce identically with all changes reverted to the branch base — pre-existing local-environment failures, unrelated (ui e2e runs in the live/e2e workflow, not PR CI).
  • pnpm check:changed (Testbox) — format/lint/typecheck lanes green for the committed tree.
  • Autoreview (Codex gpt-5.6-sol, xhigh): first pass flagged three real gaps — spark hidden during background reloads, spark stacking under running tool rows, no visible mobile interrupted state — all fixed in fix(ui): keep working spark through reloads...; fresh run after the fixes is clean ("patch is correct", no accepted findings).

@openclaw-barnacle openclaw-barnacle Bot added app: web-ui App: web-ui size: S maintainer Maintainer-authored PR labels Jul 11, 2026
@clawsweeper clawsweeper Bot added proof: sufficient ClawSweeper judged the real behavior proof convincing. proof: 📸 screenshot Contributor real behavior proof includes screenshot evidence. rating: 🦞 diamond lobster Very strong PR readiness with only minor maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. P3 Low-priority cleanup, docs, polish, ergonomics, or speculative work. labels Jul 11, 2026
@clawsweeper

clawsweeper Bot commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs real behavior proof before merge. Reviewed July 11, 2026, 8:52 PM ET / July 12, 2026, 00:52 UTC.

Summary
Moves active-run feedback from visible composer status chrome to a transcript working spark and screen-reader announcement, while leaving only interrupted terminal status visibly rendered.

PR surface: Source -44, Tests +80. Total +36 across 13 files.

Reproducibility: yes. Current source deterministically suppresses Done, while current main, the PR body, the linked issue, and the submitted after image all establish the expected visible completion confirmation.

Review metrics: 1 noteworthy metric.

  • Visible status states: 2 removed, 1 retained. The branch removes visible in-progress and Done states while retaining Interrupted, which materially changes the user feedback contract beyond chrome styling.

Stored data model
Persistent data-model change detected: vector/embedding metadata: ui/src/styles/chat/layout.css. Confirm migration or upgrade compatibility proof before merge.

Root-cause cluster
Relationship: fixed_by_candidate
Canonical: #104765
Summary: This PR is the direct implementation candidate for the linked canonical Control UI design issue.

Members:

Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything.

Merge readiness
Overall: 🦪 silver shellfish
Proof: 🦪 silver shellfish
Patch quality: 🦐 gold shrimp
Result: blocked until stronger real behavior proof is added.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • Restore the timed visible Done state promised by the issue and PR.
  • Replace the stale media with current-head desktop and mobile proof covering the spark, streaming/tool handoff, Done, and Interrupted.

Proof guidance:

  • [P1] Needs stronger real behavior proof before merge: The linked images and GIF show the earlier composer-text design and visible Done toast, not the latest transcript-spark head; add fresh redacted current-head screenshots or a recording, then update the PR body to trigger a new review or ask a maintainer to comment @clawsweeper re-review.

Mantis proof suggestion
After the Done fix, a web UI chat proof can directly demonstrate the final visible sequence and replace the stale artifacts. A maintainer can ask Mantis to capture proof by posting this exact PR comment:

@openclaw-mantis web UI chat proof: verify and capture the pre-first-token working spark, its handoff to streamed text or a running tool row, and the Done and Interrupted outcomes on desktop and mobile.

Risk before merge

  • [P1] Merging this head removes the existing brief visible Done confirmation even though the issue, PR narrative, and submitted proof say it remains.
  • [P1] Reviewers cannot validate the actual latest UI from the supplied media because all after artifacts predate the transcript-spark redesign.

Maintainer options:

  1. Decide the mitigation before merge
    Keep the transcript spark as the active-work signal, restore the existing timed borderless Done toast alongside Interrupted, and attach fresh desktop/mobile proof from the final head.
  2. Pause or close
    Do not merge this PR until maintainers decide whether the risk is worth taking.

Next step before merge

  • [P1] The contributor should restore the defined Done behavior and provide final-head proof; the proof gate requires contributor evidence rather than an automated repair job.

Security
Cleared: The focused UI source, CSS, and test diff adds no dependency, workflow, secret, permission, or executable supply-chain surface.

Review findings

  • [P2] Restore the visible Done confirmation — ui/src/pages/chat/components/chat-composer.ts:1356-1358
Review details

Best possible solution:

Keep the transcript spark as the active-work signal, restore the existing timed borderless Done toast alongside Interrupted, and attach fresh desktop/mobile proof from the final head.

Do we have a high-confidence way to reproduce the issue?

Yes. Current source deterministically suppresses Done, while current main, the PR body, the linked issue, and the submitted after image all establish the expected visible completion confirmation.

Is this the best way to solve the issue?

No in its current form. Moving active feedback into the transcript is the cleaner shared visual language, but deleting the promised Done confirmation is unnecessary and the final design lacks matching real-behavior proof.

Full review comments:

  • [P2] Restore the visible Done confirmation — ui/src/pages/chat/components/chat-composer.ts:1356-1358
    This now returns nothing for done, although current main shows a timed Done status and both the linked issue and PR body explicitly retain terminal-state feedback. A normally completed run therefore loses its brief visible completion confirmation; keep the borderless timed Done status and limit the transcript-spark replacement to active work. This was equally visible at the earlier reviewed head, so this is a late discovery.
    Confidence: 0.98
    Late finding: first raised on code an earlier review cycle already covered.

Overall correctness: patch is incorrect
Overall confidence: 0.97

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against e7c3f7be6c83.

Label changes

Label changes:

  • add rating: 🦪 silver shellfish: Overall readiness is 🦪 silver shellfish; proof is 🦪 silver shellfish and patch quality is 🦐 gold shrimp.
  • add status: 📣 needs proof: The PR needs real behavior proof before ClawSweeper can clear the contributor ask. Needs stronger real behavior proof before merge: The linked images and GIF show the earlier composer-text design and visible Done toast, not the latest transcript-spark head; add fresh redacted current-head screenshots or a recording, then update the PR body to trigger a new review or ask a maintainer to comment @clawsweeper re-review.

Label justifications:

  • P3: The PR is a limited Control UI feedback and visual-polish change without core workflow or data risk.
  • rating: 🦪 silver shellfish: Overall readiness is 🦪 silver shellfish; proof is 🦪 silver shellfish and patch quality is 🦐 gold shrimp.
  • status: 📣 needs proof: The PR needs real behavior proof before ClawSweeper can clear the contributor ask. Needs stronger real behavior proof before merge: The linked images and GIF show the earlier composer-text design and visible Done toast, not the latest transcript-spark head; add fresh redacted current-head screenshots or a recording, then update the PR body to trigger a new review or ask a maintainer to comment @clawsweeper re-review.
Evidence reviewed

PR surface:

Source -44, Tests +80. Total +36 across 13 files.

View PR surface stats
Area Files Added Removed Net
Source 8 110 154 -44
Tests 5 227 147 +80
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 13 337 301 +36

What I checked:

  • Current-main contract: Current main renders visible in-progress, Done, and Interrupted statuses, with terminal statuses expiring after the existing toast duration. (ui/src/pages/chat/components/chat-composer.ts:1260, e7c3f7be6c83)
  • Changed terminal behavior: The PR renderer returns no visible output for Done and renders only Interrupted, so normally completed runs lose their existing brief visual confirmation. (ui/src/pages/chat/components/chat-composer.ts:1356, d4db97d4743e)
  • Defined PR expectation: The PR body and linked issue explicitly state that terminal states retain their icon and semantic color, so removing Done contradicts the authored behavior contract rather than merely changing styling. (d4db97d4743e)
  • Stale real-behavior proof: The downloaded after images show visible composer working text and a visible Done status, neither of which the latest head renders; the assets prove an earlier head, not the proposed final behavior. (ui/src/pages/chat/components/chat-composer.ts:1356, d4db97d4743e)
  • Prior review continuity: The earlier mobile Interrupted finding is addressed by the latest commit, which removes the mobile hide rule and adds a grid slot and focused Interrupted test; it is not re-raised. (ui/src/styles/chat/layout.css:2741, d4db97d4743e)
  • Focused patch scope: The merge-base patch is limited to 13 Control UI source, CSS, and test files and adds cache-key coverage for the new runWorking and loading inputs. (ui/src/pages/chat/chat-thread.ts:1365, d4db97d4743e)

Likely related people:

  • Vincent Koc: Commit a426213 is the clearest current-main history point containing the existing composer status implementation and tests. (role: recent integration author; confidence: medium; commits: a426213f0ab1; files: ui/src/pages/chat/components/chat-composer.ts, ui/src/pages/chat/chat-composer.test.ts, ui/src/styles/chat/layout.css)
  • BunsDev: Val Alexander authored several merged Control UI polish changes across chat-adjacent layout, themes, and interaction surfaces, making this a useful design-review route. (role: recent Control UI design contributor; confidence: medium; commits: 2cfb660a9bb8, a710366e9ece, 21ac4b9a8a84; files: ui/src/pages/chat/components/chat-composer.ts, ui/src/styles/chat/layout.css, ui/src/styles/chat/tool-cards.css)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.
Review history (1 earlier review cycle)
  • reviewed 2026-07-11T23:17:08.945Z sha f11fc4d :: needs maintainer review before merge. :: none

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 13a7975bec

ℹ️ 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".

Comment on lines +2673 to 2677
${composerRunStatus?.phase === "interrupted"
? html`
<div class="agent-chat__composer-run-status">
${renderChatRunStatusIndicator(composerRunStatus, inProgressLabel)}
${renderChatRunStatusIndicator(composerRunStatus)}
</div>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep interrupted status visible on mobile

When a run is interrupted, this branch now renders the only visible status into .agent-chat__composer-run-status; the old mobile .agent-chat__composer-progress strip was removed, and ui/src/styles/chat/layout.css:2749-2752 still hides .agent-chat__composer-run-status at mobile widths. On phones/tablets, stopping a run therefore leaves only the sr-only live region and no visible confirmation, even though interrupted runs do not add a transcript marker. Please keep a visible mobile status slot or avoid hiding this element for the interrupted state.

Useful? React with 👍 / 👎.

@clawsweeper clawsweeper Bot added rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. and removed proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🦞 diamond lobster Very strong PR readiness with only minor maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. proof: 📸 screenshot Contributor real behavior proof includes screenshot evidence. labels Jul 12, 2026
@steipete steipete changed the title feat(ui): redesign composer run-status indicator as chrome-free status text feat(ui): replace composer run-status pill with a transcript working spark Jul 12, 2026
@steipete
steipete merged commit 9a04fb4 into main Jul 12, 2026
138 of 143 checks passed
@steipete
steipete deleted the claude/redesign-is-working-indicator-44961a branch July 12, 2026 01:08
@steipete

Copy link
Copy Markdown
Contributor Author

Merged via squash.

fakoli added a commit to fakoli/openclaw that referenced this pull request Jul 12, 2026
- void the now-async submitToolResult calls in the anvil-voice test
- oxfmt scripts/sync-fakoli-fork-main.mjs
- sync control-ui i18n raw-copy baseline + locale meta (upstream
  openclaw#104768 left Interrupted strings out of the baseline; path-filtered
  upstream CI never ran the check)
- drop unused WatchInboxStore.shouldShowExecApprovalReviewStatus
  (upstream openclaw#104913, flagged by the iOS periphery scan)
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request Jul 12, 2026
…spark (openclaw#104768)

* feat(ui): redesign composer run-status indicator as chrome-free status text

* feat(ui): replace run-status text with transcript working spark

* fix(ui): keep working spark through reloads, dodge running tool rows, show mobile interrupted toast

* fix(ui): satisfy lint on tool-stream marker access
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

app: web-ui App: web-ui maintainer Maintainer-authored PR P3 Low-priority cleanup, docs, polish, ergonomics, or speculative work. rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. size: L status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Control UI: composer run-status pill is visually heavy

1 participant