fix(web): Compose input no longer adds stray quotes#20350

merged1
main
GitHub fork: fix/compose-key-input
opened13d agobyJJohnnyBill
View on GitHubTwo-way sync enabledPR last imported 9d ago

Problem

In the web/desktop composer, Right Alt (Compose), ", then o can leave ö·" instead of just ö. Composing é can also leave stray quotes. The editor mistakes the replacement range of provisional composition text for a selection to surround with delimiters.

Change

Only surround a matching, nonempty TextSelection when composition is inactive. This lets the editor replace provisional text normally, including changes processed after compositionend, while preserving quote/bracket wrapping of explicitly selected text. Existing chip, styled-text, and literal-answer protections remain in place.

The handler is shared by plain/rich composer modes and web/desktop. Native mobile uses a different editor.

Scope and approval

Fixes #16859. This is the focused guard described in the maintainer response, with regression tests and native Compose recordings. Related prior fix: #12644.

Verification

Five new regression cases fail before the fix; all seven input cases pass after it. All 24 focused tests pass, along with web typecheck and targeted lint/format checks:

sh
1vp test run \
2 apps/web/src/components/ComposerPromptEditorTiptap.input.test.tsx \
3 apps/web/src/components/ComposerPromptEditorTiptap.navigation.test.tsx \
4 apps/web/src/components/ComposerPromptEditorTiptap.citationDraft.test.tsx \
5 apps/web/src/composer-undo-grouping.test.ts
6(cd apps/web && vp run typecheck)
7vp lint apps/web/src/components/ComposerPromptEditorTiptap.tsx apps/web/src/components/ComposerPromptEditorTiptap.input.test.tsx
8vp fmt --check apps/web/src/components/ComposerPromptEditorTiptap.tsx apps/web/src/components/ComposerPromptEditorTiptap.input.test.tsx

Manually recorded on Linux/GNOME Wayland using US-International with dead keys disabled and Right Alt as Compose. The same sequences were typed on baseline cfafb4bb54 and fixed 5b77b5d7c1:

  • Compose → " → o, then Compose → ' → e: stray characters before; clean ö é after.
  • Select word and type ": still produces "word".
  • Select test and type (: still produces (test).

Both composer modes are covered by automated tests; the recordings do not show a mode switch. Native dead-key quote+Space was not manually tested. The tests replay composition replacements, including a final quote arriving after compositionend; they are not a native dead-key event capture. Wrapping with a dead quote key during composition now replaces the selection, as does typing a delimiter over a whole-document selection. Native Electron was not separately exercised.

Before

Before: stray characters after Compose input

https://github.com/user-attachments/assets/9619e630-8705-45a6-ba74-2e28e54c8ba9

After

After: clean Compose input with selection wrapping preserved

https://github.com/user-attachments/assets/244a31e0-a726-4422-ad8d-bfb2858ddcf9


Implemented with GPT-6 in Codex. Reviewed with Claude Opus 5.5 at high effort in Claude Code.

Checks

25 successful · 9 skipped
All checks passed
5b77b5d

Added 1 commit

  • fix(web): preserve Compose and dead-key input5b77b5d
Synced from GitHub

Approvability

Verdict: Approved at 5b77b5d

Macroscope's review found this PR approvable — This is a small, self-contained editor bug fix that preserves normal quote wrapping while preventing composition updates from adding stray surrounding characters. The accompanying tests cover the affected composition and selection cases, with no product-default or static-analysis configuration changes.

You can add or adjust custom eligibility rules. Learn more.

Synced from GitHub

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Path: .coderabbit.config.ts
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: f32741e4-a4db-46ee-b77d-b318b6a4673f
📥 Commits

Reviewing files that changed from the base of the PR and between e58a4857130a93cc58b45dd6ebee14cf08df04ec and 5b77b5d7c14b667e567d61710c093e0c4f1abb03.

📒 Files selected for processing: 2
  • apps/web/src/components/ComposerPromptEditorTiptap.input.test.tsx
  • apps/web/src/components/ComposerPromptEditorTiptap.tsx

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 9 remain after this review.

📝 Walkthrough

The composer now skips quote wrapping during composition. It wraps selected text only when the editor selection matches the text input replacement range. New tests cover composition and text replacement in both rich-text modes.

Changes: Composer text input

Layer / File(s)Summary
Selection-aware quote wrapping
apps/web/src/components/ComposerPromptEditorTiptap.tsx, apps/web/src/components/ComposerPromptEditorTiptap.input.test.tsx
The input handler skips wrapping during composition and wraps text only when the non-empty editor selection matches the replacement range. Tests cover composed characters, replacement over and outside a selection, and quote wrapping in both rich-text modes.

Priority: ➖ Normal

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix · Severity of issue fixed: Medium

Suggested reviewers: stienswout

Merge Risk: ⚪ Minimal · up to 5b77b

The composer no longer inserts stray quotes during composition, and wrapping of explicitly selected text is preserved. No merge-blocking risk was found.

Pre-merge checks: Passed 4
Check nameStatusExplanation
Title checkPassedThe title clearly and concisely describes the main fix: stray quotes caused by Compose input in the web composer.
Description checkPassedThe description includes all required sections. It explains the problem, implementation, scope approval, focused verification, limitations, screenshots, and the tools used.
Linked Issues checkPassedThe change addresses active issue #16859. handleTextInput now skips delimiter wrapping while view.composing is true and requires a nonempty TextSelection that exactly matches the replacement ran…
Out of Scope Changes checkPassedThe pull request changes only the shared composer input handler and adds focused regression tests for composition and selection wrapping. These changes directly support #16859. No unrelated product be…
Full details: Linked Issues check

Explanation

The change addresses active issue #16859. handleTextInput now skips delimiter wrapping while view.composing is true and requires a nonempty TextSelection that exactly matches the replacement range. This prevents provisional dead-key or Compose text from being wrapped. The shared handler covers the web and desktop composer. Tests cover plain and rich text composition, composed quotes, composition over selected text, and explicit quote wrapping. Closed issue #12644 supplies historical context only.

Full details: Out of Scope Changes check

Explanation

The pull request changes only the shared composer input handler and adds focused regression tests for composition and selection wrapping. These changes directly support #16859. No unrelated product behavior or files are included.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • 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.