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-169Done

3.2.5 Per-column lazy load-more + virtualization (finding #57) — consume cursor/count

Estimate: 20m · Depends on: 3.2.3, 3.2.2, 3.1.6

Make each column bounded at the UI, honouring the 3.1 paged projection (finding #57): the board never renders every card. 3.1 already returns, per column, a bounded first page + a total count + a cursor; this subtask consumes that.

Load-more. A column showing fewer than its total renders the "Load more" affordance from design/boards/ (button and/or scroll-to-load via an IntersectionObserver sentinel); triggering it calls GET /api/projects/[key]/board/columns/[columnId]/cards?cursor=&limit= (Story 3.1.6) and appends the returned page to that column's card list in the board state (the per-column-mutable shape from 3.2.2), advancing the cursor. Done/terminal columns are already windowed server-side — the UI just shows their count + load-more like any column.

Virtualization. A tall column virtualizes its card stack so the DOM row count stays bounded regardless of how many cards are loaded — reusing the windowing primitive Story 2.5.15 establishes for the issue tree (do NOT add a second virtualization library). The virtualized list must coexist with the 3.2.4 dnd-kit sortable (keep the dragged item + its neighbours mounted; this is a known dnd-kit + virtualization integration — follow the documented pattern).

Out of scope here: the move behaviour itself (3.2.4); swimlanes (3.3). This subtask is the count display, the load-more paging, and the windowing.

Acceptance criteria

  • Each column shows its total count and, when more cards exist, a "Load more" affordance (button and/or scroll-sentinel) that fetches GET …/columns/[id]/cards?cursor= and appends the page, advancing the cursor — never a full-board refetch, never a load-all.
  • A tall column virtualizes (the rendered DOM row count stays bounded as more pages load), reusing the 2.5.15 windowing primitive (no second virtualization dep).
  • Virtualization coexists with drag-drop (a card can be dragged within/out of a virtualized column without detaching mid-drag).
  • Against pnpm db:seed:large, a hundreds-of-cards column loads bounded pages and the DOM stays bounded (the finding-#57 proof).
  • Vitest covers the page-append logic (cursor advance, no duplicate cards, count vs loaded reconciliation).

Context refs

  • Story 3.1.4 / 3.1.6 — the per-column cursor/total + loadColumnCards / GET …/columns/[id]/cards this consumes
  • Story 2.5.15 — the virtualization/windowing primitive to reuse; design/work-items/tree-scale.mock.html — the load-more affordance language
  • design/boards/board.mock.html + design-notes.md (3.2.1) — the column count + load-more design; finding #57 — bounded, no load-all
  • dnd-kit + virtualization integration notes; motir-core/CLAUDE.md — token rules