fluttercnfluttercn
Components

Card

A versatile container component for grouping related content

Installation

npx fluttercn@latest add card

Usage

Basic Card

A simple card with custom content:

Basic card component preview
Card(
  header: const CardHeader(
    title: CardTitle('Complete Card'),
    description: CardDescription('With all sections'),
  ),
  content: CardContent(
    child: Text(
      'Use the content slot for your main information or body copy.',
      style: TextStyle(color: AppTheme.textSecondary),
    ),
  ),
  footer: CardFooter(
    child: Row(
      children: [
        Button(
          onPressed: () {},
          child: const Text('Primary Action'),
        ),
        AppTheme.gapHorizontalSm,
        Button(
          variant: ButtonVariant.ghost,
          onPressed: () {},
          child: const Text('Secondary'),
        ),
      ],
    ),
  ),
)

Interactive Card

Cards can be made tappable with the onTap callback:

Interactive card preview
Card(
  onTap: () {
    print('Card tapped');
  },
  header: CardHeader(
    title: CardTitle('Clickable Card'),
    description: CardDescription('Tap to interact'),
  ),
  content: CardContent(
    child: Text('This card responds to taps'),
  ),
)

Card with Dividers

Visually separate sections with dividers:

Card with divider preview
Card(
  showDividers: true,
  header: CardHeader(
    title: CardTitle('Sectioned Card'),
    description: CardDescription('With dividers'),
  ),
  content: CardContent(
    child: Text('Content section'),
  ),
  footer: CardFooter(
    child: Text('Footer section'),
  ),
)

Examples

Profile Card

Profile card preview
Card(
  header: const CardHeader(
    title: CardTitle('John Doe'),
    description: CardDescription('Software Engineer'),
  ),
  content: CardContent(
    child: Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        const Text('Email: john@example.com'),
        AppTheme.gapSm,
        const Text('Location: San Francisco, CA'),
        AppTheme.gapSm,
        Row(
          children: const [
            Icon(Icons.star, color: Colors.amber),
            SizedBox(width: 4),
            Text('Top-rated mentor'),
          ],
        ),
      ],
    ),
  ),
  footer: CardFooter(
    child: Button(
      onPressed: () {},
      child: const Text('View Profile'),
    ),
  ),
)

API Reference

Card

PropertyTypeDefaultDescription
headerCardHeader?nullHeader section with title and description
contentCardContent?nullMain content area
footerCardFooter?nullFooter section for actions
childWidget?nullSingle child for simple cards (cannot be used with header/content/footer)
onTapVoidCallback?nullCallback when card is tapped
paddingEdgeInsets?nullCustom padding (only for single child mode)
showDividersboolfalseShow dividers between sections

CardHeader

PropertyTypeDefaultDescription
titleCardTitle?nullCard title widget
descriptionCardDescription?nullCard description widget
childWidget?nullCustom header content (cannot be used with title/description)
paddingEdgeInsets?nullCustom padding

CardTitle

PropertyTypeDefaultDescription
textStringrequiredThe title text
styleTextStyle?nullCustom text style

CardDescription

PropertyTypeDefaultDescription
textStringrequiredThe description text
styleTextStyle?nullCustom text style

CardContent

PropertyTypeDefaultDescription
childWidgetrequiredContent widget
paddingEdgeInsets?nullCustom padding

CardFooter

PropertyTypeDefaultDescription
childWidgetrequiredFooter widget
paddingEdgeInsets?nullCustom padding

Features

  • Composable Structure - Build cards with separate header, content, and footer sections
  • Interactive - Built-in tap handling with scale animation and hover effects
  • Flexible - Use simple single-child mode or full composable structure
  • Themed - Automatically adapts to your app's theme
  • Dividers - Optional visual separation between sections

Cards automatically handle hover states and press animations when onTap is provided.

Customization

Custom Padding

Card(
  header: CardHeader(
    title: CardTitle('Custom Spacing'),
    padding: EdgeInsets.all(24),
  ),
  content: CardContent(
    padding: EdgeInsets.symmetric(horizontal: 24, vertical: 16),
    child: Text('Custom padded content'),
  ),
)

Custom Styles

CardTitle(
  'Styled Title',
  style: TextStyle(
    fontSize: 24,
    color: Colors.blue,
    fontWeight: FontWeight.bold,
  ),
)

Do not use both child and header/content/footer together. Choose either the simple single-child approach or the composable structure.