perf(web): typing no longer re-renders the traits picker or attach button#23040
Typing in the composer re-rendered the traits picker and the attach button on every keystroke.
Traits picker. It took the whole prompt so it could tell whether Ultrathink was in it. It now takes promptUltrathink ("none" | "prefix" | "body"), which is all it reads while rendering. When a pick edits the prompt, the picker hands the composer an edit through onPromptEdit, and the composer applies it to the live draft. The settings pickers drop the prompt="" and no-op onPromptChange they used to pass.
Attach button. addComposerAttachments was declared before insertAttachmentReferences and insertComposerText, which it calls. The compiler does not memoize a function that refers to a later declaration, so the handler was rebuilt on every render. Those two helpers now come first, and insertAttachmentReferences calls the existing stable insert helpers instead of the cursor-bound ones. That also memoizes foldPastedText and the paste and drop handlers that capture it. No new useStableCallback.
| Interaction (median of 3) | main | this PR |
|---|---|---|
| Type 20 chars: total renders | 344 | 182 |
| Type 20 chars: TraitsPicker / ComposerAttachButton | 20 / 20 | 0 / 0 |
| Type 20 chars with an image attached: total | 302 | 182 |
| Open the slash menu: total | 450 | 402 |
| Traits Medium -> High: total | 288 | 284 |
| File | main | this PR |
|---|---|---|
| ChatComposer.tsx | 6,365 | 6,372 |
Tested:
vp test run src/components/chat/composerProviderState.test.tsx, which adds areadPromptUltrathinkcase.- React Compiler coverage for the touched files: 0 bailouts.
- apps/web typecheck and lint on the changed files.
- Hands-on with Claude Opus in a dev build. Picking Ultrathink adds the prefix. Picking High removes it. Typing "ultrathink" in the body disables the effort options and shows the notice. Pasting an image attaches it.
🤖 Generated with Claude Code
Checks
- SuccessfulCodeRabbitGitHub
Review completed
- Successful
Skipped - Not affected
- Skipped
- Skipped
- Skipped
- SuccessfulRemove preview downloadGitHub
- SuccessfulLabel PR 23040GitHub
- Successful
- Skipped
- SuccessfulLabel PR sizeGitHub
- Successful
- Successful
- SuccessfulCollect PR targetsGitHub
- SuccessfulPrepare PR size configGitHub
- SuccessfulNative fingerprint diffGitHub
- SuccessfulNative fingerprint diffGitHub
- CancelledNative fingerprint diffGitHub
- SuccessfulCheckGitHub
- SuccessfulNative fingerprint diffGitHub
- SkippedRustGitHub
- Skipped
- SkippedRelease SmokeGitHub
- SuccessfulBuild and TypecheckGitHub
- SuccessfulTestGitHub
- SuccessfulTest WebGitHub
- Skipped
- SuccessfulLabel PR sizeGitHub
- SuccessfulLabel PR 23040GitHub
- SuccessfulPrepare PR size configGitHub
- SuccessfulCollect PR targetsGitHub
- SkippedEAS PreviewGitHub
- CancelledNative fingerprint diffGitHub
- SuccessfulTest Server 8GitHub
- SuccessfulTest Server 1GitHub
- SuccessfulTest Server 3GitHub
- SuccessfulTest Server 7GitHub
- SuccessfulTest Server 2GitHub
- SuccessfulTest Server 4GitHub
- SuccessfulTest Server 6GitHub
- SuccessfulChangesGitHub
- SuccessfulTest Server 5GitHub
- SuccessfulLintGitHub
Added 1 commit
- perf(web): typing no longer re-renders the traits picker or attach buttonec8a087
Approvability
Verdict: Approved at ec8a087
Macroscope's review found this PR approvable — This is a bounded web performance refactor that replaces full prompt propagation with a stable Ultrathink summary and live prompt-edit callback, while retaining existing picker behavior. The settings changes remove obsolete no-op props and do not change product defaults or persisted selections.
You can add or adjust custom eligibility rules. Learn more.
@coderabbitai review
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:
906d432e-e446-4b8f-82c2-d3d28b17b25e
📥 Commits
Reviewing files that changed from the base of the PR and between 0bdf33a34dc520d3ab1364cd116686b3492184bd and ec8a0878b4c9eb31ff47432a143893d0fedba6d9.
📒 Files selected for processing: 7
apps/web/src/components/chat/ChatComposer.tsxapps/web/src/components/chat/TraitsPicker.tsxapps/web/src/components/chat/composerProviderState.test.tsxapps/web/src/components/chat/composerProviderState.tsxapps/web/src/components/settings/ProjectDefaultsSettings.tsxapps/web/src/components/settings/SettingsPanels.tsxapps/web/src/components/settings/SourceControlWritingSettings.tsx
💤 Files with no reviewable changes: 3
- apps/web/src/components/settings/ProjectDefaultsSettings.tsx
- apps/web/src/components/settings/SettingsPanels.tsx
- apps/web/src/components/settings/SourceControlWritingSettings.tsx
Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 8 remain after this review.
📝 Walkthrough
The composer now routes trait prompt changes through transformations applied to the current draft. Trait controls use a classified Ultrathink state. Composer text and attachment-reference insertion helpers are relocated earlier in the component.
Changes: Prompt trait editing
Layer / File(s) Summary Ultrathink classification and trait selection
apps/web/src/components/chat/TraitsPicker.tsx,apps/web/src/components/chat/composerProviderState.test.tsxThe picker classifies prompts as none,prefix, orbodyand uses that state for trait selection and visibility. Tests cover these classifications.Draft prompt edit wiring
apps/web/src/components/chat/composerProviderState.tsx,apps/web/src/components/chat/ChatComposer.tsx,apps/web/src/components/settings/ProjectDefaultsSettings.tsx,apps/web/src/components/settings/SettingsPanels.tsx,apps/web/src/components/settings/SourceControlWritingSettings.tsxTrait renderers receive classified prompt state and an edit callback. The composer applies transformations to the current draft and skips unchanged results. Settings picker calls remove unused prompt props and no-op callbacks. Composer text and attachment insertion
Layer / File(s) Summary Relocate composer insertion helpers
apps/web/src/components/chat/ChatComposer.tsxText and attachment-reference insertion helpers move earlier in the component. The helpers validate composer context and apply edits through stable insertion paths; their later duplicate definitions are removed. Priority: ⬇️ Low
Estimated code review effort: 3 (Moderate) | ~20 minutes
Change: Refactor
Suggested reviewers:
maria-rcks
Merge Risk: ⚪ Minimal · up to ec8a0
No actionable regression was established in trait selection or composer insertion. The PR is mergeable after normal checks.
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, measurements, tests, and manual verification. It does not include the required Scope and approval section, and it omits the required before/after … Add the required Problem, Change, Scope and approval, and Verification headings. Document the triaged issue or maintainer approval, or explain why this focused fix is exempt. Add clear before/after UI screenshots and any required recording … Passed Passed checks: 3 passed
Check name Status Explanation Title check Passed The title clearly and concisely describes the main performance change: typing no longer re-renders the traits picker or attach button. 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, measurements, tests, and manual verification. It does not include the required Scope and approval section, and it omits the required before/after screenshots for a UI change.
Resolution
Add the required Problem, Change, Scope and approval, and Verification headings. Document the triaged issue or maintainer approval, or explain why this focused fix is exempt. Add clear before/after UI screenshots and any required recording for interaction timing.
✨ 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
Comment @coderabbitai help to get the list of available commands.
⚠️ Action not completed
Already reviewed the last commit. Use @coderabbitai full review to rerun a review of the entire changeset.
Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.