Find out what's new in Tiptap Editor 3.0

Drag Context Menu

Available in Start plan

A fully accessible drag context menu for Tiptap editors. Provides a drag handle with an extensive context menu for block-level operations including transforming nodes, styling content, copying, duplicating, and deleting blocks.

Installation

Add the component via the Tiptap CLI:

npx @tiptap/cli@latest add drag-context-menu

Components

<DragContextMenu />

A prebuilt React component that renders a drag handle with a comprehensive context menu for block operations.

Usage

import { EditorContent, EditorContext, useEditor } from '@tiptap/react'
import { StarterKit } from '@tiptap/starter-kit'
import { DragContextMenu } from '@/components/tiptap-ui/drag-context-menu'

import '@/components/tiptap-node/paragraph-node/paragraph-node.scss'

export default function MyEditor() {
  const editor = useEditor({
    immediatelyRender: false,
    extensions: [StarterKit],
    content: `
        <h1>Drag Context Menu Demo</h1>
        <p>Hover over any block to see the drag handle appear on the left side.</p>
        <blockquote>
            <p>Click the drag handle to access the context menu with various options.</p>
        </blockquote>
        `,
  })

  return (
    <EditorContext.Provider value={{ editor }}>
      <EditorContent editor={editor} role="presentation" />
      <DragContextMenu editor={editor} withSlashCommandTrigger={true} />
    </EditorContext.Provider>
  )
}

Props

NameTypeDefaultDescription
editorEditor | nullundefinedThe Tiptap editor instance
withSlashCommandTriggerbooleantrueShows a slash command trigger button alongside the drag handle

The component also accepts all props from DragHandleProps (excluding editor and children).

Hooks

useMenuActionVisibility()

A custom hook that determines which action groups should be visible in the context menu based on the current editor state and selected node.

Usage

function MyCustomDragMenu() {
  const { hasAnyActionGroups, hasColorActions, hasTransformActions, hasResetFormatting, hasImage } =
    useMenuActionVisibility(editor)

  return (
    <div>
      {hasColorActions && <ColorActions />}
      {hasTransformActions && <TransformActions />}
      {hasResetFormatting && <ResetFormattingAction />}
      {hasImage && <ImageActions />}
    </div>
  )
}

Props

NameTypeDefaultDescription
editorEditor | nullundefinedThe Tiptap editor instance

Return Values

NameTypeDescription
hasAnyActionGroupsbooleanWhether any action groups should be rendered
hasColorActionsbooleanWhether color and highlight actions are available
hasTransformActionsbooleanWhether node transformation actions are available
hasResetFormattingbooleanWhether reset formatting action is available
hasImagebooleanWhether image-specific actions are available

Context Menu Features

The drag context menu provides several action groups:

Color Actions

  • Text Color: Change text color with recent color history
  • Highlight Color: Apply background highlights with color options

Transform Actions

Transform the current block into different node types:

  • Text: Convert to paragraph
  • Heading 1, 2, 3: Convert to different heading levels
  • Bullet List: Convert to unordered list
  • Numbered List: Convert to ordered list
  • Task List: Convert to task/checkbox list
  • Blockquote: Convert to blockquote
  • Code Block: Convert to code block

Core Actions

  • Ask AI: Trigger AI assistance for the selected content
  • Copy: Copy the block content to clipboard
  • Duplicate: Create a duplicate of the current block

Reset Formatting

  • Reset All Formatting: Remove all formatting marks from the content

Image Actions (for image nodes)

  • Download: Download the image file

Delete Actions

  • Delete: Remove the current block

Utilities

getNodeDisplayName(editor)

Gets a user-friendly display name for the currently selected node.

import { getNodeDisplayName } from '@/lib/tiptap-collab-utils'

const displayName = getNodeDisplayName(editor) // Returns "text", "Heading 1", "Blockquote", etc.

isTextSelectionValid(editor)

Checks if the current selection is a valid text selection.

import { isTextSelectionValid } from '@/lib/tiptap-collab-utils'

const isValidSelection = isTextSelectionValid(editor)

Behavior

Drag Handle Positioning

  • The drag handle appears on hover over block elements
  • Automatically positions itself relative to the block height
  • For blocks taller than 40px, aligns to the top
  • For smaller blocks, centers vertically

Mobile Behavior

  • Automatically hides on mobile devices to prevent interface conflicts
  • Touch interactions are optimized for mobile editing

AI Integration

  • Hides when AI generation is active to prevent interface conflicts
  • Provides AI ask functionality through the context menu

Requirements

Dependencies

  • @tiptap/react - Core Tiptap React integration
  • @tiptap/extension-drag-handle-react - Drag handle functionality
  • @floating-ui/react - Positioning utilities
  • react-hotkeys-hook - Keyboard shortcut management

Referenced Components

  • use-tiptap-editor (hook)
  • use-mobile (hook)
  • use-ui-editor-state (hook)
  • button, button-group (primitives)
  • menu, menu-content, menu-item (primitives)
  • separator, spacer (primitives)
  • combobox (primitive)

Referenced UI Components

  • image-download-button
  • duplicate-button
  • copy-to-clipboard-button
  • delete-node-button
  • reset-all-formatting-button
  • slash-command-trigger-button
  • color-text-button
  • color-highlight-button
  • ai-ask-button
  • text-button
  • heading-button
  • list-button
  • blockquote-button
  • code-block-button

Icons

  • grip-vertical-icon - Main drag handle icon
  • paint-bucket-icon - Color actions
  • chevron-right-icon - Submenu indicators
  • repeat-2-icon - Reset formatting
  • text-color-small-icon - Text color