We use tracking cookies to understand how you use the product and help us improve it. For more information on how we store cookies, read our  privacy policy.

Card.tsx

Compound card component for displaying content in a structured layout

The Card component is a compound component system for creating structured content containers with header, content, and footer sections.

Features

  • Compound component pattern
  • Flexible layout with grid-based header
  • Optional action slot in header
  • Consistent spacing and styling
  • Fully customizable with className

Basic Usage

app/page.tsx
import { Card, CardHeader, CardTitle, CardDescription, CardContent } from '@/components/ui/Card';

export default function Page() {
  return (
    <Card>
      <CardHeader>
        <CardTitle>Card Title</CardTitle>
        <CardDescription>Card description goes here</CardDescription>
      </CardHeader>
      <CardContent>
        <p>Card content</p>
      </CardContent>
    </Card>
  );
}
app/page.tsx
import { Card, CardHeader, CardTitle, CardContent, CardFooter } from '@/components/ui/Card';
import { Button } from '@/components/ui/Button';

<Card>
  <CardHeader>
    <CardTitle>Confirm Action</CardTitle>
  </CardHeader>
  <CardContent>
    <p>Are you sure you want to proceed?</p>
  </CardContent>
  <CardFooter>
    <Button variant="outline">Cancel</Button>
    <Button>Confirm</Button>
  </CardFooter>
</Card>

With Action Button

The CardAction component positions an element in the top-right corner:

app/page.tsx
import { Card, CardHeader, CardTitle, CardDescription, CardAction, CardContent } from '@/components/ui/Card';
import { Button } from '@/components/ui/Button';
import { MoreVertical } from 'lucide-react';

<Card>
  <CardHeader>
    <CardTitle>Settings</CardTitle>
    <CardDescription>Manage your preferences</CardDescription>
    <CardAction>
      <Button variant="ghost" size="icon">
        <MoreVertical className="h-4 w-4" />
      </Button>
    </CardAction>
  </CardHeader>
  <CardContent>
    <p>Settings content</p>
  </CardContent>
</Card>

Custom Styling

app/page.tsx
<Card className="border-brand">
  <CardHeader className="bg-brand/10">
    <CardTitle className="text-brand">Custom Styled Card</CardTitle>
  </CardHeader>
  <CardContent>
    <p>Content with custom styling</p>
  </CardContent>
</Card>

Grid Layout

Cards work well in grid layouts:

app/page.tsx
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
  <Card>
    <CardHeader>
      <CardTitle>Card 1</CardTitle>
    </CardHeader>
    <CardContent>Content 1</CardContent>
  </Card>
  
  <Card>
    <CardHeader>
      <CardTitle>Card 2</CardTitle>
    </CardHeader>
    <CardContent>Content 2</CardContent>
  </Card>
  
  <Card>
    <CardHeader>
      <CardTitle>Card 3</CardTitle>
    </CardHeader>
    <CardContent>Content 3</CardContent>
  </Card>
</div>

Implementation

The Card uses a compound component pattern:

components/ui/Card.tsx
function Card({ className, ...props }: React.ComponentProps<'div'>) {
  return (
    <div
      className={cn(
        'bg-neutral/40 text-foreground flex flex-col gap-6 rounded-md border border-neutral py-6 shadow-sm',
        className
      )}
      {...props}
    />
  );
}

function CardHeader({ className, ...props }: React.ComponentProps<'div'>) {
  return (
    <div
      className={cn(
        'grid auto-rows-min items-start gap-1.5 px-6',
        className
      )}
      {...props}
    />
  );
}

Components

Card

Main container with background, border, and shadow.

CardHeader

Header section with grid layout. Automatically adjusts when CardAction is present.

CardTitle

Title text with semibold font weight.

CardDescription

Muted description text below the title.

CardAction

Action button positioned in top-right corner of header.

CardContent

Main content area with horizontal padding.

CardFooter

Footer section for actions or additional info.

Data Slots

Components use data-slot attributes for styling hooks:

  • data-slot="card"
  • data-slot="card-header"
  • data-slot="card-title"
  • data-slot="card-description"
  • data-slot="card-action"
  • data-slot="card-content"
  • data-slot="card-footer"

How is this guide ?

Last updated on