Card
A flexible container for grouping related content. Uses a compound component pattern — compose Header, Content, and Footer independently for full layout control.
Compound PatternDark Mode3 VariantsComposable
Install
$
npx react-principles add card01
Theme Preview
A profile card rendered with forced light and dark styling — independent of the current app theme.
Light
AJ
Alice Johnson
alice@example.com
AdminActive
Dark
AJ
Alice Johnson
alice@example.com
AdminActive
02
Live Demo
Variant
AJ
Alice Johnson
alice@example.com
AdminActive
trending_up
+12.5%8,249
Monthly visitors
notifications
New comment
Bob left a reply on your post.
03
Code Snippet
src/ui/Card.tsx
import { Card } from "@/ui/Card"; import { Button } from "@/ui/Button"; <Card variant="elevated"> <Card.Header> <Card.Title>Account Settings</Card.Title> <Card.Description> Manage your profile and preferences. </Card.Description> </Card.Header> <Card.Content> <p className="text-sm text-slate-600 dark:text-slate-400"> Your account was last updated 3 days ago. </p> </Card.Content> <Card.Footer> <Button size="sm">Save changes</Button> <Button variant="ghost" size="sm">Cancel</Button> </Card.Footer> </Card>
Flat exports seperti CardHeader, CardContent, dan lainnya tetap didukung untuk migrasi bertahap.
04
Copy-Paste (Single File)
Snippet ini self-contained dan bisa dipindahkan ke project lain tanpa setup alias atau util tambahan.
Card.tsx
import type { HTMLAttributes } from "react"; import { cn } from "@/lib/utils"; export type CardVariant = "default" | "elevated" | "flat"; export interface CardProps extends HTMLAttributes<HTMLDivElement> { variant?: CardVariant; } const CARD_VARIANT_CLASSES: Record<CardVariant, string> = { default: "bg-white dark:bg-[#161b22] border border-slate-200 dark:border-[#1f2937]", elevated: "bg-white dark:bg-[#161b22] border border-slate-200 dark:border-[#1f2937] shadow-lg shadow-slate-200/60 dark:shadow-black/30", flat: "bg-slate-50 dark:bg-[#0d1117] border border-transparent", }; export function Card({ variant = "default", className, children, ...props }: CardProps) { return ( <div className={cn("rounded-xl", CARD_VARIANT_CLASSES[variant], className)} {...props}> {children} </div> ); } Card.Header = function CardHeader({ className, children, ...props }: HTMLAttributes<HTMLDivElement>) { return ( <div className={cn("p-6 pb-4", className)} {...props}> {children} </div> ); } Card.Title = function CardTitle({ className, children, ...props }: HTMLAttributes<HTMLHeadingElement>) { return ( <h3 className={cn("text-base font-bold text-slate-900 dark:text-white leading-snug", className)} {...props}> {children} </h3> ); } Card.Description = function CardDescription({ className, children, ...props }: HTMLAttributes<HTMLParagraphElement>) { return ( <p className={cn("mt-1 text-sm text-slate-500 dark:text-slate-400 leading-relaxed", className)} {...props}> {children} </p> ); } Card.Content = function CardContent({ className, children, ...props }: HTMLAttributes<HTMLDivElement>) { return ( <div className={cn("px-6 pb-4", className)} {...props}> {children} </div> ); } Card.Footer = function CardFooter({ className, children, ...props }: HTMLAttributes<HTMLDivElement>) { return ( <div className={cn("px-6 pb-6 flex items-center gap-3", className)} {...props}> {children} </div> ); }
05
Props
All sub-components extend their corresponding HTML element attributes.
| Component | Prop | Type | Default | Description |
|---|---|---|---|---|
Card | variant | "default" | "elevated" | "flat" | "default" | Visual style — border only, shadow, or flat background. |
Card | className | string | — | Additional CSS classes. |
Card.Header | className | string | — | Spacing wrapper for title + description. |
Card.Title | className | string | — | Renders as h3. Bold, dark text. |
Card.Description | className | string | — | Renders as p. Muted, secondary text. |
Card.Content | className | string | — | Main body area with horizontal padding. |
Card.Footer | className | string | — | Action row with flex + gap. Usually holds buttons. |