Skip to content

Product card

Stable Available in release assets

Summarize a server-authored product with a durable detail-page link, honest price, inventory message, and resilient media treatment.

Product card in context

Show code
<article class="thin-product-card">
  <img src="product.jpg" alt="Blue canvas tote">
  <div class="thin-product-badges">
    <span class="thin-badge">Sale</span>
  </div>
  <div class="thin-product-card-body">
    <h2><a href="/products/tote">Canvas tote</a></h2>
    <p class="thin-product-price">
      <span aria-label="Sale price">$68.00</span>
      <s aria-label="Original price">$82.00</s>
    </p>
    <p class="thin-inventory-status" data-state="low-stock">Only 3 left</p>
  </div>
</article>

Each authored example uses the production assets and includes copyable markup.

Anatomy

  • Linked product media or named fallback
  • Optional badges
  • Product heading and durable link
  • Current and optional previous price
  • Server-rendered availability

Variants and sizes

  • Default — shown above
  • Sale — shown above
  • No image — shown above
  • Long localized product and price — shown above

Rendered fixtures exercise authored content and constrained layouts with the same production assets.

  • Available
  • Sale
  • Sold out
  • Low stock
  • Loading collection
  • Difficult content
  • Narrow container

Structured state fixtures are not published for this item yet.

Interaction and keyboard behavior

The product link and optional native controls work without enhancement; selection, inventory, and pricing remain server truth.

Accessibility

Use meaningful image alternatives, a descriptive product link, explicit price labels when multiple amounts appear, and text for availability.

Contract
COMPOSE
Basis
Native links, headings, forms, lists, and status content; no product-specific APG widget
Evidence
  • tests/unit/library/ecommerce-patterns.test.ts

API

Use .thin-product-card on semantic article markup and group card content in .thin-product-card-body. Optional quick-add steppers, mini-cart drawers, and gallery layouts compose with quantity-input, drawer, and product-gallery, which remain preview. Mark stock with .thin-inventory-status and data-state=low-stock or data-state=sold-out; the text must still say the state.

Behavior tier: datastar-optional

Structured host, property, and example tables are not authored for this item yet. Use the summary above and the primary example.

Fallback

Products, prices, forms, pagination, and empty states remain in document flow.

Assets and dependencies

  • /foundation.css
  • /layouts.css
  • /components.css
  • /patterns/ecommerce.css

Dependencies: quantity-input, drawer, product-gallery

Source: packages/ui/src/style/ecommerce.ts

Stability evidence

  • Semantic server-authored markup, intrinsic CSS, and no-JavaScript contract: test:tests/unit/library/ecommerce-patterns.test.ts
  • Complete item-specific API, fallback, difficult states, and preview composition honesty: test:tests/unit/library/composition-stable.test.ts
  • Cross-theme, density, narrow-container, zoom, and forced-colors fixture: review:site/src/pages/quality/index.astro#quality-review

Composition

Derived from the examples and style specs, not authored.

Composes

Used by