6.6 KiB
Component Guide - Dish Planner
This guide documents the standardized UI components in the Dish Planner application. All components use Tailwind CSS with our custom color variables from the design system.
Design System
Colors
Our color palette is defined in src/styles/theme/colors/root.css and integrated into Tailwind via tailwind.config.ts:
- Primary (Rose):
bg-primary,text-primary,border-primarywith shades 50-950 - Secondary (Deluge):
bg-secondary,text-secondary,border-secondarywith shades 50-950 - Accent (Malibu Blue):
bg-accent,text-accent,border-accentwith shades 50-950 - Yellow (Gamboge):
bg-yellow,text-yellow,border-yellowwith shades 50-950 - Gray (Ebony Clay):
bg-gray,text-gray,border-graywith shades 100-950 - Semantic Colors:
- Danger (Alizarin Crimson):
bg-danger,text-danger,border-danger - Success (Spring Green):
bg-success,text-success,border-success - Warning (Burning Orange):
bg-warning,text-warning,border-warning
- Danger (Alizarin Crimson):
Components
Button (src/components/ui/Button.tsx)
Unified button component supporting multiple variants, appearances, and states.
Props
interface ButtonProps {
appearance?: 'solid' | 'outline' | 'text'; // Default: 'solid'
variant?: 'primary' | 'secondary' | 'accent' | 'danger'; // Default: 'primary'
size?: 'small' | 'medium' | 'large'; // Default: 'medium'
type?: 'button' | 'submit' | 'reset'; // Default: 'button'
href?: string; // For link buttons
icon?: ReactNode;
disabled?: boolean;
onClick?: () => void;
className?: string;
children: ReactNode;
}
Examples
// Solid primary button
<Button variant="primary" appearance="solid">
Save
</Button>
// Outline accent button with icon
<Button variant="accent" appearance="outline" icon={<PlusIcon />}>
Add Item
</Button>
// Text danger button
<Button variant="danger" appearance="text" size="small">
Delete
</Button>
// Link button
<Button href="/dishes" appearance="outline" icon={<ChevronLeftIcon />}>
Back to Dishes
</Button>
Input (src/components/ui/Input.tsx)
Standardized text input component with label, error, and helper text support.
Props
interface InputProps extends InputHTMLAttributes<HTMLInputElement> {
label?: string;
error?: string;
helperText?: string;
fullWidth?: boolean; // Default: true
}
Examples
// Basic input with label
<Input
label="Email"
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
required
/>
// Input with error
<Input
label="Name"
value={name}
error="Name is required"
/>
// Input with helper text
<Input
label="Password"
type="password"
helperText="Must be at least 8 characters"
/>
Select (src/components/ui/Select.tsx)
Standardized select dropdown component.
Props
interface SelectProps extends SelectHTMLAttributes<HTMLSelectElement> {
label?: string;
error?: string;
helperText?: string;
fullWidth?: boolean; // Default: true
options: Array<{ value: string | number; label: string }>;
}
Example
<Select
label="Recurrence"
value={recurrence}
onChange={(e) => setRecurrence(e.target.value)}
options={[
{ value: 7, label: 'Weekly' },
{ value: 30, label: 'Monthly' },
{ value: 365, label: 'Yearly' }
]}
/>
Checkbox (src/components/ui/Checkbox.tsx)
Standardized checkbox component with label support.
Props
interface CheckboxProps extends InputHTMLAttributes<HTMLInputElement> {
label?: string;
error?: string;
helperText?: string;
}
Example
<Checkbox
label="Enable notifications"
checked={enabled}
onChange={(e) => setEnabled(e.target.checked)}
/>
Toggle (src/components/ui/Toggle.tsx)
Enhanced toggle switch component.
Props
interface ToggleProps {
checked: boolean;
onChange: (checked: boolean) => void;
label?: string;
disabled?: boolean;
helperText?: string;
}
Example
<Toggle
checked={isActive}
onChange={setIsActive}
label="Active"
helperText="Enable this feature"
/>
Alert (src/components/ui/Alert.tsx)
Standardized alert component for displaying messages.
Props
interface AlertProps {
type: 'error' | 'warning' | 'info' | 'success';
children: ReactNode;
className?: string;
}
Examples
// Error alert
<Alert type="error">
An error occurred while saving.
</Alert>
// Success alert
<Alert type="success">
User created successfully!
</Alert>
// Warning alert
<Alert type="warning">
This action cannot be undone.
</Alert>
Card (src/components/layout/Card.tsx)
Standardized card container component.
Props
interface CardProps {
children: ReactNode;
className?: string;
}
Example
<Card>
<div className="flex-grow">
<h3>User Name</h3>
</div>
<div className="flex gap-2">
<Button size="small">Edit</Button>
<Button size="small" variant="danger">Delete</Button>
</div>
</Card>
Migration Guide
From Old Button Components
The old button components have been removed. Use the unified Button component instead:
SolidButton→Buttonwithappearance="solid"OutlineButton→Buttonwithappearance="outline"SolidLinkButton→Buttonwithappearance="solid"andhrefpropOutlineLinkButton→Buttonwithappearance="outline"andhrefprop
Custom CSS Classes to Tailwind
Replace custom CSS classes with Tailwind utilities:
background-red→bg-primarybackground-secondary→bg-secondaryfont-size-18→text-lgtext-accent-blue→text-accentborder-accent→border-accent
Best Practices
- Use semantic color names: Prefer
text-primary,bg-dangerover hardcoded colors - Consistent spacing: Use Tailwind's spacing scale (p-2, p-4, etc.)
- Responsive design: Consider mobile-first responsive classes
- Accessibility: Use proper ARIA attributes and semantic HTML
- Component reusability: Always use the standardized components instead of creating custom styled elements
Future Enhancements
Potential areas for further improvement:
- Migrate remaining inline-styled inputs to use the
Inputcomponent - Add dark mode support
- Create compound components for common patterns (e.g., FormGroup)
- Add animation utilities for better UX
- Implement a comprehensive form validation system