List editing UX considerations

After playing around with ProseMirror for a few months, I still haven’t gotten used to the the UX for editing lists. I’ve managed to get everything to work the way I want it in my editor, but I thought I’d bring it up in case other people have similar thoughts. And maybe if others (i.e. @marijn) agree, we can change the default ProseMirror UX.

1. Pressing backspace after a list creates a new list item:

In this example, | is the cursor:

<ul>
  <li><p>hello</p></li>
</ul>
<p>|world</p>

When you press backspace, you end up with:

<ul>
  <li><p>hello</p></li>
  <li><p>|world</p></li>
</ul>

I find this confusing. I would prefer the outcome to be:

<ul>
  <li><p>hello|world</p></li>
</ul>

Indeed, this is how Notion and Google Docs work.

2. Deleting an empty list doesn’t give me a top-level paragraph.

In this example, | is the cursor:

<ul>
  <li><p>hello</p></li>
  <li><p>|</p></li>
</ul>

When I press backspace, we end up with:

<ul>
  <li>
    <p>hello</p>
    <p>|</p>
  </li>
</ul>

When I press backspace again, we end up with:

<ul>
  <li>
    <p>hello|</p>
  </li>
</ul>

And then I remember that I need to hit enter twice to get want I want… That is, after pressing delete from the second empty list item, I want to end up here:

<ul>
  <li><p>hello</p></li>
</ul>
<p>|</p>

Indeed, this is how Notion works. Google Docs is slightly different though. The first backspace behavior is the same in Google Docs, but the second time you hit backspace, you’ll end up with a top-level paragraph.

3. Indenting paragraph into list items.

In this example, | is the cursor:

<ul>
  <li><p>hello</p></li>
</ul>
<p>|world</p>

When I press Meta-] (or Tab in some applications), I should be able to indent this paragraph into the list item and end up with:

<ul>
  <li>
    <p>hello</p>
    <p>|world</p>
  </li>
</ul>

Discussion

Obviously, ProseMirror is flexible enough to allow me to make these UX changes to my own editor. However, it did take me a while to become familiar with ProseMirror’s abstractions in order to do this and many editors out there (such as tiptap.dev) use the default functionality.

If any of these UX changes are of interest, I’d be happy to make the appropriate changes to prosemirror-commands and prosemirror-schema-list.

Thanks,

Chet

For the sake of backward compatibility, we’re not going to change the way the existing list commands work. But providing alternatives might be possible.

However, as unintuitive as the current setup may look to you, a lot of thought went into it, and it’s not trivial to create a system where users can continue or exit nested nodes in a consistent way. The idea is for all states (tree shapes) to be reachable through backspace, enter, and text input.

Yeah, I think the current solution elegantly solves for this goal. Mine involves a third means of navigation – tab/untab.