React Lightbox Component Challenge
Create an accessible and reusable React component that implements a lightbox (also known as a modal or image viewer). This component will allow users to click on an image or a thumbnail and have it display in a larger, overlaying view. This is a common UI pattern for showcasing images in a clean and interactive way.
Problem Description
Your task is to build a Lightbox React component in TypeScript. This component should be able to display an image provided as a prop. When a trigger element (e.g., a thumbnail image) is clicked, the Lightbox should appear, overlaying the current content and displaying the larger image. The lightbox should also provide controls for closing it.
Key Requirements:
- Component Structure: Create a
Lightboxcomponent that accepts animageUrlprop (string) for the image to display and achildrenprop which will act as the trigger to open the lightbox. - Opening the Lightbox: The
Lightboxshould be initially hidden. It should become visible when thechildrenprop (the trigger) is clicked. - Displaying the Image: When visible, the
Lightboxshould display the image specified by theimageUrlprop in a larger format. - Closing the Lightbox: The lightbox must have a clear way to be closed. This could be a close button within the lightbox or clicking outside the image area.
- Styling: The component should have basic styling to appear as a modal overlay. The background should be semi-transparent, and the image should be centered.
- Accessibility: Ensure the component is keyboard accessible. Users should be able to open and close the lightbox using the keyboard (e.g.,
Tabto focus the trigger,EnterorSpaceto open,Escapeto close). The focused element when the lightbox opens should be managed appropriately. - Reusability: The component should be designed to be easily integrated into different parts of an application.
Expected Behavior:
- A clickable element (provided as
children) is rendered. - Clicking this element opens the
Lightbox. - The
Lightboxdisplays a semi-transparent overlay covering the viewport. - The larger image is displayed within the overlay, typically centered.
- A close button or clicking the overlay closes the
Lightbox. - Pressing the
Escapekey closes theLightbox.
Edge Cases:
- What happens if
imageUrlis not provided? (The component should gracefully handle this, perhaps by not rendering or showing a placeholder). - What if the
childrenprop is not a single clickable element? (Focus on the most common use case wherechildrenis a single image or link).
Examples
Example 1: Basic Usage
// Parent Component
function App() {
const imageUrl = "https://via.placeholder.com/800x600.png?text=Large+Image";
return (
<div>
<h1>My Gallery</h1>
<Lightbox imageUrl={imageUrl}>
<img
src="https://via.placeholder.com/150x100.png?text=Thumbnail+1"
alt="Thumbnail 1"
style={{ cursor: 'pointer' }}
/>
</Lightbox>
<Lightbox imageUrl={imageUrl}>
<button>Open Image</button>
</Lightbox>
</div>
);
}
Expected Output (Visual):
Initially, you see "My Gallery" followed by a thumbnail image and a button. Clicking either the thumbnail or the button will open the lightbox.
Lightbox Open State Visual:
The entire screen is covered by a semi-transparent dark overlay. In the center, a large image (800x600 placeholder) is displayed. A small "X" icon in the corner of the overlay allows closing.
Explanation:
The Lightbox component wraps a trigger element (img or button). When the trigger is clicked, the Lightbox component manages its own visibility state, rendering the overlay and the larger image.
Example 2: Handling No Image URL
// Parent Component
function App() {
return (
<div>
<h1>My Gallery</h1>
<Lightbox imageUrl="">
<img
src="https://via.placeholder.com/150x100.png?text=Broken+Link+Thumbnail"
alt="Broken Link Thumbnail"
style={{ cursor: 'pointer' }}
/>
</Lightbox>
</div>
);
}
Expected Behavior:
Clicking the thumbnail should not open the lightbox, or it should open but display a placeholder or an error message within the lightbox, as no valid imageUrl is provided.
Explanation:
The Lightbox component should detect that imageUrl is an empty string and prevent itself from fully rendering the image display, or render a fallback.
Constraints
- The solution must be implemented in React using TypeScript.
- State management for the lightbox's open/closed status should be handled within the
Lightboxcomponent itself. - The overlay styling should be a fixed position with a high
z-indexto ensure it's on top of other content. - The close button should be visually distinct and easily clickable.
- Keyboard navigation (focus management,
Escapekey) is a critical requirement.
Notes
- Consider using React's
useStatehook for managing the open/closed state of the lightbox. - You will likely need CSS (or a CSS-in-JS solution) to style the overlay and the image.
- For accessibility, ensure that focus is trapped within the lightbox when it's open and returned to the trigger element when closed.
- Think about how to prevent scrolling of the background content when the lightbox is open.
- You might want to add an
altattribute to the displayed image within the lightbox for better accessibility.