Skip to content

Block Handle

Block handle components enable users to interact with, reorder, and insert blocks in your editor through drag-and-drop operations.

'use client'

import 'prosekit/basic/style.css'
import 'prosekit/basic/typography.css'

import { createEditor, type NodeJSON } from 'prosekit/core'
import { ProseKit } from 'prosekit/react'
import { useMemo } from 'react'

import { sampleContent } from '../../sample/sample-doc-block-handle'
import { BlockHandle } from '../../ui/block-handle'
import { DropIndicator } from '../../ui/drop-indicator'

import { defineExtension } from './extension'

interface EditorProps {
  initialContent?: NodeJSON
}

export default function Editor(props: EditorProps) {
  const defaultContent = props.initialContent ?? sampleContent
  const editor = useMemo(() => {
    const extension = defineExtension()
    return createEditor({ extension, defaultContent })
  }, [defaultContent])

  return (
    <ProseKit editor={editor}>
      <div className="box-border h-full w-full min-h-36 overflow-y-hidden overflow-x-hidden rounded-md border border-solid border-gray-200 dark:border-gray-700 shadow-sm flex flex-col bg-white dark:bg-gray-950 text-black dark:text-white">
        <div className="relative w-full flex-1 box-border overflow-y-auto">
          <div ref={editor.mount} className="ProseMirror box-border min-h-full px-[max(4rem,calc(50%-20rem))] py-8 outline-hidden outline-0 [&_span[data-mention=user]]:text-blue-500 [&_span[data-mention=tag]]:text-violet-500"></div>
          <BlockHandle />
          <DropIndicator />
        </div>
      </div>
    </ProseKit>
  )
}

The block handle system provides two main capabilities:

  • Block manipulation: Add new blocks or drag existing blocks to reorder content
  • Visual feedback: Show users exactly where content will be placed during drag operations

The BlockHandle consists of five main components:

  • BlockHandleRoot: Tracks the active block and coordinates block-handle state
  • BlockHandlePositioner: Positions the floating handle on the left side of the active block
  • BlockHandlePopup: The visible floating container for block-handle controls
  • BlockHandleAdd: An add button (+) that inserts a new block below the current one
  • BlockHandleDraggable: A drag handle (⋮⋮) that allows users to reorder blocks by dragging

Use BlockHandleAdd, BlockHandleDraggable, or both inside BlockHandlePopup depending on your needs.

The DropIndicator provides visual feedback during drag-and-drop operations by showing a horizontal line where the dragged content will be inserted. It automatically appears when dragging and disappears when the drag operation completes.

Copy and paste the component source files linked above into your project.