Cards

mandatory

Card — a container of related content + actions, typically clickable as a whole. Material parity (`/components/cards`). 3 variants (elevated, filled, outlined), uniform anatomy, and rules for composition with images, lists, and feeds.

Spec — Cards

Facet *isual*do Koder Design. Material parity: https://m3.material.io/components/cards.

3 card variants

Variant Visual Use
*levated* Surface bg + shadow level 1 Default — slight depth, draws attention
*illed* Surface-variant bg + no shadow Less emphasis; for embedded cards within a denser context
*utlined* Transparent bg + 1px accent border High structure, low visual weight (forms with grouped fields)

Anatomy

┌──────────────────────────────┐
│  [Optional media]            │   ← image / video / illustration
│                              │
│  Title (title-large)         │
│  Subtitle (body-medium muted)│
│                              │
│  Body content                │
│                              │
│  [Action 1] [Action 2]       │   ← optional actions
└──────────────────────────────┘
  • *ontainer* radiusmd, padding 1624 px
  • *edia*(optional): full-width image, aspect 16:9 default
  • *itle* title-large (22/28, weight 600)
  • *ubtitle* body-medium (14/20) in text-muted
  • *ody* body-medium
  • *ctions* button row, right-aligned (or left in RTL)

R1 — Card density

Density Padding Use
Comfortable 24 px Default — feeds, dashboards
Compact 16 px Dense lists (table cards, multi-column grids)
Spacious 32 px Hero cards (single card per fold)

Density follows themes/ui-style.kmd preset's density token; can be explicitly overridden per card via class modifier.

R2 — Clickable card

Most cards are clickable as a whole (navigate to detail).

  • Entire card surface is the hit area
  • Hover state: subtle elevation boost (+1 level) OR background tint
  • Focus ring: 2 px on outer container (per interaction/states.kmd)
  • role="link" if it navigates; role="button" if it triggers an action
  • Inner buttons are stop-propagation: clicking them doesn't trigger

    the card's main action

  • Cursor: pointer on whole card

R3 — Compositions

Feed item card

Used in vertical scrollable feeds (per canonical-layouts.kmd L1).

  • Compact density
  • Title + subtitle + 1-3 lines of body
  • Optional avatar (40 px) + author name + timestamp
  • Click navigates to detail

Product card

  • Elevated variant
  • Hero image (16:9 or 1:1)
  • Title + price + rating
  • "Add to cart" or similar primary action
  • Hover: shadow boost + slight scale (1.02)

List-detail card

  • Outlined or Filled variant
  • Selected state: accent-tinted bg + accent border (1.5 px)
  • Used in list-detail layout (per L2)

Stats card (dashboard)

  • Outlined variant
  • Large numeric value (headline-large)
  • Label (title-small muted)
  • Optional sparkline / mini-chart

R4 — Cards within cards

*nti-pattern.*A card MUST NOT contain another card. If nesting feels needed, the inner content should be a listitem, expansionpanel, or embedded section — not a card.

Exception: a card containing one image-card preview (e.g., a tweet embed inside a notification card) — allowed because the inner is a quoted/embedded artifact, not a peer container.

R5 — Media handling

  • Aspect ratio: 16:9 (default), 1:1 (square avatar/product), 4:3 (legacy)
  • Loading: skeleton placeholder matches final aspect (no layout shift)
  • Failure: fallback to surface-variant bg + icon
  • Alt text: alt attribute REQUIRED for non-decorative images
  • Lazy-loading: loading="lazy" for cards below the fold

R6 — Per-preset variation

Preset Variant emphasis
material3 Elevated default (subtle shadow)
material2 Stronger shadows, sharper corners
windows_11 Mica backdrop blur on Elevated
windows_95 3D bevel border instead of shadow; sharp corners
glassmorphism Translucent + backdrop blur
brutalist Outlined only (no shadows, thick border)
neumorphism Soft inverse shadow (looks "pressed into" surface)
dieter_rams Outlined default; minimal ornament

R7 — Accessibility

  • Card title is a heading (<h2>-<h4> depending on page level)
  • Clickable card focus ring on outer container only (not on title)
  • Inner buttons reachable by Tab (separately from card focus)
  • Reading order matches visual order (DOM = visual)

R8 — Forbidden patterns

  • ❌ Card without title (just a body of text) — use a <section> instead
  • ❌ Multiple primary actions in card actions row (1 primary, N secondary)
  • ❌ Card with no border + no shadow + no bg variation (use a plain <div>)
  • ❌ Animations that change card height on hover (causes feed shift)
  • app-layout/canonical-layouts.kmd — feed (L1) uses cards
  • themes/elevation.kmd — Elevated variant level 1 default
  • themes/shape.kmd — radius-md container
  • interaction/states.kmd — hover/focus per card type
  • foundations/elements.kmd — Container family

Source: ../home/koder/dev/koder/meta/docs/stack/specs/components/cards.kmd