Skip to content

Resizable

The resizable component wraps an atomic node (typically an image or embed) with drag handles that update the node's width (and optionally height) attribute as the user drags. Mount it inside a custom node view so the new dimensions persist on the node.

'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-image'

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-[canvas] 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>
        </div>
      </div>
    </ProseKit>
  )
}
ResizableRoot                    # holds the current dimensions and forwards drag events
├── <your content>               # the node view (e.g. an <img>, <iframe>, …)
└── ResizableHandle              # one per resize edge (corners or sides)

Mount one ResizableHandle per edge you want draggable (typically four corners for free resize, or just the right edge for width-only). Persist the dimensions back to the node by writing them to the node's attributes from inside the node view.

  • Custom node views: how to render an atomic node with a framework component so resizing can persist.