4.4.5 UI — start-sprint flow: wire the start modal to the backlog Start-sprint entry point; "board opens" navigation
Estimate: 28m · Depends on: 4.4.1, 4.4.2, 4.2.3
The start-sprint UI — the modal design/sprints/sprint-lifecycle.mock.html specifies, WIRED to the Start-sprint entry-point button Story 4.2.3 already mounts in the backlog sprint container (the seam pattern: 4.2 mounts the button, 4.4 wires the flow). Reuses shipped primitives; no new dialog shell.
The StartSprintDialog. A Modal opened from the backlog sprint container's Start-sprint button (enabled only on a planned sprint with ≥1 issue — the 4.2.1 rule): the sprint name (prefilled), a duration segmented control (1 / 2 / 3 / 4 weeks / Custom — Custom reveals explicit startDate/endDate pickers, the rest derive endDate from now), and the goal textarea. Primary Start sprint → POST /api/sprints/[id]/start (4.4.2). On success the sprint is active; "board opens" → navigate to /boards (the scrum board renders the active sprint once Story 4.5 lands; until then Kanban — graceful). Optimistic-friendly; the backlog sprint-container state refreshes (the started sprint shows its active chip).
Error states (from the design). The friendly SprintAlreadyActiveError (409) → an inline modal message ("Project X already has an active sprint — complete it first"); the SprintWindowInvalidError (422) → an inline field error on the date pickers. Text + --el-danger, never colour alone (finding #35).
Wire, don't rebuild (the seam). 4.2.3 ships the Start-sprint button as a seam (a button that invokes an injected handler / opens this dialog — the 3.2 Filter-seam pattern). 4.4.5 supplies the StartSprintDialog + the handler. Do NOT re-draw the sprint container or the button; mount the dialog behind the existing entry point. The dialog is a self-contained component (a planned sprint + its id) so it could also be mounted elsewhere if needed.
Tokens + a11y. Colour via --el-*, shape via element-shape tokens (no Tier-0 --color-* / raw rounded-*); the modal is a labelled dialog with focus trap + escape; the duration control + date pickers are keyboard-operable.
Acceptance criteria
- The backlog sprint container's Start-sprint button (4.2.3 seam) opens the
StartSprintDialog(name + duration deck + derived/custom dates + goal); confirm callsPOST /api/sprints/[id]/startand on success navigates to/boards("board opens"); the started sprint shows its active state in the backlog. - The empty-sprint Start button stays disabled (4.2.1 rule, unchanged); the already-active 409 renders the friendly inline modal message; an invalid window renders an inline date error — text +
--el-danger, not colour alone. - 4.4.5 WIRES the flow into the existing 4.2.3 entry point (does NOT redraw the sprint container/button); the dialog is a self-contained reusable component; matches
design/sprints/sprint-lifecycle.mock.html. - Colours via
--el-*, shape via element tokens, AA-safe; the modal is a labelled focus-trapped dialog; component tests assert the dialog render (duration → dates), the start call, the navigation, and the already-active/invalid-window error states.
Context refs
app/(authed)/backlog/_components/*(Story 4.2.3 — the sprint container + the Start-sprint entry-point seam) — where the dialog mounts; the 3.2 Filter-seam pattern to mirror- Story 4.4.2 (
POST /api/sprints/[id]/start+ the typed errors) — the backend this calls; Story 4.4.1 (design/sprints/sprint-lifecycle.mock.html+ design-notes) — the modal spec components/ui/*(Modal,FormField,Button,Combobox/segmented control, date input) — the primitives to reuse- finding #35 (not colour-alone), #54 (use the palette);
motir-core/CLAUDE.md(--el-*+ element-shape rules, client UI)