Component Creation & Props
Lab Overview
In this lab, you will create a set of reusable UI components for your company’s internal component library. You will practice creating TypeScript React components with proper prop typing, component composition, and prop handling. This lab focuses on component creation, TypeScript interfaces, prop handling, and component composition using React and TypeScript.
Workplace Context
Imagine you are a frontend developer tasked with building a component library for your company’s internal applications. Your team needs a set of reusable, type-safe components that can be easily configured for different use cases. These components will be used across multiple applications, so they need to be well-documented, properly typed, and flexible enough to handle various scenarios.
This lab will help you practice building the foundational components that will be used throughout your company’s applications.
Objectives
By the end of this lab, you will:
- Create reusable React components with TypeScript interfaces for props.
- Implement proper prop handling and validation.
- Use component composition effectively.
- Apply TypeScript best practices for component development.
- Document components with clear prop interfaces.
Instructions
Setup the Project
- Create a new React TypeScript project using Vite:
npm create vite@latest component-library -- --template react-ts
cd component-library
npm install
- Create the following folder structure:
src/
components/
AlertBox/
AlertBox.tsx
AlertBox.test.tsx
UserProfileCard/
UserProfileCard.tsx
UserProfileCard.test.tsx
ProductDisplay/
ProductDisplay.tsx
ProductDisplay.test.tsx
types/
index.ts
Component Requirements
1. AlertBox Component
Create an AlertBox
component that can display different types of alerts (success, error, warning, info) with customizable messages.
// types/index.ts
export type AlertType = 'success' | 'error' | 'warning' | 'info';
export interface AlertBoxProps {
type: AlertType;
message: string;
onClose?: () => void;
children?: React.ReactNode;
}
2. UserProfileCard Component
Create a UserProfileCard
component that displays user information with optional sections.
// types/index.ts
export interface User {
id: string;
name: string;
email: string;
role: string;
avatarUrl?: string;
}
export interface UserProfileCardProps {
user: User;
showEmail?: boolean;
showRole?: boolean;
onEdit?: (userId: string) => void;
children?: React.ReactNode;
}
3. ProductDisplay Component
Create a ProductDisplay
component that shows product information with configurable display options.
// types/index.ts
export interface Product {
id: string;
name: string;
price: number;
description: string;
imageUrl?: string;
inStock: boolean;
}
export interface ProductDisplayProps {
product: Product;
showDescription?: boolean;
showStockStatus?: boolean;
onAddToCart?: (productId: string) => void;
children?: React.ReactNode;
}
Activity Tasks
-
Component Implementation:
- Implement each component according to its interface requirements.
- Use proper TypeScript types and interfaces.
- Implement prop validation where appropriate.
- Handle optional props and children correctly.
-
Component Testing:
- Test different prop combinations.
- Verify that components render correctly with various props.
-
Component Composition:
- Create example usage of components working together.
- Demonstrate prop passing between components.
- Show how to handle component nesting.
-
Documentation:
- Add comments to describe component props.
- Create example usage documentation.
- Document any special prop handling or requirements.
Example Implementation
Here’s a starting point for the AlertBox component, using Tailwind CSS classes for styling:
// components/AlertBox/AlertBox.tsx
import React from 'react';
import { AlertBoxProps } from '../../types';
export const AlertBox: React.FC<AlertBoxProps> = ({
type,
message,
onClose,
children
}) => {
const alertStyles = {
success: 'bg-green-100 border-green-500 text-green-700',
error: 'bg-red-100 border-red-500 text-red-700',
warning: 'bg-yellow-100 border-yellow-500 text-yellow-700',
info: 'bg-blue-100 border-blue-500 text-blue-700'
};
return (
<div className={`p-4 border-l-4 ${alertStyles[type]}`}>
<div className="flex justify-between items-center">
<p>{message}</p>
{onClose && (
<button
onClick={onClose}
className="ml-4 text-gray-500 hover:text-gray-700"
>
×
</button>
)}
</div>
{children}
</div>
);
};
Example Usage
Here are examples of how to use each component, and an example of the result:
AlertBox Example
<AlertBox
type="success"
message="Your profile has been updated successfully!"
onClose={() => alert('Alert closed')}
>
<p className="text-sm">You can now continue using the application.</p>
</AlertBox>
Your profile has been updated successfully!
You can now continue using the application.
UserProfileCard Example
const user = {
id: '1',
name: 'John Doe',
email: 'john.doe@example.com',
role: 'Software Engineer',
avatarUrl: 'https://example.com/avatar.jpg'
};
<UserProfileCard
user={user}
showEmail={true}
showRole={true}
onEdit={(userId) => alert(`Editing user ${userId}`)}
>
<div className="text-sm text-gray-500">
Last login: 2 hours ago
</div>
</UserProfileCard>
John Doe
john.doe@example.com
Software Engineer
ProductDisplay Example
const product = {
id: '1',
name: 'Wireless Headphones',
price: 199.99,
description: 'High-quality wireless headphones with noise cancellation.',
imageUrl: 'https://example.com/headphones.jpg',
inStock: true
};
<ProductDisplay
product={product}
showDescription={true}
showStockStatus={true}
onAddToCart={(productId) => alert(`Added product ${productId} to cart`)}
>
<div className="text-sm text-gray-500">
Free shipping available
</div>
</ProductDisplay>

Wireless Headphones
$199.99
High-quality wireless headphones with noise cancellation.
In Stock
Component Composition Example
Here’s how these components could work together:
const App = () => {
const [showAlert, setShowAlert] = useState(false);
const [cartItems, setCartItems] = useState<string[]>([]);
const handleAddToCart = (productId: string) => {
setCartItems([...cartItems, productId]);
setShowAlert(true);
};
return (
<div className="p-4">
{showAlert && (
<AlertBox
type="success"
message="Product added to cart!"
onClose={() => setShowAlert(false)}
/>
)}
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 mt-4">
<UserProfileCard
user={user}
showEmail={true}
showRole={true}
/>
<ProductDisplay
product={product}
showDescription={true}
showStockStatus={true}
onAddToCart={handleAddToCart}
/>
</div>
</div>
);
};
Reflection Questions
- How did you handle optional props in your components?
- What considerations did you make when designing the component interfaces?
- How did you ensure type safety across your components?
- What challenges did you face when implementing component composition?
Submission
Submit your project via a GitHub repository using the Start Assignment link on Canvas. Your submission should include:
- All component implementations
- TypeScript interfaces
- Example usage documentation
- A README.md file explaining how to use the components
Grading Criteria
Your submission will be evaluated on a complete/incomplete basis based on the following criteria:
Criteria | Complete (10 pts) | Incomplete (0 pts) | Points |
---|---|---|---|
All Required Deliverables Submitted The learner has provided all files, documentation, or other artifacts specified in the assignment instructions (e.g., source code, README, diagrams). | No key component is missing. The assignment can be reviewed and run/tested (if applicable) with the provided materials. | Missing key files or deliverables (cannot compile/run, cannot review the work). | 10 |
Essential Requirements Fulfilled The core functionality or goals of the assignment are clearly and sufficiently addressed. | All main tasks or features explicitly stated in the prompt are at least partially implemented. The solution is runnable or reviewable without major, blocking errors. Any primary outputs match what is expected or are reasonably close to the stated requirements. | Main functionalities not attempted or severely broken. | 10 |
Evidence of Original Work The assignment must reflect the learner’s own effort, and any external resources used are properly cited. | No obvious evidence of plagiarism (e.g., copied code without citation). Any references to libraries, tutorials, or other external sources are credited in a README or comments. | Significant plagiarism or uncredited copying of solutions. | 10 |
Total Points: 30