Card
Bordered content surface with header, title, description, content, and footer subcomponents.
import { Card, CardHeader, CardTitle, CardDescription, CardContent, CardFooter } from '@elirobinson/react/components/molecules/Card';Styles: @elirobinson/react/styles/molecules/Card.css — already included when you import @elirobinson/react/styles.css.
Kids Recipes
Simple, fun recipes designed for kids.
Show code
import { Badge } from '@elirobinson/react/components/atoms/Badge';
import { Button } from '@elirobinson/react/components/atoms/Button';
import {
Card,
CardDescription,
CardFooter,
CardHeader,
CardTitle,
} from '@elirobinson/react/components/molecules/Card';
export default function Basic() {
return (
<div className="demo-col">
<Card>
<CardHeader>
<div className="demo-row">
<Badge>Food</Badge>
<Badge>Family</Badge>
</div>
<CardTitle>Kids Recipes</CardTitle>
<CardDescription>Simple, fun recipes designed for kids.</CardDescription>
</CardHeader>
<CardFooter>
<Button variant="ghost" size="sm">
View project
</Button>
</CardFooter>
</Card>
</div>
);
}When to use it
Use Card to group related content into one bordered surface — a portfolio tile, a
pricing tier, a contact block. It's a layout primitive, not a status signal: for a
message about the state of the page, reach for Alert; for a placeholder where a list
of cards would normally go, use EmptyState.
CardHeader, CardTitle, CardDescription, CardContent, and CardFooter are plain
layout slots — use the ones you need and skip the rest. A card doesn't require content
and a footer both.
With content and actions
Get in touch
Tell me what you need — no contracts required.
Practical AI consulting and tech support, from $150/hr.
Show code
import { Button } from '@elirobinson/react/components/atoms/Button';
import {
Card,
CardContent,
CardDescription,
CardFooter,
CardHeader,
CardTitle,
} from '@elirobinson/react/components/molecules/Card';
export default function WithContent() {
return (
<div className="demo-col">
<Card>
<CardHeader>
<CardTitle>Get in touch</CardTitle>
<CardDescription>Tell me what you need — no contracts required.</CardDescription>
</CardHeader>
<CardContent>
<p>Practical AI consulting and tech support, from $150/hr.</p>
</CardContent>
<CardFooter>
<Button variant="accent">Hire me</Button>
<Button variant="secondary">Learn more</Button>
</CardFooter>
</Card>
</div>
);
}Props
No props of its own beyond the inherited HTML attributes.
Also accepts all HTMLAttributes<HTMLDivElement> props.
CardHeader
No props of its own beyond the inherited HTML attributes.
Also accepts all HTMLAttributes<HTMLDivElement> props.
CardTitle
No props of its own beyond the inherited HTML attributes.
Also accepts all HTMLAttributes<HTMLHeadingElement> props.
CardDescription
No props of its own beyond the inherited HTML attributes.
Also accepts all HTMLAttributes<HTMLParagraphElement> props.
CardContent
No props of its own beyond the inherited HTML attributes.
Also accepts all HTMLAttributes<HTMLDivElement> props.
CardFooter
No props of its own beyond the inherited HTML attributes.
Also accepts all HTMLAttributes<HTMLDivElement> props.
Accessibility
Cardand its subcomponents render plain<div>s (andCardTitlean<h3>,CardDescriptiona<p>) with no implicit ARIA role — a card is a visual grouping, not a landmark.CardTitlealways renders an<h3>. It isn't configurable, so check that an<h3>is the right level in the surrounding heading outline before reaching for it — inside a page that's already past<h3>, write your own heading element instead.- Only
Carditself forwards a ref, to the outer<div>.CardHeader,CardTitle,CardDescription,CardContent, andCardFooterare plain functions with no ref forwarding. - Keyboard: a
Cardhas no interaction of its own. Any buttons or links placed inside it (as inCardFooter) keep their own native keyboard behavior.
Do
- Put the primary action in CardFooter as a real Button or link.
- Keep CardTitle to a short name — a product, a plan, a project — and put detail in CardDescription.
- Use Badge inside CardHeader for category tags above the title.
- Give a Card a fixed maxWidth in a grid so cards align instead of stretching unevenly.
Don't
- Wrap an entire page section in a Card — it's a content surface, not a page layout tool.
- Nest a Card inside a Card; flatten the hierarchy instead.
- Make the whole card clickable with a div onClick — wrap the title or an explicit link so keyboard users can reach it.
- Skip CardHeader and put a raw heading directly in CardContent — the header slot carries the spacing that makes the title read as a title.