Card
A bordered container that groups related content. Six parts, one prop. The parts are layout only — they carry padding and rhythm, not behaviour.
All core components have been implemented and tested. The team is now focused on documentation and integration guides for consuming applications.
Import
import {
Card,
CardHeader,
CardTitle,
CardDescription,
CardContent,
CardFooter,
} from "@mikenotthepope/substrateui"Composition
Every part is optional and order is yours. CardContent and CardFooter both drop their top padding so a stack of parts keeps one rhythm instead of doubling the gap at each seam.
Card
├── CardHeader
│ ├── CardTitle
│ └── CardDescription
├── CardContent
└── CardFooterInteractive
interactive adds the affordances of a pressable surface: the border takes the ring colour, the card lifts 2px into a larger hard shadow, and a click seats it 3px down with the shadow removed. All of it collapses under prefers-reduced-motion.
12,340
visits this month
$8,420
up 12% from last month
Holding a form
A card is a plain container, so a form inside it needs no special handling — CardContent takes the fields and CardFooter takes the submit.
Accessibility
interactive is styling and nothing else. It does not add tabIndex, a role, or a key handler, so a card carrying only an onClick is unreachable by keyboard and invisible to screen readers — it looks pressable to a mouse user and does not exist for anyone else.
Put a real control inside instead. Wrap the title in a link, or give the card a button in its footer, and let the whole surface be decoration around it. Where the entire card must be one target, render it render=<a>-style as an anchor or button so the browser supplies focus, activation, and the announced role.
CardTitle is a div, not a heading, so it adds no document outline. In a list of cards where the titles are the structure, pass a heading element to render or nest one inside — otherwise a screen-reader user cannot navigate between them.
API Reference
Card owns one prop. The other five parts add padding and rhythm and take no props of their own — every prop you pass, including className, ref, and any data-* attribute, goes straight to the underlying div. See React.ComponentPropsWithRef<"div"> for that surface; the composition tree above is the more useful map of what goes where.
| Prop | Type | Default | Description |
|---|---|---|---|
interactive | boolean | false | Hover border highlight, 2px shadow lift, and a 3px press offset on click. Styling only — it does not make the card focusable or operable. |