Description
Create a reusable Button component to reduce code duplication across the application.
Problem
Button styling and logic is duplicated across multiple components. This leads to:
- Inconsistent button styles
- Duplicated code
- Harder maintenance
- Inconsistent accessibility
Solution
Create a shared Button component with variants.
Files to Create
src/components/ui/button/index.tsx
src/components/ui/button/button.module.css (or use Tailwind)
Suggested Implementation
import React from 'react';
export interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
variant?: 'primary' | 'secondary' | 'outline' | 'ghost' | 'danger';
size?: 'sm' | 'md' | 'lg';
isLoading?: boolean;
fullWidth?: boolean;
children: React.ReactNode;
}
export const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
(
{
variant = 'primary',
size = 'md',
isLoading = false,
fullWidth = false,
disabled,
className = '',
children,
...props
},
ref
) => {
const baseClasses = 'tw-font-medium tw-rounded tw-transition-colors';
const variantClasses = {
primary: 'tw-bg-blue-600 tw-text-white hover:tw-bg-blue-700',
secondary: 'tw-bg-gray-600 tw-text-white hover:tw-bg-gray-700',
outline: 'tw-border-2 tw-border-gray-600 tw-text-gray-600 hover:tw-bg-gray-50',
ghost: 'tw-text-gray-600 hover:tw-bg-gray-100',
danger: 'tw-bg-red-600 tw-text-white hover:tw-bg-red-700'
};
const sizeClasses = {
sm: 'tw-px-3 tw-py-1.5 tw-text-sm',
md: 'tw-px-4 tw-py-2 tw-text-base',
lg: 'tw-px-6 tw-py-3 tw-text-lg'
};
const classes = `
${baseClasses}
${variantClasses[variant]}
${sizeClasses[size]}
${fullWidth ? 'tw-w-full' : ''}
${(disabled || isLoading) ? 'tw-opacity-50 tw-cursor-not-allowed' : ''}
${className}
`.trim().replace(/\s+/g, ' ');
return (
<button
ref={ref}
className={classes}
disabled={disabled || isLoading}
{...props}
>
{isLoading ? (
<>
<span className="tw-mr-2">Loading...</span>
{children}
</>
) : (
children
)}
</button>
);
}
);
Button.displayName = 'Button';
Usage Examples
// Primary button
<Button variant="primary" onClick={handleClick}>
Submit
</Button>
// Loading state
<Button variant="primary" isLoading>
Submitting...
</Button>
// Full width
<Button variant="primary" fullWidth>
Sign Up
</Button>
// Danger action
<Button variant="danger" onClick={handleDelete}>
Delete Account
</Button>
Tasks
Learning Outcomes
- Understanding component composition
- Learning about React.forwardRef
- Practice with TypeScript generics
- Understanding design systems
- Learning about component variants
Estimated Time
2-3 hours
Priority
Medium - Reduces code duplication
Difficulty
Intermediate
Description
Create a reusable Button component to reduce code duplication across the application.
Problem
Button styling and logic is duplicated across multiple components. This leads to:
Solution
Create a shared Button component with variants.
Files to Create
src/components/ui/button/index.tsxsrc/components/ui/button/button.module.css(or use Tailwind)Suggested Implementation
Usage Examples
Tasks
src/components/ui/index.tsLearning Outcomes
Estimated Time
2-3 hours
Priority
Medium - Reduces code duplication
Difficulty
Intermediate