Bug: Pressing backspace (delete) in an empty list item, should remove the list formatting, before removing the entire line
Pressing backspace / delete in an empty list item, currently removes the entire line, instead of first removing the list style. This seems to be unconventional and can break user expectations (compared to Google Docs, Notion, Apple Pages, Tiptap, Prosemirror).
Google Docs, Notion and Apple Pages allow the list indentation to be removed completely. Tiptap and Prosemirror remove the list style but not the indentation.
It seems like the most conventional behavior is the one used by Google Docs, Notion and Apple pages where both the list style and indentation can be removed, before the whole line is deleted.
https://github.com/facebook/lexical/assets/208149/9501c5bd-039b-46f7-bd86-48f4c81e9269
Lexical version: 0.20.0
Steps To Reproduce
- Create a list
- Try to remove the list style by pressing backspace multiple times in one of the list items
Link to code example:
https://playground.lexical.dev/
The current behavior
The whole line gets completely removed
The expected behavior
The list style and indentation should be removed before the line gets removed
Any feedback on this?
Facing the same problem. Is there even a way to catch the keyboard event and handle it myself?
Yes, of course you can catch the keyboard event and handle it yourself, or add a listener for the DELETE_CHARACTER_COMMAND and handle that yourself.
Good idea for the DELETE_CHARACTER_COMMAND
I was able to use DELETE_CHARACTER_COMMAND and do it myself. But it is quite a lot of code. No wonder it's not done by default. Some key points:
Detect if user is pressing backspace/delete at the beginning of a list item is the first thing to do. I was able to use the selection to figure it out. The condition is the selection must have 1 and only 1 node, if the node is a ListItemNode, then it is an empty list item node and it is the case. Otherwise it should be a text node, then the anchor and focus of the selection both need to have offset 0. Go up one level and the parent need to be a list item node, and the text node need to be the first child of the list item node. Also an edge case that the parent is a link node, you need to go up one more level to see if it is list item node. After all these, it is "user pressing backspace/delete at the beginning of a list item" case that we need to handle.
Then the action need to be done is to split the list into 2 lists to host items before and after that list item node. Between the two lists, put a paragraph hosting all items from the deleted list item node. I did all these then found a "replace" function on list item node that does this exactly. I then switched to use that.
One last thing is if the list item node was empty, we need to add a text node to the paragraph and set the selection, or the cursor goes back to the previous line which is super weird
@sunshineo I saw your comment and implemented the ListBreakPlugin—it worked great! Thank you so much! https://gist.github.com/fomachanyade/d28736b2913b5a76b8fefabf4a8d430c