Skip to content

Show Chat research status with the document research card - #341

Merged
MaggieAppleton merged 3 commits into
mainfrom
design/research-status-card
Oct 8, 2026
Merged

MaggieAppleton merged 3 commits into
mainfrom
design/research-status-card

Conversation

@MaggieAppleton

@MaggieAppleton MaggieAppleton commented Oct 7, 2026 •

Copy link
Copy Markdown
Collaborator

Why

After Start, the Chat research card kept its "Research suggestion" heading and showed the raw stage enum ("Research searching", "Research queued"), sometimes stepping backwards, with no progress or Cancel. The document card for the same request already had a designed vocabulary ("Searching sources", track, Cancel/Retry). The two surfaces read like two products. The document card also set the whole multi-line brief in bold.

What changed

  • Accepted offers in Chat render the document's ResearchCard (one vocabulary, one motion): stage words, 5-step track, sources found, Cancel while active, Retry when failed, ready title and summary that opens the report. The card aligns with the message text column.
  • Before the request is readable, the card shows the brief as "Waiting to start" instead of "Loading research…". Resume / Retry link check stay as a quiet row under the card.
  • An active request's stage never steps backwards in Chat (forwardStage); terminal and retried stages always show.
  • Document and Chat cards: the brief is regular weight, clamped to two lines with Show more / Show less. Report titles stay semibold.
  • A card that changes state in this session settles in (200 ms opacity/translate, reduced-motion off).

No server changes.

Screenshots

Searching, before / after
searching

Failed, before / after
failed

Ready, before / after
ready

Phone width
phone

Rendered from the real Transcript with a scripted research store (this instance cannot run web research).

Testing

  • bun test apps/web/src/chat — 162 pass
  • bun test packages/editor/src/widgets/research — 30 pass
  • bun --bun node_modules/@playwright/test/cli.js test --config e2e/source/playwright.config.ts research-offers.native.ts --timeout 300000 — 5 pass (updated for the new vocabulary)
  • bun run ci, bun run types — pass
  • e2e/research-offers-ui.e2e.ts ready-state assertions updated; relying on CI browser integration (local E2E suspended)

🤖 Generated with Claude Code

@MaggieAppleton

Copy link
Copy Markdown
Collaborator Author

Review: Looks good

Checked in the real app: #348's head on a fake-GitHub server with the fake Planner and fake Jev, CONVERSATION_PLAN=on. Port 8797 was taken by the 8795 reference server, so the fake MCP ran on 8897 through a local, uncommitted fixture change. I started research from Chat through the real offer flow. With this harness, web search fails within about a second. Running ("Waiting to start" → "Searching sources", with Cancel and the track) and failed (with Retry) are real-app states. Ready could not be reached; it is covered only by the updated e2e and the author's scripted screenshots.

What works:

  • The Chat card is the document ResearchCard. Next to the document card for the same request (failed state), they read as one family: same indicator, stage words, callout, and Retry. The only difference is the document's remove ×.
  • Retry from Chat works: 200, then "Searching sources" with Cancel.
  • The Chat card settles in over about 200 ms with opacity and translate, and is turned off for reduced motion.
  • At phone width (390) the failed card fits the message column. The brief clamps to two lines with Show more.
  • CI is green: container, e2e, and format/lint/types/tests. Locally, bun run ci, bun run types, and bun test apps/web/src/chat packages/editor/src/widgets/research (192 pass) all pass.

Findings (none blocking):

  1. A disabled "Resume" row flashes on every Start. apps/web/src/chat/research-offer.tsx, AcceptedResearch: while the link is pending, canResume is true, so a disabled "Resume" button renders under the card for about 100–180 ms (seen in frame captures) until the link becomes linked. The layout jumps when the row leaves. Suggest showing Resume only for unlinked or an exhausted error, not pending. This is a Chat-only change, so it belongs here.
  2. Cancel could not be confirmed. Both Cancel attempts (one clicked right after Retry) got 409 {"error":"research workspace is not ready"}. The card then stacked "Research could not be cancelled." above the real failure. With this harness the job may already have failed by then, so this may only be a race. It still means Cancel shows in "Waiting to start" while the server may refuse it. Suggest clearing actionError from a cancel when the request reaches a terminal stage. Please also confirm a successful Cancel against a slower job.
  3. forwardStage writes a ref during render. shown.current = stage in render. It works and is idempotent. The ref also isn't reset if id changes; that's harmless today because one offer maps to one request.
  4. Show more has no focus style. packages/editor/src/styles.css, .plan-research-more has no :focus-visible style beyond the browser default. Its margin-block-start: 0.125rem is a raw value, though the token check passes.

Document card (top) and Chat card (bottom) for the same failed request:
family

Frames 0–350 ms after Start, showing the disabled Resume row in frames 2 and 3:
resume flash

@MaggieAppleton

Copy link
Copy Markdown
Collaborator Author

Addressed in 2c98b5e:

  1. Resume now shows for unlinked straight away, and for pending only after the link has stayed pending for 1.5 s. That removes the flash after Start but still offers Resume for a request that is really stuck; the seeded pending e2e relies on that.
  2. If the server refuses a cancel because the request is not ready yet, Chat retries it up to 3 times, 600 ms apart. If it still fails, the message is the quieter "Research could not be cancelled yet.", and it clears once the request reaches a terminal stage.
  3. The displayed stage now lives in state, keyed by request id, and is updated with React's adjust-state-during-render pattern. Render no longer writes a ref.
  4. .plan-research-more has a :focus-visible ring from the focus-ring tokens and uses calc(var(--spacing) * 0.5) for its margin.
    Also updated the stale "Research accepted" assertion in research-offers-ui.e2e.ts, which only runs with E2E_RESEARCH_OFFERS=1.

@MaggieAppleton

Copy link
Copy Markdown
Collaborator Author

Follow-up in bc36c2e: focus.test.ts requires focus outlines to come from the theme, so I removed my :focus-visible outline. Show more now gets the theme's standard ring, keeps its colour change on focus, and has a small radius so the ring fits. CI is green.

MaggieAppleton and others added 3 commits October 8, 2026 01:30
Accepted research offers in Chat now render the document's research card:
the same stage words, track, Cancel and Retry, and ready state. Active
stages no longer step backwards, and the brief is set in regular weight,
clamped to two lines with Show more.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Resume waits until a pending link stalls, a cancel the server refuses while
the request starts retries briefly and its error clears once the request
settles, the stage is tracked in state rather than written during render,
and Show more gains a focus ring and a spacing token.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@MaggieAppleton
MaggieAppleton force-pushed the design/research-status-card branch from bc36c2e to 640c1f6 Compare October 8, 2026 00:39
@MaggieAppleton
MaggieAppleton merged commit f2d383a into main Oct 8, 2026
3 checks passed
@MaggieAppleton
MaggieAppleton deleted the design/research-status-card branch October 8, 2026 00:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant