# Frontend Components Specification ## Architecture Overview Single Page Application built with Vue.js 3 and Inertia.js, providing a responsive image gallery interface with real-time AI processing capabilities. ## Technology Stack - **Framework**: Vue.js 3.5.18 with Composition API - **Routing**: Inertia.js 1.3.0 (Laravel backend integration) - **Build Tool**: Vite 5.4.19 - **Styling**: Tailwind CSS 3.4.17 - **HTTP Client**: Axios 1.11.0 - **State Management**: Vue 3 Composition API (ref, computed, reactive) - **Real-time**: WebSocket for ComfyUI progress, polling for other providers ## Component Hierarchy ``` App.vue (Root) └── Home.vue (Main Gallery Page) ├── GalleryGrid.vue (Image Grid Display) ├── Navigation.vue (Pagination Controls) ├── ImageContextMenu.vue (Image Actions Overlay) │ └── StyleSelector.vue (Style Selection Interface) ├── StyledImageDisplay.vue (Result Preview) ├── LoadingSpinner.vue (Progress Indicator) └── PrintQuantityModal.vue (Print Options) ``` ## Component Specifications ### 1. Home.vue (Main Gallery Page) **Purpose**: Primary interface displaying user's image gallery with pagination and overlay management **Location**: `resources/js/Pages/Home.vue` **Props**: ```typescript interface Props { galleryHeading: string // Page title translations: object // Internationalization strings } ``` **State Management**: ```typescript const images = ref([]) // Gallery images array const currentPage = ref(1) // Current pagination page const currentOverlayComponent = ref(null) // Active overlay ('contextMenu', 'styleSelector', etc.) const contextMenuPosition = ref({ x: 0, y: 0 }) // Context menu coordinates const selectedImage = ref(null) // Currently selected image const styledImage = ref(null) // Newly processed styled image const processingProgress = ref(0) // AI processing progress (0-100) const errorMessage = ref(null) // Error display state const isLoading = ref(false) // Global loading state const currentTheme = ref('light') // UI theme preference ``` **Key Methods**: #### `fetchImages()` - **Purpose**: Retrieves and synchronizes gallery images - **Implementation**: Axios GET to `/api/images` - **Auto-refresh**: Polls every 5 seconds (configurable interval) - **Error Handling**: Displays user-friendly error messages #### `applyStyle(style, imageId)` - **Purpose**: Initiates AI style transformation process - **Flow**: 1. Sends style change request to backend 2. Receives `prompt_id` and `plugin` type 3. Establishes appropriate progress monitoring (WebSocket vs Polling) 4. Updates UI with real-time progress 5. Displays result when complete #### `showContextMenu(image, event)` - **Purpose**: Displays context menu for selected image - **Positioning**: Calculates optimal position based on click coordinates - **Responsive**: Adapts to screen boundaries **UI Structure**: - **Header**: Title and theme toggle - **Gallery**: Grid layout with pagination - **Overlays**: Conditional rendering based on `currentOverlayComponent` - **Notifications**: Error messages with auto-dismiss **Styling**: - **Layout**: Flexbox-based responsive design - **Theme**: Light/dark mode support with CSS variables - **Responsive**: Mobile-first approach with touch gestures --- ### 2. GalleryGrid.vue **Purpose**: Displays images in responsive grid layout with interaction handling **Props**: ```typescript interface Props { images: Image[] // Array of image objects to display translations: object // UI text translations } ``` **Events**: ```typescript interface Events { imageTapped: [image: Image, event: MouseEvent] // Image selection } ``` **Features**: - **Responsive Grid**: Adaptive columns based on screen size - **Lazy Loading**: Images load as they enter viewport - **Touch Support**: Tap gestures for mobile devices - **Accessibility**: Proper alt text and keyboard navigation **Image Object Structure**: ```typescript interface Image { image_id: number path: string // URL to image file name: string // Filename is_temp: boolean // Temporary styled image flag is_public: boolean // Visibility status is_new: boolean // Recently uploaded flag } ``` --- ### 3. ImageContextMenu.vue **Purpose**: Contextual action menu displayed when user taps/clicks an image **Location**: `resources/js/Components/ImageContextMenu.vue` **Props**: ```typescript interface Props { position: { x: number, y: number } // Menu position coordinates image: Image // Selected image object } ``` **Events**: ```typescript interface Events { close: [] // Close menu print: [image: Image] // Print image changeStyle: [] // Open style selector styleSelected: [style: Style, imageId: number] // Style applied } ``` **Layout Structure**: ``` ┌─────────────────────────────────────────────────┐ │ [X] Close [Image Preview] │ │ │ │ ┌─────────────────────────────────────────────┐ │ │ │ ▲ │ │ │ │ Image Preview │ │ │ │ ▼ │ │ │ │ (70% width) │ │ │ └─────────────────────────────────────────────┘ │ │ ┌─────────────────────────────────────────────┐ │ │ │ [Print] [Change Style] [Close] │ │ │ │ (30% width) │ │ │ └─────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────┘ ``` **Features**: - **Dynamic Positioning**: Calculates optimal position to stay within viewport - **Backdrop Click**: Closes menu when clicking outside - **Nested Components**: Embeds StyleSelector when needed - **Responsive**: Adapts layout for different screen sizes **Styling**: - **Overlay**: Semi-transparent backdrop with blur effect - **Menu**: Elevated card with shadow and rounded corners - **Responsive**: Touch-friendly button sizes on mobile --- ### 4. StyleSelector.vue **Purpose**: Allows users to browse and select AI styles for image transformation **Props**: ```typescript interface Props { image_id: number // Target image for styling } ``` **Events**: ```typescript interface Events { styleSelected: [style: Style, imageId: number] // Style chosen back: [] // Return to context menu close: [] // Close selector } ``` **State Management**: ```typescript const styles = ref([]) // Available styles array // Lazy loading management const observer = ref(null) // IntersectionObserver instance ``` **Key Methods**: #### `fetchStyles()` - **Purpose**: Retrieves available styles from API - **Implementation**: Axios GET to `/api/styles` - **Filtering**: Only enabled styles returned - **Lazy Loading**: Sets up IntersectionObserver for preview images #### `selectStyle(style)` - **Purpose**: Confirms style selection and triggers processing - **Implementation**: Emits `styleSelected` event with style and image ID **UI Structure**: ``` ┌─────────────────────────────────────────────────┐ │ [<] Back Available Styles │ ├─────────────────────────────────────────────────┤ │ ┌─────────────────────────────────────────────┐ │ │ │ [Preview] Style Name [Description] │ │ │ │ [Preview] Another Style [Description] │ │ │ │ [Preview] Third Style [Description] │ │ │ └─────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────┘ ``` **Features**: - **Preview Images**: Thumbnail images for each style - **Lazy Loading**: Images load when entering viewport - **Back Navigation**: Return to previous context menu - **Responsive**: Scrollable list on smaller screens **Style Object Structure**: ```typescript interface Style { id: number title: string // Display name description: string // Human-readable description preview_image: string // Thumbnail image path enabled: boolean // Availability status } ``` --- ### 5. LoadingSpinner.vue **Purpose**: Visual indicator for AI processing progress **Props**: ```typescript interface Props { progress: number // Progress percentage (0-100) } ``` **Features**: - **Progress Bar**: Visual representation of completion status - **Animated**: Smooth progress updates - **Responsive**: Adapts to different screen sizes - **Accessible**: Screen reader compatible **Styling**: - **Modern Design**: Gradient progress bar with smooth animations - **Centered**: Overlay positioning for full-screen processes - **Theme Aware**: Adapts to light/dark theme --- ### 6. StyledImageDisplay.vue **Purpose**: Preview and management interface for completed AI-styled images **Props**: ```typescript interface Props { image: Image // Styled image object } ``` **Events**: ```typescript interface Events { keep: [image: Image] // Keep styled image permanently delete: [image: Image] // Discard styled image } ``` **Features**: - **Full Preview**: Large display of styled result - **Action Buttons**: Keep/Discard options - **Responsive**: Mobile-optimized layout - **Loading State**: Handles image loading gracefully --- ### 7. Navigation.vue **Purpose**: Pagination controls for gallery navigation **Props**: ```typescript interface Props { currentPage: number // Current active page totalPages: number // Total available pages } ``` **Events**: ```typescript interface Events { prevPage: [] // Navigate to previous page nextPage: [] // Navigate to next page } ``` **Features**: - **Page Numbers**: Visual page indicators - **Touch Gestures**: Swipe left/right for page navigation - **Responsive**: Touch-friendly on mobile devices - **Keyboard**: Arrow key navigation support --- ### 8. PrintQuantityModal.vue **Purpose**: Print options interface for physical image printing **Props**: ```typescript interface Props { maxCopies: number // Maximum allowed copies } ``` **Events**: ```typescript interface Events { close: [] // Close modal printConfirmed: [quantity: number] // Print confirmed } ``` **Features**: - **Quantity Selection**: Number input for copy count - **Validation**: Enforces maximum copy limits - **Confirmation**: Clear confirmation before printing - **Responsive**: Modal overlay with backdrop ## Component Interactions ### Image Selection Flow ``` User taps image → GalleryGrid emits imageTapped → Home.vue shows contextMenu at tap position → ImageContextMenu displays with image preview and options ``` ### Style Application Flow ``` User selects "Change Style" → ImageContextMenu shows StyleSelector → User browses and selects style → StyleSelector emits styleSelected → Home.vue initiates AI processing with progress monitoring → Real-time updates via WebSocket/Polling → Result displayed → User can keep or discard styled image ``` ### Progress Monitoring #### ComfyUI (WebSocket) ```typescript // Establish WebSocket connection const wsUrl = `ws://${comfyUiHost}/ws` const ws = new WebSocket(wsUrl) // Monitor progress messages ws.onmessage = (event) => { const message = JSON.parse(event.data) if (message.type === 'progress' && message.data.prompt_id === currentPromptId) { processingProgress.value = (message.data.value / message.data.max) * 100 } } ``` #### Other Providers (Polling) ```typescript // Poll for completion every 2 seconds const pollForResult = () => { axios.get(`/api/images/fetch-styled/${promptId}`) .then(response => { // Success - display result styledImage.value = response.data.styled_image currentOverlayComponent.value = 'styledImageDisplay' }) .catch(error => { if (error.response?.status === 404) { // Still processing - continue polling setTimeout(pollForResult, 2000) } else { // Error - display message showError(error.response?.data?.error) } }) } ``` ## State Management Patterns ### Overlay Management - Single active overlay at a time - Stack-based navigation (context menu → style selector → back) - Proper cleanup on component unmount ### Error Handling - Centralized error display with auto-dismiss - User-friendly error messages - Graceful degradation for failed operations ### Theme Management - Persistent theme preference in localStorage - CSS variable-based theming - System preference detection ## Responsive Design ### Breakpoints - **Mobile**: < 768px (single column, touch-optimized) - **Tablet**: 768px - 1024px (2-3 columns, hybrid interaction) - **Desktop**: > 1024px (4+ columns, mouse-optimized) ### Touch Interactions - **Tap**: Image selection and button activation - **Swipe**: Gallery navigation (left/right) - **Long Press**: Context menu (mobile equivalent of right-click) - **Pinch**: Zoom functionality (future enhancement) ## Accessibility Features ### ARIA Support - Proper semantic HTML structure - ARIA labels for interactive elements - Screen reader announcements for dynamic content ### Keyboard Navigation - Tab order for all interactive elements - Enter/Space for button activation - Escape key for modal dismissal - Arrow keys for gallery navigation ### Visual Accessibility - High contrast mode support - Sufficient color contrast ratios - Scalable text and UI elements - Reduced motion preferences ## Performance Optimizations ### Image Loading - **Lazy Loading**: IntersectionObserver for viewport detection - **Progressive Loading**: Blur placeholder → low quality → high quality - **Caching**: Browser cache for static assets - **Compression**: Optimized image formats (WebP support) ### Component Optimization - **Conditional Rendering**: Only render active overlays - **Event Delegation**: Efficient event handling for large galleries - **Memoization**: Computed properties for expensive operations - **Code Splitting**: Component-based lazy loading ## Internationalization ### Translation Structure ```typescript interface Translations { api: { dark_mode: string light_mode: string close: string print: string change_style: string } } ``` ### Implementation - Laravel backend provides translations - Vue components use translation keys - Runtime language switching support ## Future Enhancement Opportunities ### Component Additions - **ImageEditor.vue**: Basic image editing tools - **BatchProcessor.vue**: Multi-image style application - **GalleryFilters.vue**: Search and filter functionality - **UserProfile.vue**: User settings and preferences - **AdminDashboard.vue**: Administrative controls ### Feature Enhancements - **Drag & Drop**: Upload images via drag-and-drop - **Keyboard Shortcuts**: Power user productivity features - **Offline Support**: PWA capabilities for offline viewing - **Social Features**: Share and discover styled images - **Advanced Progress**: Detailed processing stage information ### Technical Improvements - **Virtual Scrolling**: Handle very large galleries efficiently - **Service Workers**: Background processing and caching - **WebAssembly**: Client-side image processing - **Real-time Collaboration**: Multiple users styling same image