Skip to content

Card

The Card component is a composite layout element that groups related content within a bordered, rounded container. It uses a compound component pattern with CardHeader, CardContent, and CardFooter sub-components for structured content areas.

Import

import { Card, CardHeader, CardContent, CardFooter } from '@nim-ui/components';

Basic Usage

Basic Card

View Code
<Card>
<CardContent>
<p>This is a basic card with content only.</p>
</CardContent>
</Card>

Full Card Structure

Use all three sub-components for a complete card layout with header, content, and footer.

Full Card with Header, Content, and Footer

View Code
<Card>
<CardHeader>
<h3 className="text-lg font-semibold">Card Title</h3>
<p className="text-sm text-neutral-500">Card description goes here</p>
</CardHeader>
<CardContent>
<p>This is the main content area of the card.</p>
</CardContent>
<CardFooter>
<Button variant="primary" size="sm">Save</Button>
<Button variant="outline" size="sm">Cancel</Button>
</CardFooter>
</Card>

Header and Content Only

Card Without Footer

View Code
<Card>
<CardHeader>
<h3 className="text-lg font-semibold">Notifications</h3>
</CardHeader>
<CardContent>
<p>You have 3 unread notifications.</p>
</CardContent>
</Card>

Custom Styling

Cards accept a className prop for custom styling including width constraints, shadows, and border customization.

Custom Styled Cards

View Code
<Card className="shadow-lg">
<CardContent>Elevated card with shadow-lg</CardContent>
</Card>
<Card className="border-primary-500 border-2">
<CardContent>Card with custom border color</CardContent>
</Card>
<Card className="bg-primary-50 dark:bg-primary-900/20">
<CardContent>Card with custom background</CardContent>
</Card>

Props

Card

Name Type Default Description
className string - Additional CSS classes for custom styling (width, shadow, border, etc.)
children * ReactNode - Card content, typically CardHeader, CardContent, and/or CardFooter

CardHeader

Name Type Default Description
className string - Additional CSS classes to apply to the header area
children * ReactNode - Header content (title, description, etc.)

CardContent

Name Type Default Description
className string - Additional CSS classes to apply to the content area
children * ReactNode - Main card content

CardFooter

Name Type Default Description
className string - Additional CSS classes to apply to the footer area
children * ReactNode - Footer content (actions, links, metadata)

Usage Examples

User Profile Card

function UserProfileCard({ user }) {
return (
<Card className="max-w-sm">
<CardHeader>
<Flex align="center" gap="md">
<Avatar src={user.avatar} initials={user.initials} />
<div>
<h3 className="font-semibold">{user.name}</h3>
<p className="text-sm text-neutral-500">{user.role}</p>
</div>
</Flex>
</CardHeader>
<CardContent>
<p className="text-sm">{user.bio}</p>
</CardContent>
<CardFooter>
<Button variant="primary" size="sm">Follow</Button>
<Button variant="outline" size="sm">Message</Button>
</CardFooter>
</Card>
);
}

Settings Card

function SettingsCard() {
return (
<Card>
<CardHeader>
<h3 className="text-lg font-semibold">Account Settings</h3>
<p className="text-sm text-neutral-500">
Manage your account preferences
</p>
</CardHeader>
<CardContent>
<Stack spacing="md">
<Input label="Display Name" defaultValue="John Doe" />
<Input label="Email" type="email" defaultValue="[email protected]" />
<Textarea label="Bio" rows={3} />
</Stack>
</CardContent>
<CardFooter className="justify-end">
<Button variant="outline">Cancel</Button>
<Button variant="primary">Save Changes</Button>
</CardFooter>
</Card>
);
}

Card Grid

function CardGrid({ items }) {
return (
<Grid cols={3} gap="lg">
{items.map((item) => (
<Card key={item.id}>
<CardHeader>
<h3 className="font-semibold">{item.title}</h3>
</CardHeader>
<CardContent>
<p className="text-sm">{item.description}</p>
</CardContent>
<CardFooter>
<Button variant="ghost" size="sm">Learn more</Button>
</CardFooter>
</Card>
))}
</Grid>
);
}

Accessibility

The Card component renders semantic <div> elements. For better accessibility:

  • Use heading elements (h2, h3, etc.) in CardHeader for proper document structure
  • When cards are interactive (clickable), add role="button" and tabIndex={0} with keyboard handlers
  • For card lists, consider wrapping in a <section> with a label
{/* Interactive card */}
<Card
role="button"
tabIndex={0}
onClick={handleClick}
onKeyDown={(e) => e.key === 'Enter' && handleClick()}
className="cursor-pointer hover:shadow-md transition-shadow"
>
<CardContent>Click to view details</CardContent>
</Card>
{/* Card section with heading */}
<section aria-labelledby="team-heading">
<h2 id="team-heading">Team Members</h2>
<Grid cols={3} gap="md">
<Card>...</Card>
<Card>...</Card>
</Grid>
</section>
  • Grid - Arrange cards in responsive grid layouts
  • Stack - Stack cards vertically with spacing
  • Flex - Flex layout for card footer actions
  • Modal - Overlay dialog for detailed card interactions