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

Users cannot break out of inline nodes at the end of an editor due to #4578 #4704

Open
AleksandrHovhannisyan opened this issue Dec 1, 2021 · 7 comments
Labels

Comments

@AleksandrHovhannisyan
Copy link

AleksandrHovhannisyan commented Dec 1, 2021

Description

#4578 changed the behavior for how typing works at the end of inline nodes, allowing users to continue typing while their cursor is on either side of an inline node (e.g., a hyperlink). The PR fixed that problem, but it introduced a related problem: If an inline node is the last child of the editor, users are unable to break out of it with their arrow keys.

(It's worth noting that this change was not documented; as far as I can tell, it was not mentioned in Releases and presumably went in as a patch or minor upgrade—0.67 maybe?).

Current behavior causes problems at the end of the editor

We did some internal testing, and non-technical users who are unfamiliar with this change could not figure out how to break out of inline nodes at the end of the editor. This is actually a fairly common situation—imagine you are authoring content and you want to insert a link. If you do this as you are typing, you won't be able to continue typing at the end of the editor.

Arguably, this creates a more frustrating end-user experience than if users cannot continue typing at the end of an inline node (the original bug). The latter can easily be fixed by backtracking the cursor, inserting text in the middle of the inline, and forward-deleting the unwanted content. It's not ideal, but at least your cursor is not stuck in the inline anymore.

The proposed solution may not be intuitive for all users

There was some discussion about this change in that PR; the recommendation was for Slate developers to alter their implementation to change how the left and right arrow keys behave. Assuming that Slate users do implement this proposed change, it does not fix the underlying UX problem. From an end user's perspective, it is not intuitive to have to press the left/right arrow keys twice to be able to enter and exit inline nodes, as demonstrated in https://www.slatejs.org/examples/inlines. Users expect that pressing the left arrow key moves them one unit to the left, and pressing the right arrow key moves them one unit to the right.

The proposed solution requires a design change

Implementing this new behavior requires providing some sort of visual indication that the cursor is actively focusing an inline node vs. "sitting right next to an inline but technically outside it." Without such a visual indicator, a user may think that this is a bug because the cursor appears to be stuck in a single location and doesn't move. I think Slate should try to maintain good default behaviors that don't require these types of UI decisions.

Recording

demo

Sandbox

https://codesandbox.io/s/slate-reproductions-forked-pc1g9?file=/index.js

Steps to reproduce

  1. Create an editor whose last child is an inline.
  2. Put your cursor at the end of the inline.
  3. Start typing.
  4. Observe that you cannot break out of the inline.

Expectation

The user experience needs to be reconsidered for how typing works at the end of an inline node. What this entails is unclear. In the meantime, pending design feedback on the focus indicator, our team may need to downgrade Slate.

Environment

  • Slate Version: 0.70
  • Operating System: Tested on Windows and Mac
  • Browser: all
@jameshfisher
Copy link
Contributor

(Author of #4578 here)

I agree that this is a problem, because it's one that I have as well!

I would strongly feel that reverting #4578 would be the wrong solution, though, because it's easy to add the "jump out of the inline" feature if you want it, but hard/impossible to remove the "jump out of the inline" feature if you don't want it.

I could contribute a tiny plugin like withInlineEscaper, that basically just re-adds that behavior. @AleksandrHovhannisyan would that be appreciated?

(However, I think the better approach would be to solve the underlying bug: when you click at the end of the paragraph, it should drop the cursor into the end of the empty {text: ''} at the end of the paragraph (which should always exist due to normalization rules). Currently, it instead seems to drop the cursor at the end of the inline element.)

@jameshfisher
Copy link
Contributor

I believe it's a browser bug that causes the bad "click at end of line" behavior. I found a possible fix/workaround: make the text element non-zero-width, e.g. add padding-right: 0.001em to it. The browser (at least, Chrome) then stops ignoring it when deciding where to place the cursor when a click happens. @AleksandrHovhannisyan here's a POC using your example: https://codesandbox.io/s/fix-click-at-end-of-line-by-adding-padding-to-text-bkfw9?file=/components/CustomText.jsx

@jameshfisher
Copy link
Contributor

It's certainly a browser bug, because Firefox has different behavior. Using @AleksandrHovhannisyan's example on Firefox (v85 on Windows), clicking at the end of the paragraph puts the cursor outside the inline, as desired.

(However, this is slightly obscured by the example, where the starting document is technically invalid. It should have { text: '' } as its last child to satisfy normalization rules.)

@jameshfisher
Copy link
Contributor

Apart from clicking at the end of the paragraph, the other thing that users try (@AleksandrHovhannisyan could you confirm?) is to hit the right arrow key. Currently, Slate seems to do nothing here, and I think that's a bug. The current Slate logic is here:

if (Hotkeys.isMoveBackward(nativeEvent)) {
event.preventDefault()
if (selection && Range.isCollapsed(selection)) {
Transforms.move(editor, { reverse: !isRTL })
} else {
Transforms.collapse(editor, { edge: 'start' })
}
return
}
if (Hotkeys.isMoveForward(nativeEvent)) {
event.preventDefault()
if (selection && Range.isCollapsed(selection)) {
Transforms.move(editor, { reverse: isRTL })
} else {
Transforms.collapse(editor, { edge: 'end' })
}
return
}

@AleksandrHovhannisyan
Copy link
Author

(However, I think the better approach would be to solve the underlying bug: when you click at the end of the paragraph, it should drop the cursor into the end of the empty {text: ''} at the end of the paragraph (which should always exist due to normalization rules). Currently, it instead seems to drop the cursor at the end of the inline element.)

Yup, agreed! Reverting your PR would just regress to the other bug, which would just make things worse. The ideal fix would be to keep that change but also improve the click-at-end UX, as you mentioned.

the other thing that users try (@AleksandrHovhannisyan could you confirm?) is to hit the right arrow key.

Yup—we ended up implementing your solution in f1b7d18#diff-98b609559db12cb7cc755fd41741b9c72affed934a10cd75db684d5455f3868cR65 and #4630 for the time being, and it seems to work well. We had to add a focus ring indicator to make the UX clearer, though.

Regarding the padding trick: That's interesting! I was able to confirm it fixes the click-at-end behavior for Chrome, Firefox, and Safari (both on Windows and mac).

jameshfisher added a commit to jameshfisher/slate that referenced this issue Jan 6, 2022
… place

There is a Chromium bug where, if you have an inline at the end of a block,
clicking the end of a block puts the cursor inside the inline
instead of inside the final {text: ''} node.

This commit updates the inlines example to show the problem, and to show
a known workaround for the problem.

See for context: ianstormtaylor#4704
@jameshfisher
Copy link
Contributor

Yup—we ended up implementing your solution in f1b7d18#diff-98b609559db12cb7cc755fd41741b9c72affed934a10cd75db684d5455f3868cR65 and #4630 for the time being, and it seems to work well. We had to add a focus ring indicator to make the UX clearer, though.

Okay, great! Yeah I've also used the focus ring technique.

I've added this padding workaround to the standard Slate example in that PR ^^ I would like to better understand the root cause of the bug, but I think this will have to do for now.

I think the remaining issue is the Slate behavior when hitting the right arrow key.

dylans pushed a commit that referenced this issue Jan 6, 2022
… place (#4772)

There is a Chromium bug where, if you have an inline at the end of a block,
clicking the end of a block puts the cursor inside the inline
instead of inside the final {text: ''} node.

This commit updates the inlines example to show the problem, and to show
a known workaround for the problem.

See for context: #4704
DougReeder pushed a commit to DougReeder/slate that referenced this issue Apr 3, 2022
… place (ianstormtaylor#4772)

There is a Chromium bug where, if you have an inline at the end of a block,
clicking the end of a block puts the cursor inside the inline
instead of inside the final {text: ''} node.

This commit updates the inlines example to show the problem, and to show
a known workaround for the problem.

See for context: ianstormtaylor#4704
@lworkman
Copy link

lworkman commented May 3, 2024

For anyone else running into this, a style rule that only applies the spacing when the last node is empty appears to work. That way you don't get extra spacing between words or letters. Something like:

[data-slate-editor="true"] > *:last-child > *:last-child [data-slate-length='0']

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

No branches or pull requests

3 participants