Node type chooser node view

I am trying to do something that I believe others here are doing (or trying to do) as well, but that I can’t seem to get to work.

Basically, every time a new empty paragraph is created (empty document, enter at end of block…) instead of adding essentially an empty paragraph I want to offer a choice of nodes to add there. The Medium editor does something like that where at the side of a new empty paragraph it affords the possibility to make it an image or embed. I want something similar, but much more powerful.

I thought my approach was simple: create a choice node type and make it first in the schema, build a NodeView for it that exposes a list of buttons, replace the node with whatever corresponds to the button that gets activated.

However it seems that I have been fighting PM every step of the way and I still have no idea if it will eventually work:

  • Making the underlying node type non-selectable will cause the browser (at least Firefox) to render the node selected as soon as it’s clicked on (though PM correctly does not select into it). The “fix” for this is to actually make is selectable, intercept selectNode, and forcefully focus one of the buttons — but that feels backwards.
  • Since the sole purpose of that node type is to trigger a row of buttons then get replaced, I initially had it have no content. This caused all kinds of problems (though it wasn’t immediately obvious what caused them), including checkJoin erroring because the main node given it by joinable was null.
  • Adding a content to that node type fixed that, but now I’m up against other issues in which my buttons become contenteditable, I’m trying weird workarounds with hidden contentDOM and yet more manual focus management, I’m now getting RangeErrors if I activate the buttons with the keyboard despite stopping propagation…

I’m used to editable content being hell, that’s just how it is, but the above tends to make me believe that I must be going about this wrong. I’m clearly using NodeViews in a way they weren’t expected to be; or in an expected manner but completely the wrong way. So my questions are:

  1. Are there examples out there of people doing this?
  2. Is there a way of achieving this that goes less against the grain of PM’s expectations?


I don’t think it’s a good idea to use a node for that. I’ve implemented something similar in the past by allowing empty paragraphs to be created, and use a decoration to show a choice control when the cursor is inside an empty paragraph.