Feature: Lightbox Photo Viewer
Relevant source files
The following files were used as context for generating this wiki page:
The Lightbox is a full-screen, modal-style viewer for photos and videos. It provides a rich, interactive experience, allowing users to navigate through a collection of media, zoom and pan images, watch videos with playback controls, and engage a slideshow mode. It is a central UI component used across various views within the PIXONA application, such as the main Library, Calendar, and Places pages, ensuring a consistent media viewing experience. The component is built with React and leverages framer-motion for smooth animations and transitions.
Sources: src/components/Lightbox.tsx, src/components/PhotoGrid.tsx:28-32
Component Architecture
The Lightbox component is designed to be invoked from other components that display collections of media, such as PhotoGrid. It overlays the entire application when active.
The diagram below illustrates how pages like Library.tsx use PhotoGrid.tsx to display thumbnails, while other pages like Calendar.tsx and Places.tsx invoke the Lightbox.tsx component directly.
This diagram shows the invocation flow for the Lightbox component from various parts of the application.
Sources: src/components/PhotoGrid.tsx:28-32, 69-75, src/pages/Library.tsx:59-64, src/pages/Calendar.tsx:142-147, src/pages/Places.tsx:121-126
Props
The Lightbox component accepts the following props to function:
| Prop Name | Type | Description |
|---|---|---|
media | Media[] | An array of media objects to be displayed. |
initialIndex | number | The index of the media item in the media array to display initially. |
onClose | () => void | A callback function that is executed when the lightbox should be closed. |
| Sources: src/components/Lightbox.tsx:16-20 |
The Media interface defines the structure for each item in the lightbox.
interface Media {
id: string;
url: string;
date: string;
location?: string;
type?: 'photo' | 'video';
}
Sources: src/components/Lightbox.tsx:9-15
Integration
The Lightbox is typically rendered conditionally based on a state variable in the parent component. For example, in PhotoGrid.tsx, it is wrapped in an <AnimatePresence> tag from framer-motion and rendered only when lightboxOpen is true.
// src/components/PhotoGrid.tsx
<AnimatePresence>
{lightboxOpen && (
<Lightbox
media={photos}
initialIndex={lightboxIndex}
onClose={handleLightboxClose}
/>
)}
</AnimatePresence>
Sources: src/components/PhotoGrid.tsx:68-76
State Management
The Lightbox component manages a significant amount of internal state to handle its various features. State is managed using React's useState hook.
| State Variable | Type | Initial Value | Description |
|---|---|---|---|
currentIndex | number | initialIndex | The index of the currently displayed media item. |
zoom | number | 1 | The current zoom level of the image. Min 1, Max 5. |
isPlaying | boolean | false | Tracks if a video is currently playing. |
slideshowActive | boolean | false | Toggles the automatic slideshow mode. |
slideshowDirection | 'forward' | 'backward' | 'forward' | The direction of the slideshow. |
position | { x: number, y: number } | { x: 0, y: 0 } | The X/Y position for panning a zoomed image. |
isDragging | boolean | false | Tracks if the user is currently dragging a zoomed image. |
volume | number | 1 | The volume level for video playback (0 to 1). |
isMuted | boolean | false | Toggles mute for video playback. |
playbackSpeed | number | 1 | The playback speed for videos (e.g., 0.5, 1, 1.5, 2). |
slideshowInterval | number | 3000 | The interval in milliseconds for the slideshow (3s, 5s, 10s). |
transitionType | 'fade' | 'slide' | 'zoom' | 'fade' | The animation type for transitioning between media. |
direction | number | 0 | Used by framer-motion to determine slide direction (1 or -1). |
isFullscreen | boolean | false | Tracks if the component is in browser fullscreen mode. |
showControls | boolean | true | Controls the visibility of UI elements, which auto-hide. |
| Sources: src/components/Lightbox.tsx:29-50 |
Core Functionality & Features
Media Navigation and Transitions
Users can navigate between photos and videos using the left/right arrow buttons or the corresponding keyboard keys. The transition between media is animated using framer-motion. The user can select one of three transition types: fade, slide, or zoom.
// src/components/Lightbox.tsx:23-35
const slideVariants = {
fade: {
enter: { opacity: 0 },
center: { opacity: 1 },
exit: { opacity: 0 }
},
slide: {
enter: (direction: number) => ({ x: direction > 0 ? 1000 : -1000, opacity: 0 }),
center: { x: 0, opacity: 1 },
exit: (direction: number) => ({ x: direction < 0 ? 1000 : -1000, opacity: 0 })
},
zoom: {
enter: { scale: 0.5, opacity: 0 },
center: { scale: 1, opacity: 1 },
exit: { scale: 1.5, opacity: 0 }
}
};
Sources: src/components/Lightbox.tsx:23-35
The handleNext and handlePrevious functions update the currentIndex and reset the zoom and pan position for the new item. They also play a 'click' sound via the soundManager.
Sources: src/components/Lightbox.tsx:128-143
Zoom and Pan
For images, users can zoom in up to 5x and zoom out to the default 1x. When an image is zoomed in (i.e., zoom > 1), it can be panned by clicking and dragging.
- Zooming: Controlled by
handleZoomInandhandleZoomOutfunctions, which are triggered by UI buttons or keyboard shortcuts (+,-,Ctrl/Meta + Mouse Wheel). - Panning: The
isDraggingstate is set totrueononMouseDown. TheonMouseMoveevent then updates thepositionstate to move the image.onMouseUpsetsisDraggingback tofalse.
Sources: src/components/Lightbox.tsx:145-169
Slideshow
The lightbox includes a slideshow feature that automatically cycles through the media.
- Activation: Toggled via a play/pause button or the spacebar.
- Controls: Users can set the interval (3, 5, or 10 seconds) and the direction (forward or backward).
- State: The
slideshowActive,slideshowInterval, andslideshowDirectionstates manage this feature. AuseEffecthook contains thesetIntervallogic that callshandleNextorhandlePrevious.
Sources: src/components/Lightbox.tsx:109-119, 201-206, 474-533
Video Playback
When the current media item is a video, the component displays an HTML5 <video> element with a custom control overlay.
- Standard Controls: The native
controlsattribute is present on the video element. - Custom Overlay Controls:
- Volume: Increase, decrease, and mute functionality.
- Playback Speed: Options for 0.5x, 1x, 1.5x, and 2x speed.
- State Sync: The
videoRefis used to programmatically control the video element, and its state (playing, paused) is synced with theisPlayingReact state.
Sources: src/components/Lightbox.tsx:171-200, 357-433
Fullscreen Mode
The entire lightbox can be toggled into the browser's native fullscreen mode by clicking a button or pressing 'F'. The component listens for the fullscreenchange event to keep its isFullscreen state synchronized.
Sources: src/components/Lightbox.tsx:121-127, 208-221
UI Controls and Auto-Hide
The UI controls (header, footer, navigation arrows) automatically hide after 3 seconds of inactivity when the slideshow is active. Moving the mouse brings them back into view. This is managed by a useEffect hook that sets and clears a setTimeout.
Sources: src/components/Lightbox.tsx:56-74
User Interaction and Event Handling
The component is highly interactive, responding to both mouse and keyboard inputs.
Keyboard Shortcuts
A useEffect hook registers a keydown event listener to provide keyboard shortcuts for common actions.
| Key(s) | Action |
|---|---|
Escape | Exit fullscreen, or close the lightbox. |
ArrowLeft | Go to the previous media item. |
ArrowRight | Go to the next media item. |
Spacebar | Toggle the slideshow play/pause state. |
F or f | Toggle native fullscreen mode. |
+ or = | Zoom in. |
- | Zoom out. |
| Sources: src/components/Lightbox.tsx:77-107 |
Interaction Flow: Next Photo
The following sequence diagram illustrates what happens when a user clicks the "Next" button.
This diagram shows the sequence of function calls and state changes when navigating to the next item.
Sources: src/components/Lightbox.tsx:135-143, 298-307
Event Handler Logic for Keyboard Input
The handleKeyDown function uses a switch statement to route different key presses to the appropriate handler functions.
This flowchart visualizes the logic within the handleKeyDown event listener.
Sources: src/components/Lightbox.tsx:78-106
Conclusion
The Lightbox component is a feature-rich and central part of the PIXONA user experience. It provides a sophisticated and highly interactive interface for viewing photos and videos, complete with animations, keyboard shortcuts, and advanced controls for slideshows and video playback. Its modular design allows it to be easily integrated into any part of the application that needs to display a collection of media in a focused, full-screen view. The use of framer-motion ensures these interactions are fluid and visually appealing.
Sources: src/components/Lightbox.tsx