Card
Surface component used for grouping content, actions, and metadata in PyColors UI.
Structured surfaces for product UILink to section
The Card component is a foundational surface used to group related content, actions, and metadata.
Use it for:
- dashboard tiles
- pricing blocks
- settings panels
- billing summaries
- feature cards
- list items
- empty states
- account sections
- product surfaces
Card is built on semantic tokens such as bg-card, border-border, and text-card-foreground, so it stays consistent across light and dark themes.
Core idea
Card creates structure. Use it to group meaningful content, not as decoration.
ImportLink to section
import { Card } from "@pycolors/ui";Basic usageLink to section
Use Card to group a title, description, content, and optional footer actions.
Account
Manage your profile settings.
Update personal details, security preferences, and integrations.
import {
Button,
Card,
CardHeader,
CardTitle,
CardDescription,
CardContent,
CardFooter,
} from "@pycolors/ui";
export function AccountCard() {
return (
<Card className="max-w-sm">
<CardHeader>
<CardTitle>Account</CardTitle>
<CardDescription>
Manage your profile settings.
</CardDescription>
</CardHeader>
<CardContent>
<div className="text-sm text-muted-foreground">
Update personal details, security preferences, and integrations.
</div>
</CardContent>
<CardFooter className="justify-end gap-2">
<Button variant="secondary">Cancel</Button>
<Button>Save</Button>
</CardFooter>
</Card>
);
}When to use CardLink to section
Use Card when content needs a clear surface, boundary, or grouping.
Dashboards
Settings
Billing
VariantsLink to section
Cards support semantic surface variants.
Use variants to adjust contrast without changing layout.
Default
Standard surface.
Muted
Subtle secondary surface.
Transparent
Layout-only surface.
import {
Card,
CardHeader,
CardTitle,
CardDescription,
} from "@pycolors/ui";
export function CardVariants() {
return (
<div className="grid gap-4 sm:grid-cols-3">
<Card>
<CardHeader>
<CardTitle>Default</CardTitle>
<CardDescription>Standard surface.</CardDescription>
</CardHeader>
</Card>
<Card variant="muted">
<CardHeader>
<CardTitle>Muted</CardTitle>
<CardDescription>Subtle secondary surface.</CardDescription>
</CardHeader>
</Card>
<Card variant="transparent" className="border-dashed">
<CardHeader>
<CardTitle>Transparent</CardTitle>
<CardDescription>Layout-only surface.</CardDescription>
</CardHeader>
</Card>
</div>
);
}Available variantsLink to section
| Variant | Purpose |
|---|---|
default | Main surface using bg-card |
muted | Secondary surface using a softer background |
transparent | Layout-only container with no filled background |
Variant rule
Use default for primary surfaces, muted for secondary groups, and transparent when you only need structure.
Interactive cardsLink to section
Use interactive when the whole card behaves like a selectable or navigational surface.
Clickable card
Hover and focus states communicate interactivity.
Interactive + muted
Useful for secondary selection items.
import {
Card,
CardHeader,
CardTitle,
CardDescription,
} from "@pycolors/ui";
export function InteractiveCards() {
return (
<div className="grid gap-4 sm:grid-cols-2">
<Card interactive>
<CardHeader>
<CardTitle>Clickable card</CardTitle>
<CardDescription>
Hover and focus states communicate interactivity.
</CardDescription>
</CardHeader>
</Card>
<Card interactive variant="muted">
<CardHeader>
<CardTitle>Interactive + muted</CardTitle>
<CardDescription>
Useful for secondary selection items.
</CardDescription>
</CardHeader>
</Card>
</div>
);
}Interaction rule
If the card navigates, render it as a real link using asChild. If it performs an action, render it as a button or put a Button inside.
With iconLink to section
Use asChild to render Card as another element while preserving Card styling.
This is useful for link cards.
import {
Card,
CardHeader,
CardTitle,
CardDescription,
} from "@pycolors/ui";
export function CardAsLink() {
return (
<Card asChild interactive className="max-w-sm">
<a href="/docs" className="block">
<CardHeader>
<CardTitle>Read the docs</CardTitle>
<CardDescription>Go to documentation →</CardDescription>
</CardHeader>
</a>
</Card>
);
}CompositionLink to section
A Card usually follows this structure:
<Card>
<CardHeader>
<CardTitle>Title</CardTitle>
<CardDescription>Description</CardDescription>
</CardHeader>
<CardContent>
Content
</CardContent>
<CardFooter>
Actions
</CardFooter>
</Card>Use each slot intentionally:
| Slot | Purpose |
|---|---|
CardHeader | Introduces the surface |
CardTitle | Names the grouped content |
CardDescription | Adds short context |
CardContent | Holds the main body |
CardFooter | Holds actions or supporting metadata |
Usage patternsLink to section
Start with the content group
Use Card only when the content belongs together.
Add a clear title
Most cards should have a title that explains the purpose of the surface.
Keep actions in the footer
Footer actions make the card easier to scan and keep layout predictable.
Use interactivity deliberately
Interactive cards should be clickable or selectable. Static cards should not have hover affordances.
Preserve semantic behavior
Use asChild with a real link for navigational cards.
Card vs section vs list itemLink to section
| Situation | Use |
|---|---|
| Grouped content with a visible surface | Card |
| Large page section with headings | Section |
| Repeated compact rows | List item |
| Navigation tile | Card with asChild link |
| KPI or metric | Card |
| Table data | Table |
| Temporary status or error | Alert or EmptyState |
Decision rule
Use Card when the surface helps users understand grouping, priority, or interaction.
APILink to section
Components
| Component | Description |
|---|---|
Card | Root surface |
CardHeader | Header area |
CardTitle | Card heading |
CardDescription | Supporting text |
CardContent | Main content area |
CardFooter | Footer actions or metadata |
Card props
| Prop | Type | Default | Description |
|---|---|---|---|
variant | CardVariant | "default" | Surface style |
interactive | boolean | false | Adds hover and focus-visible feedback |
asChild | boolean | false | Render via Radix Slot |
className | string | — | Additional Tailwind classes |
Card extends standard HTML div props.
React.HTMLAttributes<HTMLDivElement>TypeScript typesLink to section
export type CardVariant =
| "default"
| "muted"
| "transparent";
export type CardInteractive = boolean;AccessibilityLink to section
Guidelines:
- use meaningful headings inside cards when they introduce a section
- keep interactive semantics accurate
- use
asChildwithafor navigation - use
asChildwithbuttononly when the whole card performs an action - avoid multiple nested interactive elements inside an interactive card
- keep focus states visible for interactive cards
- do not make a card interactive only for visual decoration
Accessibility rule
A clickable card should still be a real link or button. Visual interactivity is not enough.
Prefer / avoidLink to section
Prefer
- clear grouping
- consistent card rhythm
- semantic headings
- footer actions for card-level actions
- real link semantics for navigation cards
Avoid
- cards used only for decoration
- too many nested cards
- interactive styling on static content
- clickable cards without link or button semantics
- multiple competing actions inside one clickable card
Product copy guidelinesLink to section
Card copy should make the grouped content easy to understand.
Strong title examples
Titles should describe the surface immediately without extra wording.