Build beautiful card-based interfaces using the @constructive-io/ui Card component.
When to Apply
Use this skill when:
-
Building card-based layouts (dashboards, product grids, blog posts)
-
Creating stat cards, profile cards, or product cards
-
Designing interactive clickable cards
-
Implementing dashboard layouts with multiple card variants
Overview
The Card component from @constructive-io/ui provides a flexible container with multiple variants, sub-components, and styling options. Cards are perfect for grouping related content and creating visually distinct sections.
Card Components
import { Card, CardHeader, CardTitle, CardDescription, CardAction, CardContent, CardFooter, } from '@constructive-io/ui/card';
Component Hierarchy
Card ├── CardHeader │ ├── CardTitle │ ├── CardDescription │ └── CardAction (optional, positions in top-right) ├── CardContent └── CardFooter
Card Variants
The Card component supports 5 variants:
Default
Subtle shadow with standard border. Best for most use cases.
<Card variant="default"> <CardHeader> <CardTitle>Default Card</CardTitle> <CardDescription>Subtle shadow, standard border</CardDescription> </CardHeader> <CardContent> <p className="text-muted-foreground text-sm">Best for most use cases.</p> </CardContent> </Card>
Elevated
Larger shadow for prominence. Ideal for featured or important content.
<Card variant="elevated"> <CardHeader> <CardTitle>Featured Content</CardTitle> <CardDescription>This card demands attention</CardDescription> </CardHeader> <CardContent> <p className="text-muted-foreground text-sm"> Elevated cards have a more prominent shadow, ideal for hero sections. </p> </CardContent> </Card>
Flat
No shadow, border only. Minimal, clean appearance for dense layouts.
<Card variant="flat"> <CardHeader> <CardTitle>Minimal Card</CardTitle> <CardDescription>Clean and understated</CardDescription> </CardHeader> <CardContent> <p className="text-muted-foreground text-sm"> Flat cards work well in dense layouts or when you want minimal visual noise. </p> </CardContent> </Card>
Ghost
Transparent background, no border or shadow. For seamless integration.
<Card variant="ghost"> <CardHeader> <CardTitle>Ghost Card</CardTitle> <CardDescription>Blends into the background</CardDescription> </CardHeader> <CardContent> <p className="text-muted-foreground text-sm"> Ghost cards are transparent and blend seamlessly with the page. </p> </CardContent> </Card>
Interactive
Hover lift effect with enhanced shadow. Perfect for clickable cards.
<Card variant="interactive"> <CardHeader> <CardTitle>Clickable Card</CardTitle> <CardDescription>Hover to see the lift effect</CardDescription> </CardHeader> <CardContent> <p className="text-muted-foreground text-sm"> Interactive cards lift on hover, perfect for navigation items. </p> </CardContent> <CardFooter className="justify-between"> <span className="text-muted-foreground text-sm">Learn more</span> <ArrowRight className="text-muted-foreground h-4 w-4" /> </CardFooter> </Card>
Common Card Patterns
Card with Action Button
Use CardAction to place a button in the header's top-right corner:
import { MoreHorizontal } from 'lucide-react'; import { Button } from '@constructive-io/ui/button';
<Card> <CardHeader> <CardTitle>Card with Action</CardTitle> <CardAction> <Button variant="ghost" size="icon"> <MoreHorizontal className="h-4 w-4" /> </Button> </CardAction> <CardDescription>This card has an action button in the header.</CardDescription> </CardHeader> <CardContent> <p className="text-sm">Content with header action.</p> </CardContent> </Card>
Stat Card (Dashboard Metrics)
Compact cards for displaying key metrics:
import { TrendingUp } from 'lucide-react';
<Card className="w-[250px]"> <CardHeader className="pb-2"> <CardDescription>Total Revenue</CardDescription> <CardTitle className="text-3xl">$45,231.89</CardTitle> </CardHeader> <CardContent> <div className="flex items-center gap-1 text-sm text-success"> <TrendingUp className="h-4 w-4" /> <span>+20.1% from last month</span> </div> </CardContent> </Card>
User Profile Card
Card with avatar and user information:
<Card className="w-[350px]"> <CardHeader> <div className="flex items-center space-x-4"> <div className="bg-primary/10 text-primary flex h-12 w-12 items-center justify-center rounded-full font-semibold"> JD </div> <div> <CardTitle>John Doe</CardTitle> <CardDescription>Software Engineer</CardDescription> </div> </div> </CardHeader> <CardContent> <p className="text-sm">Passionate about building great user experiences.</p> <div className="text-muted-foreground mt-4 flex justify-between text-sm"> <span>Followers: 1,234</span> <span>Following: 567</span> </div> </CardContent> <CardFooter> <Button className="w-full">Follow</Button> </CardFooter> </Card>
Product Card
E-commerce style card with image placeholder, price, and actions:
import { Heart, Star } from 'lucide-react'; import { Button } from '@constructive-io/ui/button';
<Card variant="interactive" className="w-[300px]"> <CardHeader> <div className="bg-muted/50 mb-2 aspect-square rounded-lg"> {/* Product image goes here */} </div> <CardTitle>Wireless Headphones</CardTitle> <CardDescription>Premium noise-cancelling headphones</CardDescription> </CardHeader> <CardContent> <div className="flex items-center justify-between"> <span className="text-2xl font-bold">$299</span> <div className="flex items-center gap-1"> <Star className="h-4 w-4 fill-amber-400 text-amber-400" /> <span className="text-muted-foreground text-sm">4.9</span> </div> </div> </CardContent> <CardFooter className="flex gap-2"> <Button className="flex-1">Add to Cart</Button> <Button variant="outline" size="icon"> <Heart className="h-4 w-4" /> </Button> </CardFooter> </Card>
Blog Post Card
Card for article previews with tags:
import { Badge } from '@constructive-io/ui/badge'; import { Button } from '@constructive-io/ui/button';
<Card className="w-[400px]"> <CardHeader> <CardTitle>Getting Started with React</CardTitle> <CardDescription>Published on March 15, 2024</CardDescription> </CardHeader> <CardContent> <p className="text-muted-foreground text-sm"> Learn the fundamentals of React and how to build your first component. This tutorial covers everything you need to know to get started. </p> <div className="mt-4 flex gap-2"> <Badge variant="secondary">React</Badge> <Badge variant="secondary">Tutorial</Badge> <Badge variant="secondary">Beginner</Badge> </div> </CardContent> <CardFooter> <Button>Read More</Button> </CardFooter> </Card>
Card Grid Layouts
Simple 3-Column Grid
<div className="grid max-w-4xl grid-cols-1 gap-4 md:grid-cols-3"> <Card> <CardHeader> <CardTitle>Card 1</CardTitle> <CardDescription>First card in the grid.</CardDescription> </CardHeader> <CardContent> <p className="text-sm">Content for card 1.</p> </CardContent> </Card> <Card> <CardHeader> <CardTitle>Card 2</CardTitle> <CardDescription>Second card in the grid.</CardDescription> </CardHeader> <CardContent> <p className="text-sm">Content for card 2.</p> </CardContent> </Card> <Card> <CardHeader> <CardTitle>Card 3</CardTitle> <CardDescription>Third card in the grid.</CardDescription> </CardHeader> <CardContent> <p className="text-sm">Content for card 3.</p> </CardContent> </Card> </div>
Dashboard Layout with Stats
A complete dashboard layout with stat cards and a main content area:
<div className="grid max-w-4xl grid-cols-1 gap-4 md:grid-cols-4"> {/* Stats row - 4 small cards */} <Card className="col-span-1"> <CardHeader className="pb-2"> <CardDescription>Users</CardDescription> <CardTitle className="text-2xl">2,350</CardTitle> </CardHeader> <CardContent> <p className="text-muted-foreground text-xs">+180 this week</p> </CardContent> </Card>
<Card className="col-span-1"> <CardHeader className="pb-2"> <CardDescription>Revenue</CardDescription> <CardTitle className="text-2xl">$12.5k</CardTitle> </CardHeader> <CardContent> <p className="text-xs text-success">+12.3%</p> </CardContent> </Card>
<Card className="col-span-1"> <CardHeader className="pb-2"> <CardDescription>Orders</CardDescription> <CardTitle className="text-2xl">1,247</CardTitle> </CardHeader> <CardContent> <p className="text-muted-foreground text-xs">+32 today</p> </CardContent> </Card>
<Card className="col-span-1"> <CardHeader className="pb-2"> <CardDescription>Conversion</CardDescription> <CardTitle className="text-2xl">3.2%</CardTitle> </CardHeader> <CardContent> <p className="text-xs text-success">+0.4%</p> </CardContent> </Card>
{/* Main content - full width elevated card */} <Card variant="elevated" className="col-span-2 md:col-span-4"> <CardHeader> <CardTitle>Recent Activity</CardTitle> <CardDescription>Your latest updates and notifications</CardDescription> </CardHeader> <CardContent> <div className="text-muted-foreground space-y-3 text-sm"> <p>Activity content would go here...</p> </div> </CardContent> </Card> </div>
Styling with data-slot
Cards use data-slot attributes for targeted CSS styling:
/* Target specific card parts / [data-slot="card"] { / Custom card styles */ }
[data-slot="card-header"] { /* Custom header styles */ }
[data-slot="card-title"] { /* Custom title styles */ }
[data-slot="card-description"] { /* Custom description styles */ }
[data-slot="card-content"] { /* Custom content styles */ }
[data-slot="card-footer"] { /* Custom footer styles */ }
[data-slot="card-action"] { /* Custom action button area styles */ }
Adding Borders to Header/Footer
Cards support conditional borders on header and footer:
{/* Header with bottom border */} <Card> <CardHeader className="border-b"> <CardTitle>Bordered Header</CardTitle> </CardHeader> <CardContent>Content here</CardContent> </Card>
{/* Footer with top border */} <Card> <CardHeader> <CardTitle>Card Title</CardTitle> </CardHeader> <CardContent>Content here</CardContent> <CardFooter className="border-t"> <Button>Action</Button> </CardFooter> </Card>
TypeScript Types
import type { CardProps } from '@constructive-io/ui/card';
// CardProps extends React.ComponentProps<'div'> with: interface CardProps { variant?: 'default' | 'elevated' | 'flat' | 'ghost' | 'interactive'; className?: string; children?: React.ReactNode; // ...all standard div props }
Best Practices
-
Choose the right variant - Use default for most cases, elevated for featured content, interactive for clickable cards, flat for dense layouts
-
Consistent spacing - Cards have built-in padding (px-6, py-6). Use the sub-components to maintain consistency
-
Use CardAction for header buttons - It automatically positions in the top-right corner
-
Responsive grids - Use Tailwind's responsive grid classes (md:grid-cols-3) for card layouts
-
Semantic structure - Always use CardHeader with CardTitle for accessibility
-
Interactive cards - Wrap the entire card in a link or button for clickable cards
References
-
@constructive-io/ui Card component
-
Tailwind CSS Grid
-
Lucide Icons for card icons