3.2.1 Design — Kanban board surface: columns, card anatomy, drag states, scale + states
Estimate: 50m · Depends on: 1.5.1
The design asset the whole story builds against — the board is the most design-heavy surface in the product and no design/boards/ asset exists, so this subtask produces it FIRST (the planning-time design gate; mirrors 1.0.5 / 1.2.1 / 1.3.3 / 1.5.1). Output: design/boards/board.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 + design/boards/design-notes.md naming the composing primitives, copy, and placement. --el-* only (no Tier-0 --color-*); shape via the --radius-*/--spacing-* element tokens; AA-safe; mirrors Jira/Linear as the reference board.
Specify, panel by panel:
- Board layout — the board inside the shell (1.5.1): a horizontally-scrolling row of columns, sticky column headers, the overall page header (board name + a place for the 3.3 controls and the issue filter to live later). Desktop scroll behaviour + a usable mobile layout (single-column scroll or a column pager).
- Column — header with the column name, the card count, and a reserved slot for the 3.3 WIP-limit indicator (drawn as a placeholder, NOT enforced here); the column's scroll area; the empty-column state.
- Card anatomy — the compact issue card REUSING the shipped issue primitives: the
IssueTypeIcon(kind hue via--el-type-*), the issuekey/identifier chip, the title (clamped), the assignee avatar, the priority pill, the story-point/estimate chip, and the blocked/ready indicator (ReadinessBadge). Show the colour from the palette, not grey + one accent (finding #54). Note that clicking a card opens the existingIssueQuickView. - Drag states — the card lift (elevation/shadow via
--shadow-*), theDragOverlayclone, the insertion indicator between cards, the target-column highlight, and the snap-back (illegal move) treatment. Drop targets must NOT be signalled by colour alone (finding #35) — pair colour with an insertion line / border / icon. - Keyboard-DnD affordances — the focus ring on a card, the "picked up / press arrows to move / Space to drop / Esc to cancel" model, and where the
aria-livemove announcement copy reads from (document the strings). - Scale (finding #57) — the per-column count, the "Load more" affordance at the bottom of a column (or scroll-to-load), and a note that tall columns virtualize (invisible to the eye; document it, no distinct visual). Reuse the affordance language the issue tree/list scale design (2.5.10 / 2.5.11) established.
- States — board loading skeleton (columns + card placeholders), empty (project has no issues → create affordance), no-board / error / forbidden, and the unmapped-statuses tray (statuses with no column — a banner/tray listing them with a link to the board/workflow admin; the Jira behaviour).
Acceptance criteria
design/boards/board.mock.html+ a PNG export +design/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 multi-column board (with horizontal scroll + sticky headers + mobile layout), a column header with count + a WIP placeholder slot, the card anatomy reusing the issue primitives, the drag states (overlay, insertion indicator, target highlight, snap-back), and the load-more / virtualization affordance.
- It draws every state: loading skeleton, empty, no-board/error/forbidden, and the unmapped-statuses tray.
design-notes.mdnames each composing primitive (IssueTypeIcon,Pill,ReadinessBadge,IssueQuickView,EmptyState,ErrorState,Spinner), documents the keyboard-DnD model + thearia-liveannouncement copy, states that a board card opensIssueQuickView, and names Jira/Linear as the mirror.- Drop/drag affordances do not rely on colour alone (finding #35); card hues come from
--el-type-*(finding #54).
Context refs
design/shell/desktop.png/mobile-drawer.png(1.5.1) — the shell chrome the board renders insidedesign/work-items/list.mock.html+tree-scale.mock.html+design-notes.md(2.5) — the card/cell visual language + the scale (load-more/virtualization) affordance to mirrordesign/work-items/quick-view.mock.html— theIssueQuickViewa card click openscomponents/ui/*(Card, Pill, ReadinessBadge, EmptyState, ErrorState, Spinner, Tooltip) +app/(authed)/issues/_components/issueCellPrimitives.tsx+IssueTypeIcon— the primitives to composeapp/globals.css--el-*+ element-shape tokens; the/tokensspecimen route- Jira / Linear board as the mirror product; finding #35 (not colour-alone), #54 (use the palette), #57 (bounded board)