Skip to content

Fixed IME composition Enter key in the Title and Description blocks b… - #8383

Open
terapyon wants to merge 3 commits into
plone:mainfrom
plonejp:fix/8348-ime-enter-title-block
Open

Fixed IME composition Enter key in the Title and Description blocks b…#8383
terapyon wants to merge 3 commits into
plone:mainfrom
plonejp:fix/8348-ime-enter-title-block

Conversation

@terapyon

@terapyon terapyon commented Jul 15, 2026

Copy link
Copy Markdown
Member

Fixed IME composition Enter key in the Title and Description blocks and in TextLineEdit being misinterpreted as a move to the next block, which broke Japanese/Chinese/Korean input (e.g. confirming a conversion in Safari). @terapyon


If your pull request closes an open issue, include the exact text below, immediately followed by the issue number. When your pull request gets merged, then that issue will close automatically.

Closes #


If your pull request includes changes to the documentation—either in narrative documentation, Storybook, or configuration—then a pull request preview will be generated and a link will populate in the description of your pull request below.
By clicking that link, you can use the visual diff menu in the upper right corner to navigate to pages that have changes, then display the diff by checking the Show diff checkbox.

…eing misinterpreted as a move to the next block, which broke Japanese/Chinese/Korean input (e.g. confirming a conversion in Safari). @terapyon
@terapyon

Copy link
Copy Markdown
Member Author

I will check on my env, I didn't check it yet.

@terapyon

terapyon commented Jul 15, 2026

Copy link
Copy Markdown
Member Author

Local testing

Automated tests (all passing locally, vitest via pnpm):

  • Unit tests for the shared guardisIMEComposing() in
    helpers/Utils/Utils.test.jsx (4 new cases): nativeEvent.isComposing,
    the Safari keyCode === 229 fallback, a regular Enter (keyCode 13,
    not composing), and being called with a native event directly.

  • Regression/wiring testBlocks/Title/Edit.ime.test.jsx (4 cases)
    exercises the real handleKeyDown of the Title block:

    • plain Enter → onAddBlock(defaultBlockType, index + 1) +
      onSelectBlock, and the event is preventDefault-ed;
    • Enter with isComposing: true → ignored and not
      preventDefault-ed (left to the IME);
    • Enter with keyCode: 229 (Safari path) → ignored;
    • ArrowDown while composing → focus does not move.

    Only <Editable /> is mocked (slate-react's contenteditable machinery
    does not work in jsdom); everything else, including the component's
    handler, is real. The Title block is tested as the representative of the
    shared pattern — the same guard in Description, TextLineEdit and
    SlateEditor differs only by the one guard line, so the wiring test is
    deliberately not duplicated per component.

  • Full related suites pass: the volto project tests for
    Title/Description/TextLineEdit/Utils (58 tests) and the whole
    volto-slate project (24 tests). Prettier/ESLint clean.

Manual verification on macOS with a Japanese IME (Safari and Chrome):

  • Title/Description: Enter confirming a conversion stays in the field;
    a second Enter (IME inactive) moves on as before
  • Regular text block: typing, conversion, arrow-key candidate
    navigation, / slash menu, hotkeys (Cmd+B/I) unaffected

Note: no automated tool can drive a real OS-level IME, so the composition
keydown properties are synthesized in tests; final confirmation has to be
manual.

Side findings while fixing this (beyond the reported repro)

  1. Root cause context: slate-react invokes the consumer's onKeyDown
    before its own composition guard
    (isEventHandled(event, attributes.onKeyDown) || ReactEditor.isComposing(editor)),
    so every consumer keydown handler must guard itself. Slate's own
    Enter → insertBreak path is beforeinput-driven and already IME-safe
    on browsers with beforeinput support.
  2. TextLineEdit contained an identical copy of the Title handler with
    the same bug — fixed with the same guard (used by heading-like blocks in
    add-ons).
  3. volto-slate SlateEditor: the Editable onKeyDown wrapper
    dispatched hotkeys and the pluggable keyboard handlers without any
    composition guard. Real failure paths existed: splitAtSeam (a plain
    Enter at a backspace-merge seam splits into a new Volto block — matches
    "moves to the next line" reports), slashMenu (confirming a conversion
    after typing / could insert a menu item), goUp/goDown (arrow-key
    candidate navigation could jump blocks), joinWithPreviousBlock
    (Backspace at block start while composing could join blocks). The guard
    was added at that single choke point so hotkeys, textblock handlers,
    detached handlers and add-on-provided handlers are all covered at once.
    A separate volto-slate news fragment was added for this.
  4. Test-infrastructure finding: test-setup-globals.js sets
    global.__SERVER__ = false; under jsdom this makes window.__SERVER__
    defined, so components guarded by
    typeof window.__SERVER__ !== 'undefined' silently render <div /> in
    vitest while their mount effects still run against an empty Slate
    editor and crash. This is why slate-based Edit components were
    previously hard to test with testing-library; the new test deletes the
    global in beforeAll. Might be worth a follow-up cleanup of the test
    setup.
  5. Out of scope / follow-up candidates: the Search block's
    SearchInput uses onKeyPress — Safari also fires keypress for the
    composition-confirming Enter, so a search can trigger prematurely; it
    needs a different fix (switch to keydown + the guard). Similar
    lower-impact patterns exist in the Maps/Video URL inputs, AddLinkForm
    and ObjectBrowserWidget's manual-link input.

@terapyon
terapyon marked this pull request as ready for review August 12, 2026 11:37
@terapyon
terapyon requested a review from sneridagh August 12, 2026 11:37
@terapyon

Copy link
Copy Markdown
Member Author

@sneridagh I made the PR, this is IME problem. I checked local env, it fine. Please review and merge.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant