/// Cards
ProductCard
An illustrated product card — art panel, eyebrow, title, one-line body, a mono tag row, and an outbound footer link, with a [ 0N ] index.
import { ProductCard } from "@protocore/pds";Basics
A [ 0N ] index pins top-right, an art panel sits above the eyebrow + title + one-line body, a tags array renders a mono metadata row, and href turns the footer into an outbound link (linkLabel defaults to "View").
Move value across networks with guaranteed finality and no wrapped tokens.
View referenceProduct grid
The intended layout: a responsive n-up grid of enumerated products, each with its own line-art field.
When to use it
Use ProductCard for a catalogue of products, APIs, or features where each entry wants an enumerator, an illustration, a metadata tag row, and a *link out* to a detail page. It's the fully-loaded member of the tile family. If you don't need the index / tags / link — just art + text — drop to the generic Tile. For a numbered *principle* (no media, no link), use PrincipleTile. For a non-media grouping, use Card. Note the title prop is required on ProductCard (a product must be named), unlike Tile where it's optional.
Usage
Do
- Give each card a distinct `LineArt` variant so a grid reads as a set of different products.
- Keep the body to a single line — ProductCard is a scannable index entry, not a spec sheet.
- Use the `tags` row for stable metadata (protocol, version, transport), rendered as-typed mono.
- Set `href` (and `target`/`linkLabel`) so every card has one clear way through to detail.
Don't
- Don't overflow the `tags` row with more than a few chips; it's metadata, not navigation.
- Don't omit `title` — it's required and names the product.
- Don't use ProductCard for content with no destination; if there's nowhere to go, Tile is the honest choice.
- Don't put multiple links in the body; the footer link is the card's single outbound action.
Accessibility
- The footer link is a real `<a>` — it's keyboard-focusable and reads its `linkLabel`. The `↗︎` arrow is `aria-hidden`; keep the label meaningful ("View reference"), not just "View", when several cards share a page.
- The `[ 0N ]` index is decorative enumeration; don't encode essential meaning in the number alone.
- Wrap a product grid in a list so screen readers announce how many products there are.
ProductCard props
| Prop | Type | Default | Description |
|---|---|---|---|
art | ReactNode | — | The illustration panel — usually a `<LineArt>`. |
artHeight | number | 200 | Illustration panel height in px. Default `200`. |
children | ReactNode | — | One-line description body. |
className | string | — | |
eyebrow | ReactNode | — | Mono uppercase eyebrow above the title. |
href | string | — | Footer link destination — renders the outbound link when set. |
index | number | — | Enumerator pinned top-right, rendered as `[ 0N ]`. |
linkLabel | ReactNode | View | Footer link label. Default `"View"`. |
style | CSSProperties | — | |
tags | ReactNode[] | — | Mono metadata tags rendered in a row beneath the body. |
target | string | — | Anchor target for the footer link. |
title * | ReactNode | — | Product title. |