# ADR-012: Frontend Component Library and Design System **Date**: 2025-12-12 **Status**: Partially Implemented ## Context The frontend is built with React, but there is no formal strategy for component reuse, styling consistency, or UI documentation. As more features are added, this can lead to a fragmented user experience, duplicated effort, and a codebase that is difficult to maintain. ## Decision We will establish a formal Design System and Component Library. This will involve using a tool like **Storybook** to develop, document, and test UI components in isolation. It will establish clear guidelines for styling, theming (e.g., dark mode), and accessibility. ## Consequences - **Positive**: Ensures a consistent and high-quality user interface. Accelerates frontend development by providing reusable, well-documented components. Improves maintainability and reduces technical debt. - **Negative**: Requires an initial investment in setting up Storybook and migrating existing components. Adds a new dependency and a new workflow for frontend development. ## Implementation Status ### What's Implemented The codebase has a solid foundation for a design system: - ✅ **Tailwind CSS v4.1.17** as the styling solution - ✅ **Dark mode** fully implemented with system preference detection - ✅ **55 custom icon components** for consistent iconography - ✅ **Component organization** with shared vs. feature-specific separation - ✅ **Accessibility patterns** with ARIA attributes and focus management ### What's Not Yet Implemented - ❌ **Storybook** is not yet installed or configured - ❌ **Formal design token documentation** (colors, typography, spacing) - ❌ **Visual regression testing** for component changes ## Implementation Details ### Component Library Structure ```text src/ ├── components/ # 30+ shared UI components │ ├── icons/ # 55 SVG icon components │ ├── Header.tsx │ ├── Footer.tsx │ ├── LoadingSpinner.tsx │ ├── ErrorDisplay.tsx │ ├── ConfirmationModal.tsx │ ├── DarkModeToggle.tsx │ ├── StatCard.tsx │ ├── PasswordInput.tsx │ └── ... ├── features/ # Feature-specific components │ ├── charts/ # PriceChart, PriceHistoryChart │ ├── flyer/ # FlyerDisplay, FlyerList, FlyerUploader │ ├── shopping/ # ShoppingListComponent, WatchedItemsList │ └── voice-assistant/ # VoiceAssistant ├── layouts/ # Page layouts │ └── MainLayout.tsx ├── pages/ # Page components │ └── admin/components/ # Admin-specific components └── providers/ # Context providers ``` ### Styling Approach **Tailwind CSS** with utility-first classes: ```typescript // Component example with consistent styling patterns ``` **Common Utility Patterns**: | Pattern | Classes | | ------- | ------- | | Card container | `bg-white dark:bg-gray-800 rounded-lg shadow-md p-6` | | Primary button | `bg-brand-primary hover:bg-brand-dark text-white rounded-lg px-4 py-2` | | Secondary button | `bg-gray-100 dark:bg-gray-700 text-gray-700 dark:text-gray-200` | | Input field | `border border-gray-300 dark:border-gray-600 rounded-md px-3 py-2` | | Focus ring | `focus:outline-none focus:ring-2 focus:ring-brand-primary` | ### Color System **Brand Colors** (Tailwind theme extensions): - `brand-primary` - Primary brand color (blue/teal) - `brand-light` - Lighter variant - `brand-dark` - Darker variant for hover states - `brand-secondary` - Secondary accent color **Semantic Colors**: - Gray scale: `gray-50` through `gray-950` - Error: `red-500`, `red-600` - Success: `green-500`, `green-600` - Warning: `yellow-500`, `orange-500` - Info: `blue-500`, `blue-600` ### Dark Mode Implementation Dark mode is fully implemented using Tailwind's `dark:` variant: ```typescript // Initialization in useAppInitialization hook const initializeDarkMode = () => { // Priority: user profile > localStorage > system preference const stored = localStorage.getItem('darkMode'); const systemPreference = window.matchMedia('(prefers-color-scheme: dark)').matches; const isDarkMode = stored ? stored === 'true' : systemPreference; document.documentElement.classList.toggle('dark', isDarkMode); return isDarkMode; }; ``` **Usage in components**: ```typescript