/// Cards
Card
A surface block with a hairline border and sharp corners — flat title/subtitle/action props or compound Card.Header/Body/Footer.
import { Card } from "@protocore/pds";Basics
The flat API covers the common case: an optional bracket index, a title, a muted subtitle, body copy as children, and an action slot pinned to the footer.
Composition
When the layout is richer than the flat props allow, drop into Card.Header, Card.Body, and Card.Footer. The header and footer are flex rows, so a title sits left and controls or a status Badge sit right.
In a grid
Cards tile cleanly into a responsive grid. Keep body copy to a ≤60ch measure so cards in a row stay visually balanced.
When to use it
Reach for Card when you need a self-contained surface that groups a heading with body content and optional actions — a feature block, a settings panel, a summary tile. For a *tone-tinted note* (success/warning/danger), use Callout instead; it carries the colored left rule that Card deliberately omits. For a *media-led* block with an art panel and eyebrow, use Tile (or its ports ProductCard / PrincipleTile). For a *single labelled metric*, use StatCard. Card is the neutral, un-tinted container the others specialise.
Usage
Do
- Use the flat `title`/`subtitle`/`action` props for simple cards, and only reach for the compound parts when you need a two-sided header or multiple footer rows.
- Keep body copy to a comfortable measure (~60ch) so grids of cards stay even.
- Put the primary control in `action` (flat) or `Card.Footer` (compound) — one clear next step per card.
- Use `index` to enumerate a sequence of cards (steps, principles, features).
Don't
- Don't add a box-shadow or rounded corners — Card is a flat hairline surface by contract.
- Don't tint the whole card to signal status; that's Callout's job.
- Don't mix the flat `title` prop and a `Card.Header` in the same card — pick one model.
- Don't stuff multiple unrelated actions into the footer; if the card does many things it should be several cards.
Accessibility
- Card is a plain `<div>` surface — it renders no interactive semantics of its own. Any buttons or links you place in `action`/`Card.Footer` keep their native keyboard behavior.
- The bracket `index` is decorative (`aria-hidden`); put any meaning the number carries into the visible `title` as well.
- Give the card a heading element or `aria-labelledby` if it acts as a landmark region in a larger layout; by default it is not announced as a region.
Mobile (React Native)
Preview. @protocore/pds-mobile ships the React Native sibling of Card. It mirrors the web API where React Native allows; the package is a preview with no device-level QA yet, so pin it and expect small changes.
Import it from the mobile package (not @protocore/pds), inside a <PdsProvider> — there is no stylesheet, so style (a ViewStyle) replaces className and every value comes from the theme:
import { Card } from "@protocore/pds-mobile";Parity with web. The surface / feature block — hairline border, sharp corners, no shadow — with the same flat props and compound parts as web.
- Flat props
index/title/subtitle/action, plus compoundCard.Header/Card.Body/Card.Footer. - String / number children render as 14dp secondary body copy.
<Card index={1} title="Payments API" subtitle="v2.4.0" action={<Button>Open</Button>}>
Handles checkout and refunds.
</Card>Card props
| Prop | Type | Default | Description |
|---|---|---|---|
action | ReactNode | — | Footer action slot, usually a Button; separated from the body by 24px. |
children | ReactNode | — | Body content — rendered at 14px / secondary / 1.6 line-height. |
className | string | — | |
index | number | — | Optional bracket index pinned top-right, zero-padded to two digits (`1` → `[ 01 ]`). |
style | CSSProperties | — | |
subtitle | ReactNode | — | Secondary line under the title — 15px, muted. |
title | ReactNode | — | Card title — 22px / 500 / -0.01em, ink. |