Reputation: 10792
I'm trying to not show the return to origin animation when a droppable is dropped in the dropzone.
I don't want to out right disable the animation. <DragOverlay dropAnimation={null}>
The "return to origin" animation should play when the droppable item is dropped in an invalid location, i.e. outside the droppable zone. A <DragOverlay>
must be used.
I seem to be missing something basic.
Here's a demo of the issue: https://codesandbox.io/p/sandbox/summer-frost-d6m8kd
export default function App() {
const [items] = useState(["1", "2", "3", "4", "5"]);
const [activeId, setActiveId] = useState(null);
return (
<DndContext onDragStart={handleDragStart} onDragEnd={handleDragEnd}>
{items.map((id) => (
<Draggable key={id} id={id}>
<Item value={`Item ${id}`} />
</Draggable>
))}
<DragOverlay>
{activeId && <Item value={`Item ${activeId}`} />}
</DragOverlay>
<Droppable>
<div style={{ border: "solid", padding: "15px" }}>Drop here</div>
</Droppable>
</DndContext>
);
function handleDragStart(event) {
setActiveId(event.active.id);
}
function handleDragEnd() {
setActiveId(null);
}
}
Upvotes: 1
Views: 546
Reputation: 1
You need to add styles to position the drag-overlay component when the 'onDragEnd' event fires.
Update your code to:
export default function App() {
const [items] = useState(["1", "2", "3", "4", "5"]);
const [activeId, setActiveId] = useState(null);
// 1: save position of dropzone
const [dropZoneRect, setDropZoneRect] = useState(undefined);
return (
<DndContext onDragStart={handleDragStart} onDragEnd={handleDragEnd}>
{items.map((id) => (
<Draggable key={id} id={id}>
<Item value={`Item ${id}`} />
</Draggable>
))}
<DragOverlay
dropAnimation={{
keyframes: (resolver) => {
return [
{
transform:
`translate3d(${resolver.transform.initial.x}px,
${resolver.transform.initial.y}px, 0)`,
},
{
// 2: add a conditional positioning.
...(dropZoneRect
? { position: "fixed", top: "0", left: "0" }
: {}),
transform:
dropZoneRect
? `translate3d(${dropZoneRect?.x},
${dropZoneRect?.y}, 0)`
: `translate3d(${resolver.transform.final.x}px,
${resolver.transform.final.y}px, 0)`,
},
];
},
}}
>
{activeId && <Item value={`Item ${activeId}`} />}
</DragOverlay>
<Droppable>
<div style={{ border: "solid", padding: "15px" }}>Drop here</div>
</Droppable>
</DndContext>
);
function handleDragStart(event) {
setActiveId(event.active.id);
}
// 3: Update the handleDragEnd function
const handleDragEnd = (e) => {
if (e.over?.id) {
setDropZoneRect({
top: `${e.over.rect.top}px`,
left: `${e.over.rect.left}px`,
});
}
setActiveId(null);
requestAnimationFrame(() => setDropZoneRect(undefined));
};
}
Trick is to immediately set the style of the drag-overlay element to be positioned over the dropZone and remove the style immediately. DragOverlay docs
Upvotes: 0