Skip to content

[popups] Dismiss after dropped IME compositions - #5978

Open
jjenzz wants to merge 2 commits into
mui:masterfrom
jjenzz:codex/popups-dropped-composition-5967
Open

jjenzz wants to merge 2 commits into
mui:masterfrom
jjenzz:codex/popups-dropped-composition-5967

Conversation

@jjenzz

@jjenzz jjenzz commented Oct 12, 2026

Copy link
Copy Markdown
Member

In #5967, Escape stops dismissing a popup after Chromium abandons an IME composition without emitting compositionend. This change restores dismissal after that abandoned composition while continuing to protect Escape used by an active IME.

An Input Method Editor (IME) lets someone enter text such as Japanese or Chinese using a Latin keyboard. A composition is the temporary editing stage before that text is committed—for example, typing a pronunciation and choosing the intended characters. During this stage, Escape can cancel the composition, so it should not also dismiss the popup. MDN's composition event explanation and interactive example shows how this works in the browser.

Closes #5967

Root cause and solution

The dismissal handler records compositionstart and assumes compositionend will clear that state. Removing the composing input or rewriting its contents can omit the end event, leaving the flag set indefinitely. Every later Escape is then treated as composition input.

Active composition is now identified from the keyboard event's isComposing or keyCode === 229 indicators. The start listener and its unbounded flag are removed. The existing self-expiring compositionend suppression window remains, preserving the Safari end-before-key safeguard.

The event describes the current Escape, so an abandoned composition cannot leave stale state behind. Clearing the old flag only when an input disconnects would miss aborts caused by rewriting a connected input. Relying exclusively on native flags would discard the existing Safari timing protection. The selected solution handles both without DOM observers, mutation interception, or consumer coordination.

Validation

  • Native CDP traces in Chromium 153.0.8010.12 on macOS confirm that input removal, input value replacement, and contenteditable replacement omit compositionend. The following Escape reports isComposing=false/keyCode=27; active composition Escape reports isComposing=true.
  • Native Japanese Hiragana testing in Firefox 157 on macOS reproduced the dropped-end bug: removing the composing input omitted compositionend, then Escape reported isComposing=false/keyCode=27. The original implementation kept the dialog open; the fix closed it. Active composition Escape preserved the dialog.
  • Native Japanese Hiragana testing in Safari 26.6.1 on macOS confirmed that Escape preserves the dialog during active composition and dismisses after committing. Rewriting a connected input emitted compositionend, and subsequent ordinary Escape dismissed normally.
  • Shared popup conformance verifies dismissal after a dropped end event and non-dismissal for each native IME guard. Original source fails the new regressions; removing either guard independently fails its corresponding tests.
  • Existing composition timing and close/reopen tests pass. jsdom: 421 passed, 175 skipped. Chromium popup roots: 526 passed, 3 skipped.
  • Full TypeScript, ESLint, stylelint, and Prettier checks passed.

Public APIs and controlled dismissal/cancellation behavior are unchanged. The keyCode === 229 guard follows the existing Base UI input/list handling.

@jjenzz jjenzz added type: bug It doesn't behave as expected. browser: Firefox Affects or fixes behavior in Mozilla Firefox. scope: all components Widespread work has an impact on almost all components. browser: Chrome Affects or fixes behavior in Chrome. labels Oct 12, 2026
@jjenzz jjenzz added component: dialog Changes related to the dialog component. component: alert dialog Changes related to the alert dialog component. component: popover Changes related to the popover component. and removed scope: all components Widespread work has an impact on almost all components. labels Oct 12, 2026
@pkg-pr-new

pkg-pr-new Bot commented Oct 12, 2026

Copy link
Copy Markdown

commit: fb9b814

@jjenzz
jjenzz marked this pull request as ready for review October 12, 2026 12:59
@code-infra-dashboard

code-infra-dashboard Bot commented Oct 12, 2026 •

Copy link
Copy Markdown

Bundle size

Bundle Parsed size Gzip size
@base-ui/react ▼-42B(-0.01%) 🔺+5B(0.00%)

Details of bundle changes

Performance

Total duration: 471.25 ms -66.58 ms(-12.4%) | Renders: 76 (+0) | Paint: 865.29 ms -100.74 ms(-10.4%)

Test Duration Renders
Mixed surface mount (app-like density) 40.60 ms ▼-12.83 ms(-24.0%) 5 (+0)
Scroll Area mount (300 instances) 40.95 ms ▼-12.12 ms(-22.8%) 3 (+0)
Select open (500 options) 27.36 ms ▼-7.60 ms(-21.7%) 14 (+0)
Combobox type — 500 items, all stay mounted (type "Row ") 12.75 ms ▼-4.52 ms(-26.2%) 11 (+0)

11 tests within noise — details


Check out the code infra dashboard for more information about this PR.

@netlify

netlify Bot commented Oct 12, 2026

Copy link
Copy Markdown

✅ Deploy Preview for base-ui ready!

Built without sensitive environment variables

Name Link
🔨 Latest commit fb9b814
🔍 Latest deploy log https://app.netlify.com/projects/base-ui/deploys/6accd9154fdba80d366f9e5e
😎 Deploy Preview https://deploy-preview-5978--base-ui.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

@github-actions github-actions Bot added the PR: out-of-date The pull request has merge conflicts and can't be merged. label Oct 16, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

browser: Chrome Affects or fixes behavior in Chrome. browser: Firefox Affects or fixes behavior in Mozilla Firefox. component: alert dialog Changes related to the alert dialog component. component: dialog Changes related to the dialog component. component: popover Changes related to the popover component. PR: out-of-date The pull request has merge conflicts and can't be merged. type: bug It doesn't behave as expected.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[popups] Escape stops dismissing a popup after a composition is dropped without compositionend

1 participant