Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Selection reverts when button click in void element causes input to appear #5791

Open
12joan opened this issue Jan 12, 2025 · 1 comment · May be fixed by #5795
Open

Selection reverts when button click in void element causes input to appear #5791

12joan opened this issue Jan 12, 2025 · 1 comment · May be fixed by #5795

Comments

@12joan
Copy link
Contributor

12joan commented Jan 12, 2025

Description
Due to a regression introduced in Chrome 127, clicking a button inside a void element that causes an input element to appear causes the selection to incorrectly revert to its previous location.

Recording

recording.mp4

Sandbox
https://codesandbox.io/p/sandbox/p553rr

Steps
To reproduce the behavior:

  1. Open the sandbox in Chrome 127 or newer
  2. Click anywhere in block 1 to select it (indicated by grey background)
  3. Click the button in block 2 (which is a void block element)
  4. The selection incorrectly reverts to block 1

Expectation
Ordinarily, clicking a button inside a void element causes that void element to be selected. When clicking the button in block 2, block 2 should be selected, which is what happens in other browsers.

Environment

  • Slate Version: all versions
  • Operating System: tested in macOS, Windows and Android
  • Browser: Chrome 127+

Context
I've reported this bug to the Chromium issue tracker: https://issues.chromium.org/issues/389368412

The behaviour in Chrome 127 that causes this bug is that appending to the DOM an input element with a non-empty value causes a selectionchange event to be sent. However, the selection according to document.getSelection() remains the same as it was before the click. This confuses slate-react's selection change and click handling logic and causes the selection to revert incorrectly.

@12joan
Copy link
Contributor Author

12joan commented Jan 13, 2025

Documenting this here in case anyone else needs to work around the bug before it's fixed in a stable release of Chrome.

Here's the specific sequence of events that causes the bug to occur:

  1. The user clicks a button inside a void element that causes an input to appear
  2. The click handler in editable.tsx calls Transforms.select to select the void element, setting editor.selection to the void element but leaving the DOM selection unchanged for now. (At this point, the DOM selection is still pointing to the previous editor.selection.)
  3. Expected behaviour:
    1. The useIsomorphicLayoutEffect in editable.tsx runs and the DOM selection is updated to match editor.selection
  4. Actual behaviour in Chrome 127+:
    1. Chrome fires the selectionchange event
    2. The onDOMSelectionChange handler in editable.tsx updates editor.selection to match the DOM selection, inadvertently reverting editor.selection to its previous location
    3. Since editor.selection now matches the DOM selection, nothing else happens and the selection remains at its location prior to the click

Thus, the simplest workaround is to add a click handler to the button that manually sets the DOM selection (not the Slate selection) to the correct void element.

const handleClick = () => {
  const path = ReactEditor.findPath(editor, element);
  const range = Editor.range(editor, path);
  const domRange = ReactEditor.toDOMRange(editor, range);
  document.getSelection().setBaseAndExtent(
    domRange.endContainer,
    domRange.endOffset,
    domRange.startContainer,
    domRange.startOffset
  );
};

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

Successfully merging a pull request may close this issue.

1 participant