fix(webchat): skip textarea resize during IME composition to eliminate typing lag

This commit is contained in:
joelnishanth
2026-06-16 13:23:05 -07:00
committed by Vincent Koc
parent 2ee4b523b4
commit 820e10fa49
2 changed files with 31 additions and 1 deletions

View File

@@ -1839,6 +1839,33 @@ describe("chat composer IME composition", () => {
expect(onSend).not.toHaveBeenCalled();
expect(onHistoryKeydown).not.toHaveBeenCalled();
});
it("does not force textarea resize during IME composition", () => {
const container = renderChatView({});
const textarea = requireElement(
container,
".agent-chat__composer-combobox > textarea",
"composer textarea",
) as HTMLTextAreaElement;
// Set a sentinel height to detect unwanted overwrites
textarea.style.height = "42px";
textarea.dispatchEvent(new CompositionEvent("compositionstart", { bubbles: true }));
textarea.value = "shi";
textarea.dispatchEvent(new InputEvent("input", { bubbles: true, isComposing: true }));
textarea.value = "shichang";
textarea.dispatchEvent(new InputEvent("input", { bubbles: true, isComposing: true }));
// Height must stay untouched — no forced reflow during composition
expect(textarea.style.height).toBe("42px");
textarea.value = "市场";
textarea.dispatchEvent(new CompositionEvent("compositionend", { bubbles: true }));
// After composition ends, adjustTextareaHeight runs via syncComposerValue
expect(textarea.style.height).not.toBe("42px");
});
});
describe("chat slash menu accessibility", () => {

View File

@@ -2422,7 +2422,10 @@ export function renderChat(props: ChatProps) {
const handleInput = (e: InputEvent) => {
const target = e.target as HTMLTextAreaElement;
if (vs.composerComposing || e.isComposing) {
adjustTextareaHeight(target);
// Skip adjustTextareaHeight during IME composition — each pinyin
// keystroke fires `input` and the height read/write forces a
// synchronous reflow that blocks the composition thread.
// Resize runs once in handleCompositionEnd → syncComposerValue.
draftMirror.value = target.value;
return;
}