Sample built from public fixes

Sample report: two IME defects in open-source UI components

This is not a client report. I built it from two fixes of mine that were merged into rsuite and tdesign-vue-next, so every claim below can be checked against the merged pull request. A paid report has the same sections, with your app's inputs in place of these components.

これは顧客向けの報告書ではありません。rsuiteとtdesign-vue-nextにマージされた自分の修正2件から作ったサンプルです。実際の報告書も同じ構成で、対象がお客様のアプリの入力欄になります。

Summary

IDInputKeyWhat goes wrongSeverity
F1rsuite InputPicker, single selectEnterConfirming a conversion selects the highlighted option and closes the menu.High
F2tdesign-vue-next Drawer with closeOnEscKeydownEscCancelling a candidate closes the drawer the user is typing in.Medium

Severity: High means a wrong value is saved or sent without the user noticing. Medium means the user loses their place or has to redo work, but no wrong data is stored.

F1. InputPicker selects an option on the Enter that confirms a conversion

Where

src/InputPicker/InputPicker.tsx, handleMenuItemKeyPress. The tag-input handler a few lines above (handleTagKeyPress) already ignores Enter during composition; the single-select handler did not.

What happens

The user filters the list in Japanese. The Enter meant to confirm the kanji also fires onChange with whichever option is focused, and the menu closes. The value saved is an option the user never chose.

Steps to reproduce

  1. Render a single-select InputPicker and open it.
  2. Turn on a Japanese IME and type in the search box to filter the list. An option becomes focused.
  3. Press Enter to confirm the conversion.

Expected: the text is confirmed and the picker stays open. Actual: onChange fires, the focused option is selected, and the menu closes.

Cause

The handler reacts to every Enter keydown and never reads isComposing. During composition the browser still reports the key as Enter.

Patch

   const handleMenuItemKeyPress = useEventCallback((event: React.KeyboardEvent) => {
+    // When composing, ignore the keypress event.
+    if (event.nativeEvent.isComposing) {
+      return;
+    }
+     if (!focusItemValue || !controlledData) {
       return;
     }

Full diff: rsuite/rsuite #4585, files changed. The guard reads nativeEvent because React's synthetic keyboard event has no isComposing.

Regression test

it('Should not call `onChange` when Enter is pressed during IME composition', () => {
  const onChange = vi.fn();
  render(<InputPicker defaultOpen data={data} onChange={onChange} defaultValue={'Kariane'} />);

  fireEvent.keyDown(screen.getByRole('textbox'), { key: 'Enter', isComposing: true });

  expect(onChange).not.toHaveBeenCalled();
});

Without the guard the test fails (onChange is called once); with it, the full InputPicker suite passes.

Status

Merged upstream on 2 July 2026.

F2. Esc that cancels a candidate also closes the drawer

Where

packages/components/drawer/drawer.tsx, handleEscKeydown. The same project had fixed this for Dialog in #6740; Drawer was missing the guard.

What happens

With closeOnEscKeydown on, the user is typing Japanese in a field inside the drawer and presses Esc to back out of a conversion. The drawer closes. With destroyOnClose, whatever they typed in the drawer is gone.

Steps to reproduce

  1. Open a t-drawer with closeOnEscKeydown and a text input inside.
  2. Turn on a Japanese IME, type in the input, and convert so a candidate is showing.
  3. Press Esc to cancel the candidate.

Expected: only the candidate is cancelled. Actual: the drawer closes.

Cause

The drawer listens for keydown on the window and checks only e.key === 'Escape'. An Escape pressed during composition belongs to the IME.

Patch

     const handleEscKeydown = (e: KeyboardEvent) => {
+      if (e.key === 'Escape' && e.isComposing) return;       if (
         (props.closeOnEscKeydown ?? globalConfig.value.closeOnEscKeydown) &&
         e.key === 'Escape' &&

Full diff: Tencent/tdesign-vue-next #6756, files changed. The merged line carries a one-line comment in Chinese, omitted here.

Regression test

it('should not close on ESC during IME composition', async () => {
  const onClose = vi.fn();
  const wrapper = mount(Drawer, {
    attachTo: document.body,
    props: { visible: true, body: '内容', closeOnEscKeydown: true, onClose },
  });
  vi.runAllTimers();
  await nextTick();
  window.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape', isComposing: true }));
  await nextTick();
  expect(onClose).not.toHaveBeenCalled();
  // A normal ESC still closes the drawer.
  window.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape' }));
  await nextTick();
  expect(onClose).toHaveBeenCalledTimes(1);
  expect(onClose.mock.calls[0][0].trigger).toBe('esc');
  wrapper.unmount();
});

The test checks both sides: Escape during composition leaves the drawer open, and a normal Escape still closes it.

Status

Merged upstream on 30 June 2026.

Inputs that passed

A paid report also lists every input that passed, with the browsers and key sequences tried, so you know what was covered. This sample has none, because it covers only the two components above.