refactor(web): composer attachment tiles live in their own component#22689
ChatComposer.tsx is about 7,400 lines, which makes it hard to read and gives the React Compiler one huge component to cache. This is the first layer of a stack that splits it up.
The image, SnapShot and video tiles, the non-media file list, and the draft file preview dialog move into ComposerAttachmentStrip.tsx. The strip reads upload progress from useAttachmentUploadStore itself.
ChatComposer builds the media row and the file list as element consts outside the form's JSX. That JSX is rebuilt on every keystroke, so building the elements there re-rendered every tile while you typed. ChatComposer passes its remove handlers straight through. The preview dialog gets the preview-id state setter and closes itself. This adds no useStableCallback uses; ChatComposer keeps the 34 it has on main. Behavior is unchanged.
| main | this PR | |
|---|---|---|
| ChatComposer.tsx lines | 7,403 | 7,016 |
| ComposerAttachmentStrip.tsx lines | n/a | 535 |
| Renders, 20 typed chars | 678 | 678 |
| Renders, 20 typed chars with one image attached | 702 | 622 (the tiles no longer re-render) |
Renders measured with the shared fiber counter (rc-init.js) on a seeded dev server: typing 20 characters into an existing thread's composer, median of 3 runs.
Tests run: vp lint and vp fmt --check on the changed files, tsc-rs --noEmit for apps/web, and reactCompilerCoverage.test.ts for the changed files (0 bailouts).
🤖 Generated with Claude Code
Checks
- SuccessfulCodeRabbitGitHub
Review completed
- Successful
Skipped - Not affected
- Skipped
- Skipped
- Skipped
- SuccessfulRemove preview downloadGitHub
- Skipped
- SuccessfulLabel PR sizeGitHub
- SuccessfulLabel PR 22689GitHub
- Successful
- Successful
- Successful
- SuccessfulCollect PR targetsGitHub
- SuccessfulPrepare PR size configGitHub
- SuccessfulCheckGitHub
- SuccessfulNative fingerprint diffGitHub
- SkippedRustGitHub
- SkippedRelease SmokeGitHub
- Skipped
- SuccessfulBuild and TypecheckGitHub
- SuccessfulTest WebGitHub
- SuccessfulTestGitHub
- SuccessfulLabel PR 22689GitHub
- Skipped
- SuccessfulLabel PR sizeGitHub
- SkippedEAS PreviewGitHub
- SuccessfulCollect PR targetsGitHub
- SuccessfulPrepare PR size configGitHub
- SkippedDeploy web previewGitHub
- SuccessfulTest Server 2GitHub
- SuccessfulTest Server 8GitHub
- SuccessfulTest Server 1GitHub
- SuccessfulTest Server 4GitHub
- SuccessfulTest Server 5GitHub
- SuccessfulTest Server 6GitHub
- SuccessfulTest Server 7GitHub
- SuccessfulTest Server 3GitHub
- SuccessfulChangesGitHub
- SuccessfulNative fingerprint diffGitHub
- SuccessfulLintGitHub
Added 1 commit
- refactor(web): composer attachment tiles live in their own component1122a85
Approvability
Verdict: Approved at 1122a85
Macroscope's review found this PR approvable — This refactor extracts the composer’s existing attachment rendering and preview logic into a dedicated component without changing its behavior, data contracts, or product defaults. The new file is primarily relocated code with explicit prop plumbing and preserved handlers/effects.
You can add or adjust custom eligibility rules. Learn more.
No actionable comments were generated in the recent review. 🎉
ℹ️ Recent review info
⚙️ Run configuration
- Configuration used: Path: .coderabbit.config.ts
- Review profile: CHILL
- Plan: Team
- Run ID:
af45a4e1-3bb5-4cee-beeb-960f96b63e19
📥 Commits
Reviewing files that changed from the base of the PR and between 163bdeaa119f32bf92f25d2841048b808df542a5 and 1122a852bc1639e9a64142e58de97f38125c1336.
📒 Files selected for processing: 2
apps/web/src/components/chat/ChatComposer.tsxapps/web/src/components/chat/ComposerAttachmentStrip.tsx
Limit details: You’ve used all 10 included reviews currently available.
📝 Walkthrough
ChatComposer now delegates attachment media, file-list, and preview rendering to dedicated components. The new components render attachment previews and provide upload progress, retry, removal, and snapshot animation behavior.
Changes: Composer attachments
Layer / File(s) Summary Attachment rendering components
apps/web/src/components/chat/ComposerAttachmentStrip.tsxAdded components for media attachments, non-media files, and file previews. They handle previews, upload progress and retries, removal, snapshot animations, and persistence warnings. ChatComposer integration
apps/web/src/components/chat/ChatComposer.tsxChatComposer now passes attachment state and callbacks to the new components. It replaces the inline attachment renderers and preview dialog with the shared components. Priority: ⬇️ Low
Estimated code review effort: 3 (Moderate) | ~20 minutes
Change: Refactor
Suggested reviewers:
t3dotgg
Merge Risk: ⚪ Minimal · up to 1122a
This refactor moves attachment rendering into its own component without a behavior change. No concrete merge-blocking risk was identified.
Pre-merge checks: Passed 3 · Failed 1
Failed Failed checks: 1 warning
Check name Status Explanation Resolution Description check Warning The description explains the problem, implementation, performance measurements, and verification steps. It does not provide the required Scope and approval section or the required before/after UI scre… Add the Problem, Change, Scope and approval, and Verification sections. Include the linked issue or explicit maintainer approval, plus before/after screenshots and a recording if interaction or motion requires it. Passed Passed checks: 3 passed
Check name Status Explanation Title check Passed The title clearly and concisely describes the main change: moving composer attachment tiles into a dedicated component. Linked Issues check Passed Check skipped because no linked issues were found for this pull request. Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Full details: Description check
Explanation
The description explains the problem, implementation, performance measurements, and verification steps. It does not provide the required Scope and approval section or the required before/after UI screenshots, and it does not use the template headings.
Resolution
Add the Problem, Change, Scope and approval, and Verification sections. Include the linked issue or explicit maintainer approval, plus before/after screenshots and a recording if interaction or motion requires it.
✨ Finishing Touches
📝 Generate docstrings
- Commit to this branch
- Create a new PR
🧪 Generate unit tests (beta)
- Commit to this branch
- Create a new PR
- Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
Usage-based review receipt
- Mode: Continue automatically
- Reviewed files: 2
- Charged: $0.50
- View usage details
Note
This review was completed with usage-based billing: files reviewed beyond your plan's included limits are billed at $0.25/file. View usage-based billing.
Comment @coderabbitai help to get the list of available commands.