Skip to content

perf(web): keep chat markdown mounted while text streams - #255

Merged
leoisadev1 merged 2 commits into
mainfrom
fix/web-markdown-stream-stable-components
Sep 11, 2026
Merged

perf(web): keep chat markdown mounted while text streams#255
leoisadev1 merged 2 commits into
mainfrom
fix/web-markdown-stream-stable-components

Conversation

@leoisadev1

Copy link
Copy Markdown
Member

What Changed

ChatMarkdown no longer rebuilds its ReactMarkdown renderer map on every streamed token. Named renderer types live in a module-level CHAT_MARKDOWN_COMPONENTS object and read the current message through ChatMarkdownRendererContext.

Live bot and group chats already use this component from BotThreadLanding and GroupThreadLanding. Code wrap, copy, and details state can now survive trailing text updates, and unchanged fences do not remount.

Why

Each token used to recreate renderer function types. React treated that as a new tree, so code-block controls reset and Shiki ran again even when the fence had not changed.

Adapted from pingdotgg/t3code#9677. Credit to that work.

UI Changes

No intended visual change. Isolated browser check: Scout bot chat still renders ChatMarkdown for the assistant reply, with reply/reaction/read-aloud on the live BotThreadLanding composer.

This fixture home had no group chat, so group-route markdown was not exercised here. The renderer is the same ChatMarkdown path.

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I linked the accepted plugin or provider proposal in Why, or this PR does not add one
  • I included before/after screenshots for any UI changes
  • I included a video for animation/interaction changes

Scope

  • Does not resurrect ChatView.
  • Does not port upstream artifact-template cards, extra remark plugins, or expanded-image media actions. Those belong with later image-gallery work.
  • Does not add react-test-renderer. Stability is guarded by a source test plus the existing ChatMarkdown suite.

Verification

  • vp test run apps/web/src/components/ChatMarkdown.test.tsx passed (36 tests)
  • vp run --filter @t3tools/web typecheck passed
  • Isolated fixture browser: Scout BotThreadLanding still renders the assistant reply through .chat-markdown

Limitations

A live streaming turn was not exercised because the fixture provider instances are disconnected. Native mobile was not run. File preview markdown uses the same component and was covered by existing tests, not a separate browser pass.

Implemented and verified by Grok 4.6 High in Grok Build via Orca.

Streamed assistant text recreated the ReactMarkdown renderer map on
every token, which remounted code controls and details and re-ran
highlighting for unchanged fences. Named renderer types now live in a
module-level map and read message state from context, so live bot and
group ChatMarkdown stays mounted while the text grows.
@vercel

vercel Bot commented Sep 10, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated
akeru-bot-landing Skipped Skipped Sep 10, 2026 6:43pm UTC

Request Review

@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:L labels Sep 10, 2026
@greptile-apps

greptile-apps Bot commented Sep 10, 2026

Copy link
Copy Markdown

Greptile Summary

This update keeps Markdown renderer component identities stable as streamed chat text changes, moving message-specific data through ChatMarkdownRendererContext so interactive code-block and details state can remain mounted. No new issues were identified. The existing non-blocking test-coverage request remains: the test does not update an already-rendered Markdown message to demonstrate state preservation during streaming.

Confidence Score: 5/5

Safe to merge; the remaining test-coverage concern is non-blocking.

The previous finding remains outstanding because ChatMarkdown.test.tsx still performs one static render with trailing text rather than rerendering after interactive code-block or details state has been established. This does not identify a confirmed behavioral regression.

Reviews (2): Last reviewed commit: "Merge branch 'main' into fix/web-markdow..." | Re-trigger Greptile

Comment on lines +53 to +62
it("still renders streamed fences and details after extra trailing text", () => {
const fence = ["```text", "First code block", "```", "", "Streaming reply"].join("\n");
const html = renderToStaticMarkup(
<ChatMarkdown cwd="/tmp/project" text={`${fence} 9`} isStreaming />,
);

expect(html).toContain('data-language="text"');
expect(html).toContain("First code block");
expect(html).toContain("Streaming reply 9");
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Test streaming state

This test renders one static tree containing only a fenced code block and trailing text. It does not include <details>, change an interactive control, or rerender after text changes, so a later change that remounts markdown renderers during streaming could still pass while collapsing expanded details or resetting code controls. This is non-blocking, but add a client-rendered test that expands a details block or changes a code control, appends streamed text, and verifies the same node and its state are retained.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Artifacts

Mounted-state validation test

  • The focused test expands markdown details, updates streamed text, and checks that the same node remains open.

Mounted-state validation command

  • The saved command runs the focused mounted-state validation.

Mounted-state validation output

  • The recorded output shows the focused mounted-state test passed.

View artifacts

T-Rex Ran code and verified through T-Rex

Fix in Claude Code

@leoisadev1

Copy link
Copy Markdown
Member Author

This is Leo's agent. Independently accepted head 424f183 after full diff review, passing focused committed tests, and isolated browser checks in individual and group chats. Twelve successive client message-text updates preserved expanded details and code-node identity on each route; a separate message remained collapsed. Collapse and code-wrap controls worked. These checks used reversible client-state fixtures, not live provider streaming. The committed mounted-rerender coverage request remains valid non-blocking test debt, as the fresh Greptile review states; I am not marking it fixed or resolving the reviewer-owned thread. Required Repository checks passed.

@leoisadev1
leoisadev1 merged commit 15dccaa into main Sep 11, 2026
11 checks passed
@leoisadev1
leoisadev1 deleted the fix/web-markdown-stream-stable-components branch September 11, 2026 09:39
@github-actions github-actions Bot mentioned this pull request Sep 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant