3.3.1 Design — swimlanes layout + group-by control + WIP config + over-limit warning (extends design/boards/)
Estimate: 45m · Depends on: 3.2.1
The design asset every UI subtask of this story builds against. The 3.2.1 board mockup drew a WIP slot only as a NON-enforced placeholder and drew NO swimlanes, NO WIP-config editor, and NO over-limit treatment — under the design gate, unspecified == no design, so this subtask produces it FIRST (mirrors 1.0.5 / 1.2.1 / 1.3.3 / 1.5.1 and the 3.2.1 board design it extends). Output: design/boards/swimlanes-wip.mock.html (an HTML mockup built from the real design system — components/ui/* + the --el-* tokens, so a coding agent has no Pencil→code gap) + a PNG export + an extension of design/boards/design-notes.md (a "Swimlanes + WIP (Story 3.3)" section) naming the composing primitives, copy, and placement. --el-* only (no Tier-0 --color-*); shape via the element shape tokens; AA-safe; Jira/Linear boards as the mirror.
Specify, panel by panel:
- Group-by control — a board-header control (in the slot 3.2.1 reserved for the 3.3 controls) letting the user pick None / Assignee / Epic / Priority. Reuse a shipped select/segmented primitive (do not invent a control); show the active group-by; note it persists to the board (server) so all viewers see it.
- Swimlane row — a horizontal lane spanning all columns: a sticky lane header (group label — assignee name+avatar / epic key+title / priority pill / the catch-all "No <dim>") + an aggregate card count + a collapse/expand chevron (collapsed lanes show just the header + count). Draw the lane grid (column boundaries align across lanes), the catch-all lane sorted last, and the flat (group-by None) board as the baseline. Lane order rule documented (alpha / priority-rank / epic-position; catch-all last).
- Cross-lane drag — the drop treatment when a card is dragged into a DIFFERENT lane (reassign the grouped field): the target-lane highlight + insertion indicator (NOT colour-alone, finding #35), and the diagonal case (different column AND lane). Document the
aria-liveannouncement copy for a reassign vs a transition vs a diagonal move. - WIP-limit config — the editor reached from the column actions
[⋯]menu (reserved in 3.2.1): a small "Set WIP limit" field (integer, clearable). Document the empty/none state (no limit → the count shows plain). - Over-limit warning (SOFT) — the column header + count treatment when cards > limit (e.g.
6/5): a warning hue (--el-warning/--el-dangerfamily) PAIRED with an icon and/or then/limitlabel so it is not colour-alone (finding #35); the at-limit (5/5) and under-limit (3/5) states for contrast. Make explicit in the notes that the warning is advisory and does NOT block drops. - States — switching group-by (the re-lay loading transition), a single-lane board, the catch-all-only board, and the over-limit + collapsed-lane combinations.
Acceptance criteria
design/boards/swimlanes-wip.mock.html+ a PNG export + a "Swimlanes + WIP (Story 3.3)" section indesign/boards/design-notes.mdexist; the mockup is built fromcomponents/ui/*+--el-*/element-shape tokens only (no Tier-0--color-*, no rawrounded-*/p-*for control shape), passes the render checklist (icon viewBox, no nested buttons, prettier), and is AA-safe.- The mockup draws: the group-by control, the swimlane row (header + count + collapse), the catch-all lane (sorted last), the cross-lane drag/diagonal drop treatment (not colour-alone), the column-
[⋯]WIP-config editor, and the under/at/over-limit count states. design-notes.mdnames each composing primitive (the select/segmented control,Pill,IssueTypeIcon, the column[⋯]menu,Tooltip), documents the lane-order rule, the collapse-persistence, thearia-livecopy for reassign/transition/diagonal, and states explicitly that WIP is a SOFT warning (never blocks a drop).- Over-limit + drop affordances do not rely on colour alone (finding #35); hues come from
--el-*.
Context refs
design/boards/board.mock.html+design-notes.md(3.2.1) — the base board this extends (the reserved WIP slot + the column[⋯]+ the 3.3-controls slot in the header)design/work-items/list.mock.html+design-notes.md(2.5) — the card/cell visual language + the assignee/priority/epic primitives reused in lane headerscomponents/ui/*(Select/Segmented, Pill, Tooltip, the menu primitive) +app/(authed)/issues/_components/issueCellPrimitives.tsx+IssueTypeIcon— the primitives to composeapp/globals.css--el-*(incl.--el-warning/--el-danger) + element-shape tokens; the/tokensspecimen route- Jira / Linear swimlanes + column WIP as the mirror; finding #35 (not colour-alone), #54 (use the palette)