ReferenceComponents

product_cards

One product card, or a rail of them.

Things to buy, shown as things to buy. product_cards gives each item a real image, a price in tabular figures and one optional badge, the reason this card is worth a second look.

A single item renders as one card on the left. Two or more become a horizontal rail, all the height of the tallest card, that starts on the thread's own left edge.

Best sellerAero Glide 2Volt / white★★★★★★★★★★4.7 (1,284)$129
Court LowBone leather★★★★★★★★★★4.2 (96)$95
Trail CircuitSlate / moss$149

Re-rendered in the browser from the SDK’s own scales. Not a screenshot.

Rendered natively by the Flutter SDK and the Web SDK, both since 0.1.0.

When not to use it

Do not use it for order history or anything else where the picture is incidental. item_list is denser and reads faster.

Do not use it to compare tiers of a subscription, which is plan_comparison, and do not use it as a photo gallery of one product, which is media_gallery.

Props

Every block also carries type and a required fallback_text of 1 to 300 characters.

PropTypeRequiredConstraints
itemsarrayYes1 to 10 entries.
items[].titlestringYes1 to 120 characters.
items[].subtitlestringNoUp to 200 characters.
items[].pricestringNoUp to 30 characters. Formatted by you, including the currency symbol.
items[].image_urlstringNohttps only.
items[].badgestringNoUp to 30 characters. This block's one accent mark.
items[].ratingnumberNo0 to 5. Drawn as stars. A rating goes here as a number, not into badge as text.
items[].rating_countintegerNo0 to 100,000,000. How many ratings rating averages. Drawn with the stars.
items[].actionactionNo{ kind: "reply", text } or { kind: "open_url", url }. See Actions. Omit it and the card is not tappable.

On the wire

{
  "id": "blk_04",
  "type": "product_cards",
  "fallback_text": "Three running shoes under $150.",
  "props": {
    "items": [
      {
        "title": "Aero Glide 2",
        "subtitle": "Road, neutral",
        "price": "$129",
        "badge": "Best seller",
        "image_url": "https://cdn.example.com/aero-glide-2.jpg",
        "action": {
          "kind": "reply",
          "text": "Add Aero Glide 2 in size 43"
        }
      },
      {
        "title": "Court Low",
        "subtitle": "Everyday, leather",
        "price": "$95",
        "image_url": "https://cdn.example.com/court-low.jpg",
        "action": {
          "kind": "reply",
          "text": "Add Court Low in size 42"
        }
      },
      {
        "title": "Trail Circuit",
        "subtitle": "Trail, waterproof",
        "price": "$149",
        "image_url": "https://cdn.example.com/trail-circuit.jpg"
      }
    ]
  }
}

Interaction

A card with an action presses and announces its title, subtitle, badge and price as one label. Cards without one are content. Legal kinds are reply and open_url. Both execute: open_url opens the page in an in-app browser, or goes to your RendelConfig.onOpenUrl when you set one. https only.

The rail scrolls horizontally; it does not paginate and it has no arrows, because on a phone the cut-off card at the right edge is the affordance.

States

StateWhat the SDK draws
LoadingTwo card-shaped placeholders in a rail at the real card width.
EmptyAn empty items array renders fallback_text bare, without a plate, because this block carries no enclosure of its own.
Image missingThe image slot holds a sunk rectangle with a broken-image glyph; the rest of the card renders normally.

Accessibility

fallback_text should name the set rather than list it: "Three running shoes under $150." Prices are read from each card's own label.