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

Unexpected Backspace/Delete behaviour in lists #370

Closed
theefer opened this issue Jun 3, 2016 · 7 comments
Closed

Unexpected Backspace/Delete behaviour in lists #370

theefer opened this issue Jun 3, 2016 · 7 comments

Comments

@theefer
Copy link
Contributor

theefer commented Jun 3, 2016

The behaviour of Backspace and Delete in lists feels buggy.

In particular:

  • Backspace at the beginning of a paragraph following a list turns the paragraph into a new list item (expected: join the text of the paragraph into the last list item)
  • Given a list of 3 items, Delete at the second list item turns the third list item into a second paragraph in the second list item (expected: join the text of the third item into the second one)
  • Delete at the end of the last item in a list turns the following paragraph into a new list item (expected: join the text of the paragraph into the last list item)

I've isolated the behaviours in a set of tests, but I haven't been able to come up with a fix yet. Any pointers welcome!

It looks like it's an issue in either joinForward, or deleteBarrier.

@marijnh
Copy link
Member

marijnh commented Jun 3, 2016

These are intentional behavior. You sometimes have to press backspace/delete a few more times than in other editors to get to the state you're looking for, but you'll get there, and the intermediate states give you more control.

@marijnh marijnh closed this as completed Jun 3, 2016
@theefer
Copy link
Contributor Author

theefer commented Jun 4, 2016

OK, I will look into whether it's possible to use the different extension points exposed by the ProseMirror API to get the desired behaviour. As long as it can be fixed in userspace, we'd be happy 😄

You sometimes have to press backspace/delete a few more times than in other editors to get to the state you're looking for, but you'll get there, and the intermediate states give you more control.

There are cases where no combination of backspace/delete/enter will get you to the desired state. For example:

  1. Load https://prosemirror.net/
  2. Place the selection caret before the "ProseMirror" word on the last line of the RTE.
  3. Press Backspace (places that line in the list above in a new item).

From that state, it's actually very hard to "lift" that line back into a paragraph with backspace/delete/enter. Would it be easier for users if the first Backspace would have the same behaviour as now (turns the list item for that line into a para in the previous list item), but the second Backspace would lift the paragraph out of the list, and the third Backspace would join the paragraph back into the previous list item (same end result as now)?

Thanks for your reply.

@marijnh
Copy link
Member

marijnh commented Jun 6, 2016

At some point, pressing enter at the start of a textblock always lifted it, but I ended up changing that after several people complained (#88), so now you indeed have this issue.

Your solution seems problematic as well, though -- if I understand correctly you want to have (in your example of proposed behavior) the second backspace go back to the initial state (the paragraph below the list is a regular paragraph). That means that from two identical situations (first backspace, third backspace) the backspace key would have different effects. This doesn't seem like a very nice solution.

We have backspace/delete at the start/end of a textblock mean 'move this closer to the next textblock in that direction', which seems a nice, linearly progressive concept. But your point about not being able to escape the list with basic key bindings is valid. I might be open to reopening the discussion on enter in #88, though people's opinions seem strong on that as well. Will think about this some more (further suggestions welcome).

@theefer
Copy link
Contributor Author

theefer commented Jun 21, 2016

So I've played with this some more with the latest version and currently the two key failing tests that best exists my ideal outcome are:

// 1
test("joinBackward",
     doc(ul(li(p("hi"))), p("<a>there")),
     doc(ul(li(p("hithere")))))
// 2
test("joinBackward",
     doc(ul(li(p("hi"), p("<a>there")))),
     doc(ul(li(p("hi"))), p("there")))

As far as I could trace, these fail because of the result of joinable in deleteBarrier.

I think that the mental model behind the behaviour above, rather than the current one, is that Backspace always moves you "to the left", lifting you out of the current node if necessary (2), or joining you to the previous node if there is no parent to lift out of (1). This makes it more natural to escape the list, and I think it could still work with the existing behaviour (3) below.

// 3 (as per now)
test("joinBackward",
     doc(ul(li(p("hi")), li(p("<a>there")))),
     doc(ul(li(p("hi"), p("there")))))

Let me know what you think.

@Narretz
Copy link

Narretz commented May 29, 2018

Hi @theefer, did you perchance implement the behavior to join with the last list item on backspace? I know it's been a while, but before I try it myself I wanted to see if somebody else did it before.

@bdbch
Copy link

bdbch commented Aug 5, 2023

Hey! I'm chiming in on this one. I tried to implement the behavior @theefer described on our editor framework which felt quite hacky so I thought I'd lift that up to Prosemirror and join the discussion over here. (In general I'd love to get more involved with the sauce and support Prosemirror more in terms of PR, Issues, manpower, looking forward for that).

Basically lots of users of our editor kind of expect the behaviour of other editor apps (I think Notion is the most asked for) and I also checked other editors and how their implementation of backspace / delete in nested elements work (this is not limited to simple ordered / unordered lists, but also to task lists, etc.)

https://lexical.dev/ for example has a similar backspacing and delete behaviour as asked by @theefer which feels very natural. In fact I've never seen any other editor implementation which handles those cases as Prosemirror does.

I totally understand if this is a final decision and we stick to it – but if it's possible I'd really ask to think about it again. Fixing this downstream felt really hacky and I'd rather have a natural experience in the core product (Prosemirror) before somehow hacking in keymap overwrites on our end to somehow get this behaviour done.

Any thoughts @marijnh? Could I somehow support if there is something to do that would block this or do you think this is a final decision for those delete/backspace implementations?

@marijnh
Copy link
Member

marijnh commented Aug 7, 2023

Fixing this downstream felt really hacky

What about binding keys to custom commands felt hacky?

Building a consistent set of editing commands that allow people to create all necessary types of document structure is a subtle thing, and I A) am not going to overhaul the existing commands, since that would be a breaking change, and B) don't currently have time to try to design an alternative system that conforms to what you are asking for here.

The 'bullet list limbo' in the original issue seems to refer to someone not grasping the concept of continued list items (and thus is more about the prosemirror-schema-list package than the default bindings). Again, feel free to provide a simpler editing model by, for example, disallowing continued list items and using commands like joinTextblockBackward. The library is set up in a modular way exactly to make that possible, since requirements are obviously going to be different between different setups.

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

No branches or pull requests

4 participants