I am trying to create an app similar to beatiful-dnd where if we move a card to a new position, other cards make space for it either by moving upwards or downwards. What I tried doing was display a list of cards and rearrange their orders when a drag event takes place. Now while this works I also want to add some animation whie the cards move to the top or bottom. For that I have an array where i store the top positions of each card wrt the container. Now as the cards get rearranged, a new top value is assigned to each component and an animation (top ease 0.5s) is applied. Now the problem is that every time I move a card upwards, the cards above dont wait for the animation to get applied to it whereas every time I move a card downwards, everything works as desired. Can you guys help me with this. Also, I am new here so please be kind 🙂
Attaching some relevant code:
const index = cards.findIndex((card) => card.id === id);
const handleDragOver = (e: DragEvent) => {
e.preventDefault();
if (draggedElementId) {
const rearrangeCards = [...cards];
const indexToRemove = rearrangeCards.findIndex(
(card) => card.id === draggedElementId
);
const elementToRemove = rearrangeCards[indexToRemove];
const indexToAdd = rearrangeCards.findIndex((card) => card.id === id);
rearrangeCards.splice(indexToRemove, 1);
rearrangeCards.splice(indexToAdd, 0, elementToRemove);
setCards(rearrangeCards);
}
};
useEffect(() => {
cardRef.current?.addEventListener("dragover", (e) => handleDragOver(e));
}, [draggedElementId, cards]);
useEffect(() => {
const positions = [...topPositions.current];
const indexToAdd = cards.findIndex((card) => card.id === id);
if (cardRef.current && containerRef.current)
positions.splice(
indexToAdd,
0,
cardRef.current?.getBoundingClientRect().top -
containerRef.current?.getBoundingClientRect().top
);
topPositions.current = positions;
}, []);
return (
<div
draggable
ref={cardRef}
className={`card${dragging ? " dragging" : ""}`}
onDragStart={handleDragStart}
onDragEnd={handleDragEnd}
style={{
position: draggedElementId ? "absolute" : "static",
top: `${topPositions.current[index]}px`,
transition: "top ease 0.5s",
}}
>
{name}
</div>
);
Can any of you help me with this