Displaying buttons when hovering over a node

I’m a Tiptap user but I think the solution here lies in ProseMirror (though please redirect me if wrong).

I’d like to create a Notion style interface for inserting new nodes and possibly modifying existing nodes (maybe later dragging nodes).

So this will involve two buttons appearing in the left gutter next to the node being hovered.

The extent of what I need to do now is detect the cursor position, find the closest node being hovered, and unhide and absolutely position the buttons adjacent to the beginning of that node.

The behaviour of the buttons etc. is not currently a concern, it’s just this first step I could use a few pointers with.

Many thanks

I think I’ve got this.

This is just a proof of concept right now which I’ll post here in case others stumble across it in the future:

import { Extension } from '@tiptap/core'
import { Plugin, PluginKey } from '@tiptap/pm/state'

export interface NodeToolsOptions {}

export const NodeTools = Extension.create<NodeToolsOptions>({
	name: 'nodeTools',

	addOptions() {
		return {}
	},

	addProseMirrorPlugins() {
		const editor = this.editor
		const { options, view } = editor

		const element = options.element
		const dom = view.dom

		const tools = document.createElement('div')
		tools.classList.add('editor-node-tools')
		tools.innerText = 'TOOLS'
		tools.style.display = 'none'

		return [
			new Plugin({
				key: new PluginKey(this.name),
				props: {
					handleDOMEvents: {
						mouseover: (view, event) =>
						{
							const target = event.target as HTMLElement

							if (target === dom)
							{
								return
							}

							const targetDims = target.getBoundingClientRect()
							const offsetY = targetDims.top - (targetDims.height / 2)

							tools.style.top = `${offsetY}px`
							tools.style.display = ''

							element.appendChild(tools)
						}
					}
				}
			}),
		]
	},
})

Obviously got some refinement to do but crucially this is a good basis for what I need to do next.

You can use decorations instead, which could show extra widget in your node.