# refactor\(web\): chat markdown tables and details live in their own components · PR \#22692 · pingdotgg/t3code

[View on GitCafe](https://git.cafe/pingdotgg/t3code/pull/22692)

Repository: [pingdotgg/t3code](https://git.cafe/pingdotgg/t3code)

Visibility: public

State: merged

Source repository: pingdotgg/t3code

Source branch: refactor/chat-markdown-tables

Target branch: refactor/chat-markdown-mermaid

Head commit: a29a8ee9b496e3489fa3127b38f26a24acf88a64

[Discussion and reviews](https://git.cafe/pingdotgg/t3code/pull/22692)

[Commits](https://git.cafe/pingdotgg/t3code/pull/22692/commits?format=markdown)

[Files changed](https://git.cafe/pingdotgg/t3code/pull/22692/diffs?format=markdown)

## Description

---

ChatMarkdown.tsx was a 3,560-line file that held every markdown renderer. This stack splits it into focused modules so each piece is readable on its own.

`MarkdownTable` moves to `chat/MarkdownTable.tsx`, with its clipped-cell measuring and copy menu. The collapsible details block moves to `chat/MarkdownDetails.tsx`.

This is a pure move. Each renderer was already its own component, so no render boundary changes. Behavior is unchanged.

| | Before | After |
|---|---|---|
| `ChatMarkdown.tsx` lines | 2992 | 2776 |
| New files | | chat/MarkdownTable.tsx (167), chat/MarkdownDetails.tsx (65) |
| Renders | unchanged: no component, subscription or context boundary moved | unchanged |

Renders were not measured for this layer. It changes no render boundaries: the components, their props, and the two contexts stay exactly as they were.

Tests run:
- `vp test run --project browser src/components/ChatMarkdown.browser.test.tsx src/components/ChatMarkdown.permissions.browser.test.tsx` (11 passed)
- `vp test run --project unit src/reactCompilerCoverage.test.ts` for every touched file (0 bailouts)
- `tsc --noEmit` for apps/web, and `vp lint` on changed files

🤖 Generated with [Claude Code](https://claude.com/claude-code)
