atlassian / react-beautiful-dnd

Beautiful and accessible drag and drop for lists with React
https://react-beautiful-dnd.netlify.app
Other
33.08k stars 2.52k forks source link

Prevent Draggable to move outside of Droppable region #2168

Open roguib opened 3 years ago

roguib commented 3 years ago

I'm implementing a chessboard using react-beautiful-dnd. Each cell in the chessboard is a <Droppable />, with its unique droppableId and key, that contains a <Draggable /> with a div and image of the piece, or an empty div if in that cell doesn't contain any piece. The problem I'm experimenting is that, while dragging a piece over another one, the piece that is inside the <Droppable /> is moved far away from its original position when another piece is being dragged on top. I thought this problem was related to several issues like https://github.com/atlassian/react-beautiful-dnd/issues/516, https://github.com/atlassian/react-beautiful-dnd/issues/2069, and others mentioning similar situations. However, I couldn't find a clear solution to this problem. I tried disabling transitions, playing with the animation, and other suggested solutions, but without much success. The last solution tried was using isCombineEnabled but the strange movement keeps happening.

Expected behavior

The piece stays in the same <Droppable />, although another one is being dragged on top of it.

Actual behavior

The piece located in the cell is moved around to leave space for the piece that is being dragged.

Steps to reproduce

Check the simple demo I've prepared for this issue 🚀 You can also find a full video reproducing the issue with a bigger chessboard.

https://user-images.githubusercontent.com/30463479/113552575-9dfc8e80-95f6-11eb-9825-9c2e2b082e9c.mp4

Suggested solution?

One idea could be that, if isCombineEnabled is true, then if there's another draggable inside the droppable region it's not moved at all since we want to combine both items.

What version of React are you using?

"react": "^17.0.2"

What version of react-beautiful-dnd are you running?

"react-beautiful-dnd": "^13.1.0"

What browser are you using?

Chrome 89.0.4389.90 (Build oficial) (64 bits)

Demo

Hope you can ignore poor quality code in the demo. I mean, who cares about code quality on a simple demo, right? 🤣 https://codesandbox.io/s/chessboard-hljpt?file=/index.js

artyomlebed commented 3 years ago

Hi there @roguib . I also meet up this problems when i was try to implement almost the same functional as you want. It is seems like you need the isCombineOnly functionality: #1505 . But there is only one problem: this PR still not merged, so this functional not exist in react-beautiful-dnd from the box. At the github account of GDIBass you can find his forked project with implemented his solution: https://github.com/GDIBass/react-beautiful-dnd/tree/is-combine-only But this the version is outdated and do not contains new features of react-beautiful-dnd lib. In my project i need this functional with new version of react-beautiful-dnd lib. So this variant was not suitable for me. I just combined the new version with the code that adds isCombineOnly functionality. You can find it in my repositories: https://github.com/artyomlebed/react-beautiful-dnd. To start using new functional you need a change version in packages.json: "react-beautiful-dnd": "https://github.com/artyomlebed/react-beautiful-dnd.git", And change yarn install script to: "install": "cd node_modules/react-beautiful-dnd && [ ! -d \"dist\" ] && yarn && yarn prepublishOnly && rm -rf node_modules || echo \"react-beautiful-dnd already built\"", Fine, you done it. Just add prop 'isCombineOnly' to and it should start work as you need.

artyomlebed commented 3 years ago

But on this solution i meet one strange bug. Sometimes swap working normally: Screenshot 2021-04-28 at 16 14 54 but an other times it just even do not hover the droppable item. Screenshot 2021-04-28 at 16 15 07 And why it works not correctly and how to fix it - i dont know... In version of GDIBass it`s not reproduced, so i think, you need to try his version.

roguib commented 3 years ago

Thanks for your reply @artyomlebed. Right now I don't have a lot of time to work on this side project, but I'll try it as soon as possible. Also, before knowing your solution, I thought about switching to react-dnd but I dismissed the idea until I finish other tasks I need to do to the chessboard. I really enjoyed working with this library, so before changing the drag and drop functionality I'll give a try to your proposal. Thanks!

wyhinton commented 2 years ago

Also running into this issue, is there any solution for this that doesn't involve using a custom fork?

100terres commented 1 year ago

If anyone has the time to the investigate and open a pull request, you can to it on this fork https://github.com/hello-pangea/dnd/issues/438#issuecomment-1328090710 of react-beautiful-dnd. PRs are more than welcome on our repo :slightly_smiling_face:

BruceMong commented 1 year ago

You can easily prevent this problem by adding the CSS style: transform: none !important; to all draggables except the one being dragged. It worked fine in my project.

To detect when a drag event occurs, use onBeforeCapture and use result.draggableId to determine the draggable being moved.

Before : https://user-images.githubusercontent.com/58480180/220206774-e3acaa91-94c3-4f46-bd55-651536d6dd0d.mov

After : https://user-images.githubusercontent.com/58480180/220206767-51d3fb83-5b5e-4749-85f6-2929c5ed817c.mov

I hope this will help you.

devodii commented 2 months ago

You can easily prevent this problem by adding the CSS style: transform: none !important; to all draggables except the one being dragged. It worked fine in my project.

To detect when a drag event occurs, use onBeforeCapture and use result.draggableId to determine the draggable being moved.

Before : https://user-images.githubusercontent.com/58480180/220206774-e3acaa91-94c3-4f46-bd55-651536d6dd0d.mov

After : https://user-images.githubusercontent.com/58480180/220206767-51d3fb83-5b5e-4749-85f6-2929c5ed817c.mov

I hope this will help you.

How can we target the divs?