measuredco / puck

The visual editor for React
https://puckeditor.com
MIT License
5.26k stars 318 forks source link

Support dragging between DropZone areas #123

Open chrisvxd opened 1 year ago

chrisvxd commented 1 year ago

37 introduced the DropZone component, but it is not possible to drag between DropZone areas (or parents), per the "Rules of DropZones" detailed in the PR:

  1. You can drag from the component list on the LHS into any DropZone
  2. You can drag components between DropZones, so long as those DropZones share a parent (also known as area)
  3. You can't drag between DropZones that don't share a parent (or area)
  4. Your mouse must be directly over a DropZone for a collision to be detected

This restriction was implemented to overcome some of the limitations of react-beautiful-dnd (and drag-and-drop in general). I've been exploring this over the last few days but it is non-trivial. I'm breaking this issue out from #100 to keep things moving forwards, and may pause work on this for the time-being.

Challenges

Issues that I've encountered:

  1. After switching between areas, react-beautiful-dnd incorrectly offsets for the change of height during the dropping animation - Solved by correcting the transform produced by react-beautiful-dnd during the drop animation
  2. Items need dynamically resizing during drag (which technically also affects dragging items between DropZones, not just areas) - Solved by correcting the transform produced by react-beautiful-dnd whilst dragging based on the size of the destination DropZone
  3. After switching between areas and moving above the source area to the parent area, react-beautiful-dnd offsets the dragged item by the relative position of the source Droppable to the parent Droppable - Not solved (see below)

Issues with patching 3

Unfortunately issue 3 is particularly challenging. I explored different approaches to correct this issue:

  1. Modify the transform (again) - however, it is not clear how the offset is even being applied, making it difficult to calculate a valid correction
  2. Reparent the element using the renderClone API - this solves the offset issue completely but breaks dragging of components that contain DropZones (nested Droppables are technically unsupported by react-beautiful-dnd). This API unmounts the Draggable on render, which causes the nested Droppables to unmount and react-beautiful-dnd to freak out.
  3. Reparent the element using portals (instead of renderClone) to avoid unmounting - this introduces further positioning issues, but they may be solvable. Further exploration is required.
  4. Migrating to dnd-kit - this is not a simple swap and introduces regressions that have already been resolved.

Current state

https://github.com/measuredco/puck/assets/985961/bfa13a00-9ce3-4744-b094-a566fee83a53

JakeSidSmith commented 1 year ago

@chrisvxd was/is there any particular reason(s) puck uses (or would use) a library for drag and drop as opposed to the HTML 5 drag and drop API? It's supported by all major browsers excluding mobile ones. Do you aim to support drag and drop on mobile?

JakeSidSmith commented 1 year ago

If you guys would like it, I could build a drag and drop interface that is similar enough to beautiful dnd that it should be easy to swap out, but it'll use portals by default, allow dragging to different depths, handle mobile drag and drop a bit nicer, and you'll have full control over it... Or I could publish it to NPM.

I have plenty of experience with writing drag and drop stuff e.g. https://github.com/jakesidsmith/react-reorder

I've actually been meaning to re-write the API for the above for ages, and already have a decent starting point.

chrisvxd commented 1 year ago

@JakeSidSmith Re your first question - time. We don't have a huge interest in maintaining our own dnd implementation when react-beautiful-dnd and dnd-kit exist. You get a lot of stuff for free with both (especially beautiful-dnd), including great animations, mobile (which we don't really support that right now anyway, but don't want to lock ourselves out of) and great accessibility (which might actually be better with HTML5).

However, I think that most likely the only way to robustly overcome the issues outlined here are with a custom implementation using dnd-kit or HTML5.

We have been considering dnd-kit rather than rolling our own entirely, but you still lose a lot of the free stuff from beautiful-dnd.

And your offer! Very generous and interesting. My concerns would still remain somewhat. I don't want Puck 1) relying on an immature external library or 2) taking on a load of additional maintenance. These risks need to be balanced with the dancing we currently do around react-beautiful-dnd, and feature restrictions.

Would defo be open to chatting about it. Shall we chat more about it via discord?

mgreenw commented 10 months ago

Very excited about this feature now that #211 is merged!

chrisvxd commented 10 months ago

Hey @mgreenw - this has dropped way down our priority list for the time-being. There are still several major UI/UX and technical challenges we'd need to solve.

mgreenw commented 10 months ago

Thanks for the update @chrisvxd! Really appreciate all the awesome work y'all are doing on this tool 👏

axyz commented 8 months ago

Just wondering if it would be easy to enable this feature on the outline, rather than the preview. It could be a good intermediate step towards a more complex solution.

Also in general being able to drag from the component list to the outline directly could be useful in many cases where the DOM structure starts to get more complex.

chrisvxd commented 8 months ago

@axyz outline dnd (#126) is definitely easier and should be implemented regardless of this, yeah! Just haven't gotten around to that yet.

We've actually forked the DND lib to support iframes (#353), so the more complex implementation might start to become more viable now.

ZafarKamal123 commented 6 months ago

Hi @chrisvxd,

Looks like this haven't been fixed yet. I'm going to use puck editor in a project and resolving this issue is crucial for that. Do you have any plans for this particular issue being fixed in the future? If this isn't in your priority list at the moment. Could you give me some pointers and i may try fixing this on a forked version.

chrisvxd commented 6 months ago

@ZafarKamal123 we're currently rebuilding the underlying dnd core as the existing library is just not suitable and hard to maintain. I'm hoping to have something over the next few months, but can't give a time-frame just yet.

This is not trivial and patching it in is probably going to be a bad time. You'd have to fork our fork of the underlying dnd library and solve for some thorny UX challenges. Awesome if you can solve it, but there be dragons 🐉

mgreenw commented 6 months ago

@chrisvxd Sounds like a huge project! 😳 Out of curiosity, does the new Atlassian "Pragmatic Drag and Drop" library meet some of your requirements?

chrisvxd commented 6 months ago

@mgreenw We did explore Pragmatic Drag and Drop. It meets the iframe requirements, but dropped animations, which we feel are a key part of the Puck experience.

xylish7 commented 5 months ago

I want to say you did a great job with this project. Really nice! I'm also thinking using this for some of the products I want to develop and this feature (dragging between drop zones) will make the user experience way better. Hope you can deliver it soon 🤞🏻❤️

prashanthvdckap commented 3 months ago

Hi @chrisvxd Any update on this?

chrisvxd commented 3 months ago

@prashanthvdckap working on it but it's a massive lift that's using up all Puck capacity I have rn. Trying to close it off ASAP.