5.2.4 Design — attachments panel + preview (`design/work-items/attachments.mock.html`: strip/list views, upload affordances, editor-sourced block, lightbox)
Estimate: 40m
The design asset the panel (5.2.5) and preview (5.2.6) build against. NO attachment surface is designed anywhere — detail.pen has no attachments section (the detail page reserves the Epic-5 slot in a code comment only). Under the design gate that is the NONE-exists case, so this subtask produces the asset FIRST (mirrors 5.1.3 and the prior HTML-mockup design subtasks). Output: design/work-items/attachments.mock.html (built from components/ui/* + --el-* + element-shape tokens) + a PNG export + a new section in design/work-items/design-notes.md. Passes the render checklist; AA-safe; light + dark parity. Mirror: the Jira Cloud attachments panel (strip/list views, verified at plan time).
Specify, panel by panel:
- Placement — a left-column
ContentSectionCard("Attachments" + count + the view toggle + the Attach button in the header), between Relationships and Activity (content-width, multi-row — the rail is for scalars; same argument as 2.4.5). - Strip view — thumbnail cards: image preview (cover-fit) or the file-type glyph (by MIME family) on a
--el-surface-softtile, filename (truncating, full on title), date; hover/focus reveals per-card download + delete icon buttons. Editor-sourced cards carry a small source indicator and their delete affordance is disabled with the points-at-source tooltip ("Added in the description — remove it there"). Cards whose delete the caller lacks (not uploader, not admin) simply omit the control. - List view — the same rows densified: glyph · name · size · date · uploader · actions; the toggle is a small segmented/menu control in the header (mirror the shipped view-switcher grammar from
list.mock.html). - Upload affordances — the header Attach button (file picker, multi-select) AND the whole-panel dropzone (drag-over highlight state: dashed
--el-accentborder + tint); the uploading state (per-file progress card with name + indeterminate/percent bar + cancel); inline upload errors (the 2.3.7 typed trio — too large / unsupported type / rate-limited) as a rose-tint AA banner (the 2.4.9 error grammar). - Pagination — "Show more (N)" at the strip/list end (finding #57); the loading skeleton; the empty state ("No attachments yet" + Attach affordance, never blank);
ErrorState. - Delete confirm — popover naming the file ("Delete <name>? Attachments can't be restored." — the hard-delete truth;
--el-dangerconfirm + ghost cancel, the 2.4.9 remove grammar). - Preview lightbox (for 5.2.6) — a full-screen
Modalover a focused attachment: image centered (contain-fit, dark scrim) or PDF in an embedded frame; header bar with filename + size, a Download button, and the close ×; non-previewable types never open it (the card downloads instead). No prev/next navigation (unverified in the mirror — documented out). - Viewer (read-only) — panel + preview visible; no Attach, no delete, no dropzone.
Acceptance criteria
design/work-items/attachments.mock.html+ PNG + the design-notes section exist; composed from the shipped primitives +--el-*/element-shape tokens only; render checklist + AA + dark parity pass.- Panels cover: placement, strip + list views with the toggle, per-card actions incl. the editor-sourced disabled-delete + tooltip, both upload affordances + uploading progress + the three inline errors, "Show more (N)" + skeleton + empty + error, the delete confirm, the preview lightbox (image AND pdf variants), and the viewer state.
design-notes.mdnames the composing primitives + copy strings, the file-type glyph mapping (by MIME family), records "no prev/next in preview" and the public-unguessable-URL serving decision as documented slots, and states the panel is paged (50/“Show more”) not load-all.- No improvised primitive; any new
--el-*/shape token need is recorded for 5.2.5/6.
Context refs
design/work-items/design-notes.md+detail.pen(placement context; the section card grammar) +list.mock.html(the view-switcher + row grammar to reuse)components/ui/*(ContentSectionCard,Modal,Button,Pill,EmptyState,ErrorState) + the 2.4.9 confirm/error grammarlib/blob/allowlist.ts— the MIME families the glyph map covers- The verified Jira panel behaviours in the Story 5.2 description; findings #35/#54; the design-mockup render checklist