slate icon indicating copy to clipboard operation
slate copied to clipboard

Safari: selection becomes null when editor blurs

Open Harsh1796 opened this issue 4 years ago • 10 comments

In Safari the editor selection becomes null when the editor is blurred. However in Chrome & Firefox, the selection is preserved when the editor blurs.

Chrome

https://user-images.githubusercontent.com/25709855/125637734-aa1621da-41dc-4020-820b-4f1eaf30ac64.mp4

Firefox

https://user-images.githubusercontent.com/25709855/125637787-15b43f99-af22-4fa5-b54e-ecef64af6f00.mp4

Safari

https://user-images.githubusercontent.com/25709855/125637827-b2c47db7-9338-4076-b825-8f3c2b02f62c.mp4

Sandbox

Steps

  1. Go to Sandbox
  2. Select some text from the editor.
  3. Click the button Bold. To make the text bold.
  4. Works in Chrome & Firefox. Fails in Safari.

Expectation

Expected behavior is get similar output for editor.selection across browsers when the editor blurs. In this case the selection is preserved for Chrome & Firefox but becomes null in Safari.

Environment

  • Slate Version: [0.63.0]
  • Slate React Version: [0.65.2]
  • Operating System: [macOS]
  • Browser: [Chrome, Safari,Firefox]

Cause of this issue can be #4324, where to fix a backward typing bug in Safari. Safari specific code was added to make sure the selection becomes null when editor is blurred.

Harsh1796 avatar Jul 14 '21 14:07 Harsh1796

I think this has caused an issue with our BalloonToolbar plugin. It is designed to stay open as long as the editor has selection but a bug was reported after we upgraded where it closes in Safari when the editor blurs.

@clauderic do you think we could come up with another solution for #4324? Happy to help if we can.

hwildwood avatar Jul 26 '21 08:07 hwildwood

@clauderic I can confirm that undoing the change in #4324 does fix this issue. ~~Strangely I also can't replicate the backwards typing bug, where there particular circumstances in which you got it or was it consistent?~~ I get around the backwards typing bug by calling ReactEditor.focus(editor) in my toggleMark function:

export function toggleMark(editor: Editor, format: INLINE_TYPE): void {
  const isActive = isMarkActive(editor, format);
  if (isActive) {
    Editor.removeMark(editor, format);
  } else {
    Editor.addMark(editor, format, true);
  }
  ReactEditor.focus(editor);
}

jamestowers avatar Jul 26 '21 16:07 jamestowers

The backward typing bug can be reproduced consistently in Safari if you programatically blur the editor. Try adding a toolbar button that blurs the editor when clicked to the RichText example https://github.com/ianstormtaylor/slate/blob/main/site/examples/richtext.tsx:

    <Slate editor={editor} value={value} onChange={value => setValue(value)}>
      <Toolbar>
        <MarkButton format="bold" icon="format_bold" />
        // ...
+      <button onClick={() => ReactEditor.blur(editor)}>Blur</button>
      </Toolbar>

https://user-images.githubusercontent.com/1416436/121074881-75ce0f00-c7a2-11eb-94e7-9f3fb3356943.mp4

clauderic avatar Jul 26 '21 16:07 clauderic

As far as toolbar buttons go, the approach I would recommend is to prevent the default browser behaviour (blurring the contenteditable element) on pointer down:

function ToolbarButton() {
  return <button onPointerDown={preventDefault} />
}

function preventDefault(event) {
  event.preventDefault();
}

clauderic avatar Jul 26 '21 16:07 clauderic

Thanks @clauderic, unfortunately the preventDefault() trick doesn't quite work as expected in Safari and often returns focus to the wrong place, see gif below, whereas ReactEditor.focus(editor) acts as you'd expect.

Screen Capture 2021-07-26 at 19 19 34

jamestowers avatar Jul 26 '21 18:07 jamestowers

@jamestowers I am also using React.focusEditor to get around the backward typings bug in Safari. But I have to use an older version of slate-react v0.65.0 to get similar behaviour in all browsers.

Harsh1796 avatar Jul 27 '21 05:07 Harsh1796

@Harsh1796 is the older version to prevent the null selection issue you first posted above, or are there other issues too?

I may be missing something but I feel the downsides of the changes in #4324 are bigger than the those of adding ReactEditor.focus(editor) as #4324 is wiping out a whole browser

jamestowers avatar Jul 27 '21 06:07 jamestowers

Does anyone know the root cause of #4324? I expect it's a safari quirk? I'd be keen to work on an alternative solution if we had an idea of where to look.

jamestowers avatar Jul 27 '21 06:07 jamestowers

@jamestowers I am using an older version to prevent the null selection issue and maintain a similar behaviour in all browsers for my use case.

Harsh1796 avatar Jul 27 '21 06:07 Harsh1796

Running into the same issue today, I have menu components that live outside of the Slate editor, I want to bring back the focus to the editor after the user clicks something in the menus, in Chrome caret position is restored properly but not in Safari. Has anybody found a workaround for this?

wfortin avatar Jan 17 '23 17:01 wfortin