tiptap icon indicating copy to clipboard operation
tiptap copied to clipboard

Node view in React isn't draggable

Open tuan3w opened this issue 2 years ago • 6 comments

What’s the bug you are facing?

Can't drag node with custom node view in React.

How can we reproduce the bug on our side?

I made simple code to demonstrate error. You can drag if node view written with vanilla JS but you can't drag node view written with React.

  • Screencast:

https://user-images.githubusercontent.com/2762678/156736536-0f3b5084-6578-4c46-b14a-cfbe6a3168b3.mp4

I checked the document https://tiptap.dev/guide/node-views/react/ but I can't find what's wrong here.

Can you provide a CodeSandbox?

React: https://codesandbox.io/s/tiptap-drag-and-drop-4uv0we?file=/src/App.tsx:494-513

What did you expect to happen?

React node view should be draggable.

Anything to add? (optional)

No response

Did you update your dependencies?

  • [X] Yes, I’ve updated my dependencies to use the latest version of all packages.

Are you sponsoring us?

  • [ ] Yes, I’m a sponsor. 💖

tuan3w avatar Mar 04 '22 09:03 tuan3w

It seems like I have to set draggable="true" beside data-drag-handle="" in the DOM element to make it works. Setting draggable="true" in the ancestor node of the handle also works.

Link: https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/draggable

tuan3w avatar Mar 04 '22 16:03 tuan3w

I also had to add it to the node extension. So in total it was:

  1. add draggable="true" and data-drag-handle="" on the DOM element you want to drag (or its parent)
  2. add draggable=true to your node-extension.js file. Here's my node extension which I use to import vue components:
import {Node, mergeAttributes} from '@tiptap/core'
import {VueNodeViewRenderer} from '@tiptap/vue-3'
import Component from './Component.vue'

export const VueComponent = Node.create({
    name: 'vueComponent',
    group: 'block',
    atom: true,
    draggable: true,
    addAttributes() {
        return {
            src: String
        }
    },
    parseHTML() {
        return [{ tag: 'vue-component' }]
    },
    renderHTML({ HTMLAttributes }) {
        return ['vue-component', mergeAttributes(HTMLAttributes)]
    },
    addNodeView() {
        return VueNodeViewRenderer(Component)
    },
})

Arturexe avatar Jun 06 '22 09:06 Arturexe

This issue is stale because it has been open 45 days with no activity. Remove stale label or comment or this will be closed in 7 days

github-actions[bot] avatar Aug 01 '22 17:08 github-actions[bot]

I have the same problem. I've already set draggable: true in my node and added draggable="true" and data-drag-handle to the parent element of the component but it didn't help. For some reason, removing content: "inline*" from the node solves the problem. Any idea what's happening? I really need to have content in my NodeView.

amirhhashemi avatar Aug 04 '22 05:08 amirhhashemi

@ahhshm do you have an example codesandbox for your issue?

bdbch avatar Sep 14 '22 01:09 bdbch

@bdbch https://codesandbox.io/s/react-typescript-forked-8v0ljl?file=/src/App.tsx

When you remove content: "inline*" in the Figure node (as well as the content hole in <figcaption>) you can drag the image normally.

amirhhashemi avatar Sep 14 '22 07:09 amirhhashemi

I have the same issue with React. All nodes with the content hole in the renderHTML are not draggable. 😟

// Extension

export const MyCustomExtension = Node.create({
  name: "myCustomExtension",
  group: "block",
  content: "inline*",
  draggable: true,

  // ...

  parseHTML() {
    return [{ tag: `div[data-type="${this.name}"]` }];
  },

  renderHTML({ HTMLAttributes }) {
    return ["div", mergeAttributes(HTMLAttributes, { "data-type": this.name }), 0];
  },

  addNodeView() {
    return ReactNodeViewRenderer(MyCustomExtensionComponent);
  },
});
// React component

export const MyCustomExtensionComponent = ({ node }) => (
  <NodeViewWrapper>

    {node.type.spec.draggable ? (
        <div draggable="true" data-drag-handle="">
            <DragIcon />
        </div>
    ) : null}

    <NodeViewContent />

  </NodeViewWrapper>
);

anton-liubushkin avatar Oct 18 '22 11:10 anton-liubushkin

+1, I have the same issue

iamursky avatar Oct 18 '22 11:10 iamursky

@tuan3w If you managed to get it working is it possible to update the issue with an example? I've tried adding the attributes as you suggested, but haven't had much luck.

Thanks!

yarrichar avatar Nov 23 '22 10:11 yarrichar

I'm not sure if this is what you meant, but it put me on the right path for an approach that worked for me: https://codesandbox.io/s/twilight-field-7kkytq?file=/src/styles.css:58-939

The bit I had been missing was:

<NodeViewWrapper class="draggable-item">
      <div
        class="drag-handle"
        contentEditable="false"
        draggable="true"
        data-drag-handle
      />
      <NodeViewContent class="content" />
</NodeViewWrapper>

I.e. the extra div inside the wrapper which acts as the drag handle.

yarrichar avatar Nov 23 '22 10:11 yarrichar

@yarrichar thanks a lot! contentEditable="false" fixed the problem

anton-liubushkin avatar Nov 23 '22 11:11 anton-liubushkin

draggable="true" is the important bit here. Let me know if you think we should improve the documentation on this one!

bdbch avatar Nov 23 '22 22:11 bdbch

contentEditable="false" fixed my problem too but I had to explicitly add contentEditable="true" to NodeViewContent so it can be edited.

    <NodeViewWrapper>
      <figure
        data-drag-handle
        draggable={true}
        contentEditable={false}
      >
        {node.attrs.src && <img src={node.attrs.src as string} alt="Image" />}
        <NodeViewContent contentEditable={true} />
      </figure>
    </NodeViewWrapper>

amirhhashemi avatar Nov 24 '22 07:11 amirhhashemi

@tuan3w I'll close this issue for now as it seems we were able to find out what the issue was (primarily the missing draggable="true" and the contentEditable option not being used correctly).

Feel free to reopen if you still have those issues.

bdbch avatar Nov 24 '22 16:11 bdbch

@yarrichar

I'm not sure if this is what you meant, but it put me on the right path for an approach that worked for me: https://codesandbox.io/s/twilight-field-7kkytq?file=/src/styles.css:58-939

in the above sandbox , if you add multiple p tags and try to drag from top to below it doesnt seem to work . but when you drag from below to top it works . ive added a sandbox for the same below . https://codesandbox.io/s/condescending-mendeleev-4ytzmj?file=/src/Tiptap.jsx

surajmn1 avatar Jul 11 '23 09:07 surajmn1

@surajmn1

I have this same issue.

  1. Create two draggable node views.
  2. Drag 2 -> 1 works fine as long as its dropped in a normal place.
  3. Drag 1 -> 2 does not work unless there are line breaks or other 'empty' nodes below the node view.

In my opinion we should be able to drag from above to below without needing additional content below the bottom node view.

Any thoughts on this issue?

CoreAutomation-JD avatar Jan 12 '24 21:01 CoreAutomation-JD