Card
A flexible container for grouping related content with headers and footers.
Overview
The Card component provides a flexible container system for grouping related content. It includes specialized sections for headers, content, footers, and toolbars.
Set hoverable on the root card when you want the surface to transition from surface-1 to surface-2 on hover.
Usage
import {
Button,
Card,
CardContent,
CardHeader,
CardHeading,
CardTitle,
CardToolbar,
Label,
Switch,
} from "@tilt-legal/cubitt-components/primitives";<Card>
<CardHeader>
<CardHeading>
<CardTitle>...</CardTitle>
</CardHeading>
<CardToolbar>
...
</CardToolbar>
</CardHeader>
<CardContent>
...
</CardContent>
</Card>;Examples
Hoverable
Use hoverable when a card should shift from surface-1 to surface-2 on hover.
import {
Card,
CardContent,
CardDescription,
CardHeader,
CardHeading,
CardTitle,
} from "@tilt-legal/cubitt-components/primitives";
<Card className="w-full max-w-md" hoverable>
<CardHeader>
<CardHeading>
<CardTitle>Activity Summary</CardTitle>
<CardDescription>
Use `hoverable` when a card needs a subtle surface shift on hover.
</CardDescription>
</CardHeading>
</CardHeader>
<CardContent>
<p className="text-fg-2 text-sm">
This card transitions from `surface-1` to `surface-2` while keeping the
same structure and spacing.
</p>
</CardContent>
</Card>With Toolbar
Use CardToolbar to add action buttons to the header.
import {
Button,
Card,
CardContent,
CardHeader,
CardHeading,
CardTitle,
CardToolbar,
Label,
Switch,
} from "@tilt-legal/cubitt-components/primitives";
import { Gear } from "@tilt-legal/cubitt-icons/ui/outline";
<Card className="w-full max-w-md">
<CardHeader>
<CardHeading>
<CardTitle>Settings</CardTitle>
</CardHeading>
<CardToolbar>
<Button mode="icon" variant="secondary">
<Gear />
</Button>
</CardToolbar>
</CardHeader>
<CardContent>
<div className="space-y-3">
<Label orientation="horizontal" className="justify-between">
Email notifications
<Switch />
</Label>
<Label orientation="horizontal" className="justify-between">
Push notifications
<Switch defaultChecked />
</Label>
</div>
</CardContent>
</Card>With Meta (Top)
Use CardMeta at the top of a card for metadata like timestamps,
categories,
or status.
import {
Card,
CardContent,
CardDescription,
CardHeader,
CardHeading,
CardTitle,
CardMeta,
} from "@tilt-legal/cubitt-components/primitives";
import { Clock } from "@tilt-legal/cubitt-icons/ui/outline";
<Card className="w-full max-w-md">
<CardMeta>
<Clock className="text-fg-1" />
<span>Updated 2 hours ago</span>
</CardMeta>
<CardHeader>
<CardHeading>
<CardTitle>Project Overview</CardTitle>
<CardDescription>Track your project progress</CardDescription>
</CardHeading>
</CardHeader>
<CardContent>
<p className="text-sm">
CardMeta can be placed at the top of a card to show metadata like
timestamps, categories, or tags.
</p>
</CardContent>
</Card>With Meta (Bottom)
CardMeta can also be placed at the bottom for footer-style metadata.
import {
Button,
Card,
CardContent,
CardDescription,
CardFooter,
CardHeader,
CardHeading,
CardMeta,
CardTitle,
} from "@tilt-legal/cubitt-components/primitives";
<Card className="w-full max-w-md">
<CardHeader>
<CardHeading>
<CardTitle>Article Title</CardTitle>
<CardDescription>Read the full article</CardDescription>
</CardHeading>
</CardHeader>
<CardContent>
<p className="text-sm">
CardMeta can also be placed at the bottom of a card for footer-style
metadata.
</p>
</CardContent>
<CardFooter>
<Button className="w-full">Read More</Button>
</CardFooter>
<CardMeta className="justify-between">
<span>Published: Jan 15, 2025</span>
<span>5 min read</span>
</CardMeta>
</Card>Advanced
import {
Badge,
Button,
Card,
CardContent,
CardHeader,
CardHeading,
CardMeta,
CardTitle,
CardToolbar,
} from "@tilt-legal/cubitt-components/primitives";
import { ChartActivity, Plus } from "@tilt-legal/cubitt-icons/ui/outline";
const users = [
{
id: "1",
name: "Kathryn Campbell",
email: "kathryn@example.com",
status: "active",
},
{
id: "3",
name: "Sophia Johnson",
email: "sophia@example.com",
status: "active",
},
{
id: "2",
name: "Robert Smith",
email: "robert@example.com",
status: "inactive",
},
{
id: "4",
name: "Sophia Johnson",
email: "sophia@example.com",
status: "active",
},
{
id: "5",
name: "Kathryn Campbell",
email: "kathryn@example.com",
status: "active",
},
];
<Card className="w-full max-w-md">
<CardMeta>
<ChartActivity />
<span>32 new users this week</span>
</CardMeta>
<CardHeader>
<CardHeading>
<CardTitle>Recent Users</CardTitle>
</CardHeading>
<CardToolbar>
<Button variant="secondary">
<Plus />
Add user
</Button>
</CardToolbar>
</CardHeader>
<CardContent className="gap-0 py-0">
{users.map((user) => (
<div
key={user.id}
className="flex items-center justify-between gap-2 border-border-3 border-b py-4 last:border-none"
>
<div className="flex items-center gap-3">
<div className="flex size-8 items-center justify-center rounded-full border-border-4 bg-surface-3 text-sm">
{user.name
.split(" ")
.map((n) => n[0])
.join("")}
</div>
<div>
<div className="font-medium text-sm">{user.name}</div>
<div className="text-fg-2 text-xs">{user.email}</div>
</div>
</div>
<Badge variant={user.status === "active" ? "brand" : "secondary"}>
{user.status.charAt(0).toUpperCase() + user.status.slice(1)}
</Badge>
</div>
))}
</CardContent>
</Card>API Reference
Card
The root container component for all card sections.
| Prop | Type | Default |
|---|---|---|
hoverable | boolean | false |
className | string | - |
CardHeader
Contains the card heading and optional toolbar. Uses flexbox layout to align items.
| Prop | Type | Default |
|---|---|---|
className | string | - |
CardHeading
Wrapper for CardTitle and CardDescription with vertical spacing.
| Prop | Type | Default |
|---|---|---|
className | string | - |
CardTitle
The main heading for the card (renders as h3).
| Prop | Type | Default |
|---|---|---|
className | string | - |
CardDescription
Supporting text that describes the card's purpose.
| Prop | Type | Default |
|---|---|---|
className | string | - |
CardToolbar
Container for action buttons, aligned to the right of the header.
| Prop | Type | Default |
|---|---|---|
className | string | - |
CardContent
The main content area of the card.
| Prop | Type | Default |
|---|---|---|
className | string | - |
CardTable
Alternative content area optimized for table layouts.
| Prop | Type | Default |
|---|---|---|
className | string | - |
CardFooter
The bottom section for actions or additional information.
| Prop | Type | Default |
|---|---|---|
className | string | - |
CardMeta
Displays metadata like timestamps, categories, or tags. Can be placed at the top or bottom of the card.
| Prop | Type | Default |
|---|---|---|
className | string | - |
Design Guidelines
Structure
- CardMeta can be placed first (top) or last (bottom) in the card for metadata
- CardHeading should contain CardTitle and optionally CardDescription
- CardToolbar is for action buttons (1-2 icon buttons recommended)
- CardContent is for the main content area
- CardFooter is optional, use for primary actions or additional info
Best Practices
- Place primary actions in CardFooter and secondary actions in CardToolbar
- Keep CardToolbar minimal with icon buttons
- Use CardMeta at the top for timestamps/status or at the bottom for article metadata
- CardMeta automatically displays as flexbox with justify-between for multiple children
- Cards don't require all sections - use only what's needed
- For list items within cards, use
py-1on CardContent to reduce padding