Skip to main content
Build a Kanban / multi-container board with @dnd-kit the standard way (DndContext, SortableContext, useSortable on cards) — but three of its defaults misbehave when you drag cards between columns.
A single sortable list (one SortableContext, no cross-column drops) needs none of this — the defaults work.

The three fixes

1. Register each column body as a droppable. SortableContext only registers cards as drop targets, so a drop on empty column space falls back to the nearest card — the wrong column, and the card snaps back. Give each column its own useDroppable({ id: columnId }). (The HTML id attribute alone doesn’t register a target.) 2. Detect collisions from the cursor, not the overlay. The default closestCorners measures from the overlay’s corners and can pick a card in the neighbouring column near a boundary. Use a pointer-first detector:
3. Derive the column’s isOver from context. useDroppable.isOver is false whenever the cursor is over a card (then over.id is the card’s id), so empty-column highlighting breaks. Compute it from useDndContext:

Wiring it together

Cards use useSortable({ id: task.id }) normally. Persist the move in a backend workflow calling zite.Tasks.update({ id: taskId, record: { status } }).

Gotchas

  • PointerSensor needs activationConstraint: { distance: 5 } or clicks on cards register as drags.
  • Update local state optimistically on drag end, then fire the workflow — don’t block the UI on the round-trip.