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

4.2.3 Backlog page + nav — ranked virtualized/paginated backlog list + sprint-planning containers (read render) + empty/loading/error/scale states + points/velocity seams

Estimate: 34m · Depends on: 4.2.1, 4.1.4

The page scaffold + the read-only render of the backlog surface — the structure subtasks 4.2.4 (drag) and 4.2.5 (multi-select + create) build interaction onto. Drawn per design/backlog/backlog.mock.html; reuses the work-items row + the shipped state primitives + the useRowWindow virtualization (3.2.5). No drag and no selection yet — those are 4.2.4 / 4.2.5.

Route + nav. A new /backlog route under app/(authed)/backlog/ (project-scoped — the active project from the shell context, like /boards). Add a Backlog item to SidebarNav (adjacent to Boards) + an AppCommandPalette ⌘K entry, with a nav.backlog i18n key (and every shipped locale's value). No other nav change. The page-head toolbar carries a View all issues link (mirror rung 1 — Jira "View in Issue Navigator", VERIFIED June 2026): a plain <a> to the project's issue navigator (/issues, the Story-2.5 List/Tree — every issue across the backlog AND all sprints). NOT a flat list rebuilt on this page (Jira links out to the navigator, it does not flatten the grouped planning view) — the navigator already exists, so this is a link, no new view; a backlog.viewAllIssues i18n key (every shipped locale). It sits beside the disabled [Filter] seam (Epic 6) + [+ New issue].

Sprint-planning containers (read render). Bind to 4.1.3 listByProject (the project's sprints) + 4.1.4 getSprintIssues per sprint: render each as a collapsible container with the name + state Pill + date range + issue count, the ranked issue rows, the committed-points SLOT (the Story-4.3 seam — a reserved labelled empty slot, NOT a computed number) + the velocity SLOT (the Story-4.6 seam), and the Start-sprint entry point (the flow is Story 4.4 — render it as the seam 4.4 wires, exactly as 4.5.3 seams Complete-sprint) + a Create-sprint affordance (4.1.3 createSprint). The inline-create row + the menu are placed but wired in 4.2.5.

Backlog list (bound to the BOUNDED read — finding #57). Bind to 4.1.4 getBacklog(projectId, { cursor, limit }): render the bounded count header ("N issues" — from the aggregate count, not a loaded-row tally), the ranked rows in a virtualized list via the shipped useRowWindow hook (3.2.5 — only visible rows in the DOM), and lazy-load the next page on scroll via the cursor (the 3.2.5 load-more machinery). NEVER fetch every row. Each row composes the work-items row vocabulary + the reserved estimate SLOT (the Story-4.3 seam).

States. Empty backlog → EmptyState + create CTA; no sprints → the Create-sprint affordance only; loading → a backlog skeleton (the 3.2.2 scaffold idiom); error → ErrorState + retry. All per the 4.2.1 design.

Tokens + a11y. Colour via --el-* (issue-type hue via the IssueTypeIcon); shape via the element shape tokens (no Tier-0 --color-*, no raw rounded-*/p-* for control shape — CLAUDE.md); the backlog + each sprint container are labelled landmarks; counts read as text (finding #35).

Out of scope here: drag-to-reorder / drag-into-sprint (4.2.4); multi-select + bulk + inline create wiring + the menu actions (4.2.5); the estimate/points/velocity NUMBERS (Stories 4.3 / 4.6 fill the seams); the Start-sprint FLOW (Story 4.4).

Acceptance criteria

  • A new /backlog route renders the sprint-planning containers above the ranked backlog list for the active project; a Backlog SidebarNav item + ⌘K entry (with a nav.backlog i18n key in every shipped locale) lead to it; no other nav change.
  • The page-head toolbar carries a View all issues link (a plain <a>, backlog.viewAllIssues i18n key) deep-linking to the project issue navigator (/issues, Story 2.5) — the Jira "View in Issue Navigator" affordance; NO flat all-issues list is rebuilt on this page.
  • The backlog list binds to 4.1.4 getBacklog (cursor-paginated): a bounded count header, a useRowWindow-virtualized list (only visible rows in the DOM), and lazy-load-on-scroll via the cursor — NEVER a load-all read.
  • Each sprint container renders name + state pill + date range + issue count + the committed-points SLOT + velocity SLOT (reserved empty seams, labelled, not computed) + the Start-sprint entry-point seam + the Create-sprint affordance; the backlog + sprint rows are the SAME work-items-vocabulary row with a RESERVED estimate slot.
  • Empty / no-sprints / loading / error states render per design/backlog/backlog.mock.html; colour via --el-*, shape via element tokens, AA-safe; the backlog + each sprint container are labelled landmarks and counts read as text (finding #35).
  • No drag, no selection, no create wiring yet (4.2.4 / 4.2.5); the estimate/points/velocity slots are empty seams (Stories 4.3 / 4.6).
  • Component tests assert the container/list render, the bounded count header + virtualized window (DOM stays bounded on a large seed), and each state.

Context refs

  • design/backlog/backlog.mock.html + design-notes.md (4.2.1) — the layout + seam spec this matches
  • app/(authed)/boards/page.tsx + app/(authed)/boards/_components/BoardColumn.tsx (useRowWindow) / BoardColumnPager.tsx (3.2.2 / 3.2.5) — the page scaffold + virtualization + load-more idioms to reuse
  • app/(authed)/_components/SidebarNav.tsx + AppCommandPalette.tsx — where the Backlog nav item + ⌘K entry land; the i18n nav.* key pattern
  • app/(authed)/issues/ (Story 2.5 List/Tree — the issue navigator the View all issues toolbar link targets); Jira "View in Issue Navigator" is the mirror — link out, do not rebuild a flat list here
  • Story 4.1.4 (getBacklog / getSprintIssues) + 4.1.3 (listByProject / createSprint) — the reads/CRUD this binds to; components/ui/* (Pill, EmptyState, ErrorState) + the work-items row
  • finding #57 (bounded/virtualized list), #35 (not colour-alone), #54 (palette); motir-core/CLAUDE.md (--el-* + element-shape rules)