diff --git a/demos/src/GuideNodeViews/DragHandle/React/Component.jsx b/demos/src/GuideNodeViews/DragHandle/React/Component.jsx
new file mode 100644
index 000000000..0789010b5
--- /dev/null
+++ b/demos/src/GuideNodeViews/DragHandle/React/Component.jsx
@@ -0,0 +1,11 @@
+import { NodeViewContent, NodeViewWrapper } from '@tiptap/react'
+import React from 'react'
+
+export default () => {
+ return (
+
+
+
+
+ )
+}
diff --git a/demos/src/GuideNodeViews/DragHandle/React/DraggableItem.js b/demos/src/GuideNodeViews/DragHandle/React/DraggableItem.js
new file mode 100644
index 000000000..f964519d2
--- /dev/null
+++ b/demos/src/GuideNodeViews/DragHandle/React/DraggableItem.js
@@ -0,0 +1,30 @@
+import { mergeAttributes, Node } from '@tiptap/core'
+import { ReactNodeViewRenderer } from '@tiptap/react'
+
+import Component from './Component.jsx'
+
+export default Node.create({
+ name: 'draggableItem',
+
+ group: 'block',
+
+ content: 'block+',
+
+ draggable: true,
+
+ parseHTML() {
+ return [
+ {
+ tag: 'div[data-type="draggable-item"]',
+ },
+ ]
+ },
+
+ renderHTML({ HTMLAttributes }) {
+ return ['div', mergeAttributes(HTMLAttributes, { 'data-type': 'draggable-item' }), 0]
+ },
+
+ addNodeView() {
+ return ReactNodeViewRenderer(Component)
+ },
+})
diff --git a/demos/src/GuideNodeViews/DragHandle/React/index.html b/demos/src/GuideNodeViews/DragHandle/React/index.html
new file mode 100644
index 000000000..e69de29bb
diff --git a/demos/src/GuideNodeViews/DragHandle/React/index.jsx b/demos/src/GuideNodeViews/DragHandle/React/index.jsx
new file mode 100644
index 000000000..e581ac65d
--- /dev/null
+++ b/demos/src/GuideNodeViews/DragHandle/React/index.jsx
@@ -0,0 +1,33 @@
+import './styles.scss'
+
+import { EditorProvider } from '@tiptap/react'
+import StarterKit from '@tiptap/starter-kit'
+import React from 'react'
+
+import DraggableItem from './DraggableItem.js'
+
+const extensions = [
+ StarterKit,
+ DraggableItem,
+]
+
+const content = `
+
This is a boring paragraph.
+
+
Followed by a fancy draggable item.
+
+
+
And another draggable item.
+
+
And a nested one.
+
+
But can we go deeper?
+
+
+
+ Let’s finish with a boring paragraph.
+ `
+
+export default () => {
+ return
+}
diff --git a/demos/src/GuideNodeViews/DragHandle/React/styles.scss b/demos/src/GuideNodeViews/DragHandle/React/styles.scss
new file mode 100644
index 000000000..dd2ebd606
--- /dev/null
+++ b/demos/src/GuideNodeViews/DragHandle/React/styles.scss
@@ -0,0 +1,124 @@
+/* Basic editor styles */
+.tiptap {
+ :first-child {
+ margin-top: 0;
+ }
+
+ /* List styles */
+ ul,
+ ol {
+ padding: 0 1rem;
+ margin: 1.25rem 1rem 1.25rem 0.4rem;
+
+ li p {
+ margin-top: 0.25em;
+ margin-bottom: 0.25em;
+ }
+ }
+
+ /* Heading styles */
+ h1,
+ h2,
+ h3,
+ h4,
+ h5,
+ h6 {
+ line-height: 1.1;
+ margin-top: 2.5rem;
+ text-wrap: pretty;
+ }
+
+ h1,
+ h2 {
+ margin-top: 3.5rem;
+ margin-bottom: 1.5rem;
+ }
+
+ h1 {
+ font-size: 1.4rem;
+ }
+
+ h2 {
+ font-size: 1.2rem;
+ }
+
+ h3 {
+ font-size: 1.1rem;
+ }
+
+ h4,
+ h5,
+ h6 {
+ font-size: 1rem;
+ }
+
+ /* Code and preformatted text styles */
+ code {
+ background-color: var(--purple-light);
+ border-radius: 0.4rem;
+ color: var(--black);
+ font-size: 0.85rem;
+ padding: 0.25em 0.3em;
+ }
+
+ pre {
+ background: var(--black);
+ border-radius: 0.5rem;
+ color: var(--white);
+ font-family: "JetBrainsMono", monospace;
+ margin: 1.5rem 0;
+ padding: 0.75rem 1rem;
+
+ code {
+ background: none;
+ color: inherit;
+ font-size: 0.8rem;
+ padding: 0;
+ }
+ }
+
+ blockquote {
+ border-left: 3px solid var(--gray-3);
+ margin: 1.5rem 0;
+ padding-left: 1rem;
+ }
+
+ hr {
+ border: none;
+ border-top: 1px solid var(--gray-2);
+ margin: 2rem 0;
+ }
+
+ // Focus styles
+ .has-focus {
+ border-radius: 3px;
+ box-shadow: 0 0 0 2px var(--purple);
+ }
+}
+
+.draggable-item {
+ display: flex;
+ padding: 0.5rem;
+ margin: 0.5rem 0;
+ border-radius: 0.5rem;
+ background: white;
+ box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.05), 0px 10px 20px rgba(0, 0, 0, 0.1);
+
+ .drag-handle {
+ flex: 0 0 auto;
+ position: relative;
+ width: 1rem;
+ height: 1rem;
+ top: 0.3rem;
+ margin-right: 0.5rem;
+ cursor: grab;
+ background-image: url('data:image/svg+xml;charset=UTF-8,');
+ background-repeat: no-repeat;
+ background-size: contain;
+ background-position: center;
+ }
+
+ .content {
+ flex: 1 1 auto;
+ }
+}