Skip to main content

Exercise 1: Component Composition

Objective

Practice building reusable components using composition patterns.

Task

Build a card component system with proper composition.

Requirements

1. Create a Card Component System

// Create these components:
// - Card (container)
// - Card.Header
// - Card.Body
// - Card.Footer
// - Card.Image

// Example usage:
<Card>
<Card.Image src='...' alt='...' />
<Card.Header>
<h2>Title</h2>
</Card.Header>
<Card.Body>
<p>Content goes here</p>
</Card.Body>
<Card.Footer>
<button>Action</button>
</Card.Footer>
</Card>

2. Features

  • Support variants: default, bordered, elevated
  • Support sizes: sm, md, lg
  • Optional image at top
  • Flexible content areas
  • TypeScript types

3. Implementation Guidelines

Card.tsx

interface CardProps {
variant?: 'default' | 'bordered' | 'elevated';
size?: 'sm' | 'md' | 'lg';
children: React.ReactNode;
className?: string;
}

// Implement Card and sub-components

Solution Structure

src/
├── components/
│ └── Card/
│ ├── Card.tsx
│ ├── Card.module.css
│ └── index.ts
└── App.tsx

Testing Your Solution

Create example usage in App.tsx:

function App() {
return (
<div className='app'>
<Card variant='elevated' size='md'>
<Card.Image src='/profile.jpg' alt='Profile' />
<Card.Header>
<h2>John Doe</h2>
<p>Software Developer</p>
</Card.Header>
<Card.Body>
<p>Passionate about building great user experiences...</p>
</Card.Body>
<Card.Footer>
<button>View Profile</button>
<button>Message</button>
</Card.Footer>
</Card>
</div>
);
}

Bonus Challenges

  1. Add hover effects
  2. Make the card clickable (entire card as link)
  3. Add a loading state with skeleton
  4. Support horizontal layout
  5. Add close button functionality

Hints

  • Use Context API for sharing variant/size with sub-components
  • Use CSS modules or styled-components for styling
  • Export sub-components as properties: Card.Header, Card.Body, etc.

Time Estimate

2-3 hours