fix(react-ui): don't submit on Enter while an IME composition is open - #1068
Open
iambharathpadhu wants to merge 1 commit into
Open
fix(react-ui): don't submit on Enter while an IME composition is open#1068iambharathpadhu wants to merge 1 commit into
iambharathpadhu wants to merge 1 commit into
Conversation
Both built-in composers submitted on any Enter keydown, with no awareness of IME composition state. Windows Voice Typing holds a composition session open across dictation, so a physical Enter sent and cleared the draft, the composition then finalized and fired one more onChange, and the dictated text reappeared in the textarea the user had just emptied. Every CJK IME hits the same path and sends a half-converted phrase instead of committing it. Extract the decision into a pure shouldSubmitOnEnter() helper that bails while a composition is open — checking nativeEvent.isComposing plus the keyCode 229 sentinel that Safari and older Chromium report before isComposing is set — and route both composers through it so the condition has a single source of truth. The Enter that closes a composition no longer sends; the next one does. That is standard IME behavior and is what removes the race. Fixes thesysdev#1045 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
@iambharathpadhu is attempting to deploy a commit to the thesys-devs Team on Vercel. A member of the Team first needs to authorize it. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Fixes #1045.
Both built-in composers in
@openuidev/react-uisubmit on anyEnterkeydown, with no awareness of IME composition state — there is currently no composition guard anywhere in the package (grep -rn "isComposing" packages/react-ui/srcreturns nothing).Windows Voice Typing holds an IME composition session open across dictation. A physical
Entertherefore submits and clears the textarea, the still-open composition finalizes a moment later and fires one moreonChange, and the dictated text reappears in the box the user just emptied. That is the race in the issue.The blast radius is wider than the report suggests: every IME-based input hits the same path. For Japanese, Chinese and Korean input,
Enteris the key that confirms a conversion candidate — today that keypress sends a half-converted phrase instead of committing it.The issue reporter worked around this in their own app via
AgentInterface.Composer's Mode C, patching one composer. This fixes it in the library, for both.Changes
shouldSubmitOnEnter()inAgentInterface/_shared/utils/composerKeyboard.ts— a pure predicate that returnsfalsewhile a composition is open.nativeEvent.isComposing, plus thekeyCode === 229sentinel, since Safari and older Chromium dispatch the composition-consumedkeydownbeforeisComposingis set.ComposerKeyDownEventthat React'sKeyboardEvent<HTMLTextAreaElement>satisfies, so call sites pass the synthetic event straight through and tests build a plain object — no casts, no DOM.AgentInterface/components/Composer.tsxAgentInterface/components/DesktopWelcomeComposer.tsx__tests__/composerKeyboard.test.tscovering plainEnter,Shift+Enter, non-Enterkeys,isComposing, the229sentinel, and theEnterthat follows a finished composition.Behavior change
While a composition is open,
Enterno longer sends — it closes the composition, and the nextEntersends. This is standard IME behavior, matches whatassistant-ui's own composer does, and is precisely what removes the race. Non-IME typing is unaffected:Entersends,Shift+Enterinserts a newline, exactly as before.On the approach
I went with a shared pure helper rather than a
compositionstart/compositionendref inside each component for two reasons: it keeps the two composers from drifting apart again, and it stays testable under the package's existing setup.react-uihas no jsdom today — every test here is SSR or pure — so a component-level interaction test would mean adding a DOM environment, a larger diff than the fix itself. Happy to inline the guard in both components instead if you'd prefer that.Test Plan
lint:check— 0 errors (27 pre-existingreact-hooks/exhaustive-depswarnings ingenui-lib/hooks, none from these files)format:check— cleantest— 40 passed across 8 files (6 new)pnpm --filter @openuidev/react-ui typecheckreports 73 errors, but the count is byte-identical on a clean checkout ofmain— all ingenui-lib, none inAgentInterface. It is also not part of the package'sciscript, so I left it alone rather than widening this PR.Checklist
AgentInterface