16 KiB
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:
interface Props {
galleryHeading: string // Page title
translations: object // Internationalization strings
}
State Management:
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:
- Sends style change request to backend
- Receives
prompt_idandplugintype - Establishes appropriate progress monitoring (WebSocket vs Polling)
- Updates UI with real-time progress
- 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:
interface Props {
images: Image[] // Array of image objects to display
translations: object // UI text translations
}
Events:
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:
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:
interface Props {
position: { x: number, y: number } // Menu position coordinates
image: Image // Selected image object
}
Events:
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:
interface Props {
image_id: number // Target image for styling
}
Events:
interface Events {
styleSelected: [style: Style, imageId: number] // Style chosen
back: [] // Return to context menu
close: [] // Close selector
}
State Management:
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
styleSelectedevent 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:
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:
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:
interface Props {
image: Image // Styled image object
}
Events:
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:
interface Props {
currentPage: number // Current active page
totalPages: number // Total available pages
}
Events:
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:
interface Props {
maxCopies: number // Maximum allowed copies
}
Events:
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)
// 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)
// 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
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