Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cards overlapping when I drag react-beautiful-dnd #2558

Open
RMahammad opened this issue Dec 14, 2023 · 3 comments
Open

Cards overlapping when I drag react-beautiful-dnd #2558

RMahammad opened this issue Dec 14, 2023 · 3 comments

Comments

@RMahammad
Copy link

RMahammad commented Dec 14, 2023

I have create simple task management system with react, react-beautiful-dnd and material ui. But when I want to drag my task card, before and after my selected element just overlapping each other.

<DragDropContext
              onDragEnd={(result) =>
                onDragEnd(
                  result,
                  cloneList,
                  setCloneList,
                  handleDragBoardData,
                  handleMoveList
                )
              }
            >
              <Droppable
                droppableId="board"
                type="COLUMN"
                direction="horizontal"
                mode="virtual"
                ignoreContainerClipping={true}
                isCombineEnabled={true}
              >
                {(provided) => (
                  <div
                    ref={provided.innerRef}
                    {...provided.droppableProps}
                    style={{
                      display: "inline-flex",
                      overflow: "scroll",
                      gap: 10,
                      maxWidth: "100%",
                    }}
                  >
                    {cloneList.map((column, index) => (
                      <Draggable
                        key={column._id}
                        draggableId={column._id}
                        index={index}
                      >
                        {(provided, snapshot) => (
                          <div
                            ref={provided.innerRef}
                            {...provided.draggableProps}
                            {...provided.dragHandleProps}
                          >
                            <Lane
                              key={column._id}
                              column={column}
                              handleAddList={handleCreateListCard}
                              handleEditList={handleEditList}
                              handleDeleteList={handleDeleteList}
                            >
                              <Droppable
                                direction="vertical"
                                droppableId={column._id}
                                key={column._id}
                                mode="virtual"
                                renderClone={(provided, snapshot, rubric) => (
                                  <div
                                    ref={provided.innerRef}
                                    {...provided.draggableProps}
                                    {...provided.dragHandleProps}
                                  >
                                    <Task
                                      item={column.cards[rubric.source.index]}
                                      setTaskDetails={setTaskDetails}
                                      setOpenEditTask={setOpenEditTask}
                                    />
                                  </div>
                                )}
                              >
                                {(provided) => {
                                  return (
                                    <div
                                      {...provided.droppableProps}
                                      ref={provided.innerRef}
                                      style={{
                                        minHeight: 50,
                                      }}
                                    >
                                      {column.cards.map((item, index) => {
                                        return (
                                          <Draggable
                                            key={item.id}
                                            draggableId={item.id}
                                            index={index}
                                          >
                                            {(provided) => {
                                              return (
                                                <div
                                                  ref={provided.innerRef}
                                                  {...provided.draggableProps}
                                                  {...provided.dragHandleProps}
                                                  // style={{}}
                                                >
                                                  <Task
                                                    item={item}
                                                    setTaskDetails={
                                                      setTaskDetails
                                                    }
                                                    setOpenEditTask={
                                                      setOpenEditTask
                                                    }
                                                  />
                                                  {provided.placeholder}
                                                </div>
                                              );
                                            }}
                                          </Draggable>
                                        );
                                      })}
                                    </div>
                                  );
                                }}
                              </Droppable>
                              {provided.placeholder}
                            </Lane>
                          </div>
                        )}
                      </Draggable>
                    ))}
                    {provided.placeholder}
                  </div>
                )}
              </Droppable>
            </DragDropContext>
Screen.Recording.2023-12-13.at.10.25.26.AM.mov

Main problem is cards are overlapping, also when I want to drag lists they also overlapping also. How can I fix this problem ?

@Baal-Marduk
Copy link

Hey have you found any solution to this issue ? I'm encountering same behaviour even though I used the {provided.placeholder} element which I thought would prevent it.

@RMahammad
Copy link
Author

Hey have you found any solution to this issue ? I'm encountering same behaviour even though I used the {provided.placeholder} element which I thought would prevent it.

I am using provided placeholders also but they are not working at all. I didn't find any normal solution to prevent it

@joeryoost
Copy link

joeryoost commented Jan 25, 2024

It looks like your droppable is set to mode="virtual". The documentation states that you need to provide your own placeholder.

For my use-case, with items that have a variable size, I managed to achieve this by keeping track of the index of the element that was dragged:

const draggedIndex = useRef<number | null>(null);

const handleDragStart: OnDragStartResponder = ({ draggableId, source }) => {
  ...
  draggedIndex.current = source.index
};

And then grabbing a reference to the HTML element currently being dragged from the renderClone method:

renderClone={(provided) => {
  ...
   return (
     <div
       {...provided.draggableProps}
       {...provided.dragHandleProps}
       style={{ ...provided.draggableProps.style, ...style, ...indentationStyle }}
       ref={(el) => {
         provided.innerRef(el);
         draggedElementRef.current = el;
       }}
     >
       ...
     </div>
   );
 }}

And finally inserting a placeholder when rendering the draggable nodes, that has the same height as the element we're dragging:

{items.reduce((acc, { index, measureRef }) => {
  if (draggedIndex.current === index) {
    // We need to manually add a spacer for the dragged element to prevent items in the list from overlapping
    acc.push(<div style={{ height: draggedElementRef.current?.offsetHeight ?? 100 }} />);
  }
  acc.push(renderNode(index));

  return acc;
}, [] as Array<JSX.Element>)}

Hope this helps!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants