Document Card Specification

Canonical reference for the document card component. Used by the live app, the demo server, and Claude when regenerating either.

Live Examples

These cards use the exact same CSS as the production app (copied from templates/base.html).

Annotated Breakdown

Annotated card breakdown

Card Structure

document_card.html
├── card-top-row (flex row)
│   ├── card-thumbnail (75% width)
│   │   └── Link to /document/view/{ULID}
│   │       ├── IF HasThumbnail → <img class="thumbnail-img">
│   │       └── ELSE → <div class="thumbnail-placeholder"> with DocumentType text
│   └── card-sidebar (flex column, 25% width)
│       ├── card-buttons row 1 (flex row)
│       │   ├── Edit button (✎) → /document/{ULID}/edit
│       │   └── Select toggle (☐/☑) → same page, toggles ULID in ?sel= param
│       ├── card-buttons row 2 (flex row)
│       │   └── Bulk Edit (⚙) → /documents/bulk-edit?ulids={selected or this doc}
│       └── Tag chips (loop over doc.Tags)
└── card-bottom-content (flex row)
    ├── Filename link (ellipsis overflow)
    └── Type badge (uppercase, is-info is-light)

CSS Rules

Defined in templates/base.html — the single source of truth for card styles.

SelectorKey properties
.document-cardmax-width: 320px; overflow: hidden; hover box-shadow
.card-top-rowdisplay: flex
.card-thumbnailwidth: 75%; flex-shrink: 0
.thumbnail-imgwidth/height: 100%; object-fit: cover
.thumbnail-placeholderheight: 150px; centered text; background: #f0f0f0
.card-sidebarflex column; gap: 0.25rem; padding: 0.4rem
.card-buttonsflex row; gap: 0.25rem
.card-bottom-contentflex row; padding: 0.3rem 0.5rem
.tag-chipfont-size: 0.7rem; max-width: 7ch; ellipsis
.doc-type-badgeuppercase; font-size: 0.65rem; font-weight: 700
.document-card.is-selectedborder-left: 3px solid #3273dc

Select Toggle Behaviour

  • Unselected: outlined button (☐), link adds this ULID to ?sel= param
  • Selected: filled primary button (☑), link removes this ULID from ?sel= param
  • Card gets is-selected class (blue left border) when selected
  • All other URL params (view, page, show_hidden, q) preserved

URL scheme: /?view=flat&sel=AAAA,BBBB,CCCC — comma-separated ULIDs.

Bulk Edit button navigates to /documents/bulk-edit?ulids={selected_ulids}, or falls back to the single card's ULID if nothing is selected.

Template Variables

The card template (templates/partials/document_card.html) expects these variables per document:

VariableTypeDescription
doc.ULIDstringDocument ULID for URLs
doc.NamestringOriginal filename for display
doc.DocumentTypestringFile extension (pdf, jpg, docx, ...)
doc.HasThumbnailboolWhether to show image or placeholder
doc.Tags[]TagEach has .Name and .Color
doc.IsSelectedboolWhether this card is in the selection set
doc.SelectToggleURLstringURL that toggles this ULID in/out of ?sel=
selected_ulidsstringPage-level comma-separated selected ULIDs (for Bulk Edit link)

Variant Checklist

The demo and this page should always show at least these three variants:

  1. Thumbnail + multiple tags + selected (blue left border, filled select button)
  2. Placeholder (no thumbnail) + single tag + unselected
  3. Thumbnail + no tags + unselected

Source Files

FilePurpose
templates/partials/document_card.htmlProduction card template (pongo2)
templates/base.htmlCSS source of truth for card styles
templates/demo_card.htmlDemo page template (extends base.html)
cmd/demo/main.goDemo server with mock data
page_handlers.goDocumentWithMeta struct, enrichDocumentsWithSelection, URL builders
docs/document-card.htmlThis page (static, for GitHub Pages)

Writing Annotations

Annotations are generated by cmd/annotate-card/main.go as native SVG elements. The pipeline:

  1. Demo server serves a plain card at /card (template: demo_single_card.html)
  2. url2svg captures it as /tmp/godocs-card.svg
  3. cmd/annotate-card wraps the captured SVG in a larger SVG with label rects, text, and dashed leader lines
  4. Output: docs/annotated-card.svg

To update annotations, edit the annotations slice in cmd/annotate-card/main.go, then run task demo:card:svg.

Label style

Pale yellow background (fill="#fffde7"), gold border (stroke="#f5c518"), bold 11px text.

Leader lines

Dashed lines: stroke="#f5c518" stroke-width="1" stroke-dasharray="4,3". Each runs from label edge to target element centre on the card.

Rebuilding the Demo

When the card design changes:

  1. Update templates/partials/document_card.html and templates/base.html (CSS)
  2. Update templates/demo_single_card.html if the card structure changed
  3. Update mock data in cmd/demo/main.go if new fields were added
  4. Update annotation positions in cmd/annotate-card/main.go if layout shifted
  5. Update this page — live examples, structure tree, CSS table, template variables
  6. Recapture SVGs: task demo:card:svg (captures variants + annotated card)

← UI Components | Home