Skip to content

moooon

Motir

Vibe your whole project. Bring an idea — Motir's three AI layers plan it, track it, and ship it, end to end. You're looking at Motir, built in Motir.

  • Vibe Project
  • Open Source
  • AI Agent
  • AI Loop
1
requests
0
upvotes
145
planned
1,361
shipped

Motir · Work items

MOTIR-222Done

4.2.4 Drag — reorder (rank) + drag-into-sprint + drag-between-sprints over the virtualized list, reusing the Story-3.2 dnd-kit move contract (optimistic + snap-back)

Estimate: 32m · Depends on: 4.2.1, 4.2.3, 4.2.2

Make the backlog groomable by drag — reorder within a region, drag an issue into a sprint, and drag between sprints / back to the backlog — built on the SAME @dnd-kit move contract the board (Story 3.2) already ships, over the 4.2.3 virtualized list. Drawn per the 4.2.1 drag states. No new drag mechanism (reuse), no new card vocabulary.

Reuse the 3.2 contract. Render the rows inside a @dnd-kit/core DndContext + @dnd-kit/sortable exactly as the board does, reusing the boardMove.ts move-resolution + the drag overlay + the keyboard sensor (drag is keyboard-operable). The 3.2.5 useRowWindow virtualization keeps the dragged node attached when it scrolls out of the window (the same "render the active drag node + its neighbours" guard the board uses).

The three moves → 4.1.4 / 4.2.2 writes:

  • Reorder within a region → 4.1.4 rankIssue(itemId, { beforeId?, afterId? }): compute the new backlog_rank between the drop neighbours (a single-row keyBetween write — never an N-row renumber), handling the append/prepend edges.
  • Drag backlog → sprint (or sprint → sprint) → 4.1.4 assignToSprint (single) with an optional rank placement within the target; the same-project guard backstops the write.
  • Drag sprint → backlog → 4.1.4 moveToBacklog (the issue reappears in backlog_rank order).

Optimistic + snap-back (the 3.2 board contract). Apply the move locally on drop, fire the write, and snap back + surface an error on failure — never leave the UI out of sync with the server. Counts (the sprint issue count, the backlog count header) update with the move.

Scale (finding #57). Drag composes with the virtualized + lazy-loaded list (4.2.3): a drop target may be a not-yet-loaded region (drop at the end of a sprint / backlog resolves to a rank-append, no need to have every row loaded), and the rank write stays O(1). The drag never forces a load-all.

Out of scope here: multi-select drag of N rows + the bulk bar (4.2.5 — single-row drag here); inline create + the menu (4.2.5); the points/velocity numbers (4.3 / 4.6).

Acceptance criteria

  • Rows render inside a @dnd-kit DndContext/SortableContext reusing the Story-3.2 boardMove.ts move-resolution + drag overlay + keyboard sensor; dragging out of the useRowWindow-virtualized list keeps the active node attached.
  • Reorder within a region writes a single backlog_rank via 4.1.4 rankIssue (keyBetween, append/prepend edges handled) — strictly between the drop neighbours, no other row's rank changed; drag backlog→sprint / sprint→sprint calls assignToSprint (same-project guarded); drag sprint→backlog calls moveToBacklog.
  • Moves are optimistic and SNAP BACK with a surfaced error on write failure; the sprint issue count + backlog count header update with the move; drag is keyboard-operable.
  • Drag composes with the virtualized/lazy-loaded list (finding #57): a drop into a not-yet-fully-loaded region resolves correctly (append/edge) and never forces a load-all; rank writes stay O(1).
  • Component tests assert reorder (single-row rank write), drag-into-sprint (assign + counts), drag-to-backlog (move + restore), and snap-back on failure.

Context refs

  • app/(authed)/boards/_components/boardMove.ts + BoardColumn.tsx (DndContext + useRowWindow + the active-node-attached guard) + BoardCard.tsx (Story 3.2.3–3.2.5) — the dnd-kit move contract + virtualized-drag pattern to reuse
  • Story 4.1.4 (rankIssue / assignToSprint / moveToBacklog) — the single-row writes the drops call; 4.2.2 — the bulk path 4.2.5 layers on (single here)
  • design/backlog/backlog.mock.html drag-state panels (4.2.1) — the overlay + drop-highlight spec
  • @dnd-kit/core / @dnd-kit/sortable / @dnd-kit/utilities (already in package.json); finding #57 (drag over a bounded list); motir-core/CLAUDE.md