Components · Data display
Card
BetaGroups content about one thing, such as a workout.
- Source
components/ui/card.tsx - shadcn/ui Card
- Figma: not linked yet (Q13)
Upper body A
- Bench press · 4 × 8 · 60 kg
- Bent-over row · 4 × 10 · 50 kg
When to use
- To group content about one thing so it can be scanned and compared: a workout, a program, a stat on the dashboard.
- As a repeating item in a grid.
When not to use
- To wrap a whole page or a single form: use the page layout and spacing.
- For rows of the same data: use a Table; it's easier to scan and compare.
- Don't nest cards inside cards.
Anatomy
SAR 18,450
12% more than September
- 1. Container: card surface, border, rounded-xl, shadow-sm
- 2. Title, with an optional description
- 3. Action (optional), at the end of the header
- 4. Content
- 5. Footer (optional): summary or actions
Variants
- 8 clients
- 14 clients
- Static: shows information; may contain buttons.
- Clickable: the whole card opens one place. The link lives on the title and stretches over the card, so there's one tab stop and screen readers hear a proper link name. The shadow grows on hover.
States
| State | What changes | Token |
|---|---|---|
| Rest | Card surface, border, light shadow | bg-card, border, shadow-sm |
| Hover (clickable) | Shadow grows | shadow-md, duration-(--duration-fast) |
| Focus-visible (clickable) | Ring around the whole card | ring-ring |
Usage guidelines
- One primary idea per card, with the most important number or fact in the content.
- Cards in a grid have the same structure and height.
- A clickable card has no other buttons inside it.
Active clients
24
Active clients: 24, Pending: 3, Archived: 11, Revenue: SAR 18,450
Content guidelines
- Titles are short nouns or names: "Upper body A", "Revenue this month".
- Put units and periods in the description: "Week 3 · 6 exercises · 55 min".
Accessibility
- Render the title as a heading at the right level (
<CardTitle><h3>…</h3></CardTitle>);CardTitleitself is adiv. - For clickable cards, put the link on the title and stretch it, rather than wrapping the whole card in a link, so the accessible name is the title, not every word in the card.
- Cards in a grid are a list (
ul/li), so screen readers announce how many there are.
RTL
The action sits at the end of the header, the chevron on clickable cards moves to the left and points left (rtl:-scale-x-100).
Tokens used
Read from components/ui/card.tsx at build time, so this list changes when the component does. Opacity modifiers such as /90 are shadcn hover and focus tints on top of the token.
| Token | Utilities | SuperCoach | Coach |
|---|---|---|---|
| --card | bg-card | white | white |
| --card-foreground | text-card-foreground | neutral-950 | neutral-950 |
| --muted-foreground | text-muted-foreground | neutral-600 | neutral-600 |
- Radius
rounded-xl - Shadow
shadow-sm - Type
leading-none - Type
font-semibold - Type
text-sm
Props
<Card>
Also takes every prop of <div>
No props of its own.
<CardHeader>
Also takes every prop of <div>
No props of its own.
<CardTitle>
Also takes every prop of <div>
No props of its own.
<CardDescription>
Also takes every prop of <div>
No props of its own.
<CardAction>
Also takes every prop of <div>
No props of its own.
<CardContent>
Also takes every prop of <div>
No props of its own.
<CardFooter>
Also takes every prop of <div>
No props of its own.
Replaces in coach-admin
From the read-only audit of coach-admin: 135 style values, 168 uses.
Program, workout and meal cards are coach-admin-specific and get their own Planned pages; they will be built on this component.
Classes and selectors
.card-body12.card-icon5.card-full4.card-header2.card-placeholder2.cardInfo-default2.card-number2.card-header:first-child i2.card-grid1.card-body:last-child1.card-brand1.cardInfo-container1
Files
src/reusableComponents/MealCard/MealCard.scss61src/reusableComponents/InfoCard/InfoCard.scss33src/reusableComponents/card-grid/card-grid.scss27src/reusableComponents/sortable-card-grid/sortable-card-grid.scss12
The inventory lists the first 12 locations of each value, so file counts are a lower bound.
SCSS variables in these styles
$spacernot a color: spacing, size or layout$grid-gutter-widthnot a color: spacing, size or layout$valuenot a color: spacing, size or layout$card-border-widthnot a color: spacing, size or layout$border-color→--border$gray-300not a color: spacing, size or layout