React Lightbox Component with TypeScript
This challenge asks you to build a reusable lightbox component in React using TypeScript. A lightbox is a modal window that displays an image or other content in a larger format, often used to provide a better viewing experience or showcase details. This component will be useful for displaying product images, gallery photos, or any other content that benefits from a focused, full-screen presentation.
Problem Description
You need to create a Lightbox component that displays an image (or potentially other content in the future) in a darkened overlay. The component should accept an image URL as a prop and provide functionality to close the lightbox. The lightbox should:
- Display an Image: Render the image provided via the
imageUrlprop. - Overlay: Cover the entire screen with a semi-transparent dark overlay when open.
- Close Button: Include a clear "Close" button (or an 'X' icon) to dismiss the lightbox.
- State Management: Use React state to control whether the lightbox is open or closed.
- Accessibility: Ensure the lightbox is accessible by using appropriate ARIA attributes (e.g.,
role="dialog",aria-labelledby). - Keyboard Navigation: Allow users to close the lightbox by pressing the Escape key.
- Prevent Scrolling: Disable scrolling on the body when the lightbox is open.
- Typescript: The entire component must be written in TypeScript.
Expected Behavior:
- Initially, the lightbox should be closed.
- When the component is opened (e.g., by clicking a thumbnail), the overlay and image should be displayed, and scrolling on the body should be disabled.
- Clicking the "Close" button or pressing the Escape key should close the lightbox, removing the overlay and re-enabling scrolling.
- If no
imageUrlis provided, the lightbox should not render the image and display a placeholder message (e.g., "No image provided").
Edge Cases to Consider:
- What happens if the
imageUrlis invalid or the image fails to load? Display an error message. - How should the component handle different image sizes? Ensure the image fits within the lightbox without overflowing.
- Consider responsiveness – how does the lightbox look on different screen sizes?
- What happens if the user tries to interact with the underlying page while the lightbox is open? (Scrolling should be disabled).
Examples
Example 1:
Input: imageUrl = "https://example.com/image.jpg", isOpen = true
Output: A darkened overlay covering the screen, displaying the image from the URL, and a "Close" button. Scrolling on the body is disabled.
Explanation: The component renders the lightbox with the provided image and disables scrolling.
Example 2:
Input: imageUrl = null, isOpen = true
Output: A darkened overlay covering the screen, displaying the message "No image provided." and a "Close" button. Scrolling on the body is disabled.
Explanation: The component renders the lightbox but displays a placeholder message because no image URL was provided.
Example 3:
Input: imageUrl = "https://example.com/image.jpg", isOpen = false
Output: No lightbox is displayed. The overlay is not present. Scrolling on the body is enabled.
Explanation: The component is not open, so no lightbox elements are rendered.
Constraints
- Component Structure: The component should be a functional component using React Hooks.
- Image Size: The image should be scaled to fit within the lightbox while maintaining its aspect ratio. A maximum width and height of 80% of the viewport dimensions is suggested.
- Overlay Opacity: The overlay should have an opacity of 0.7.
- Performance: The component should render efficiently and avoid unnecessary re-renders.
- Dependencies: You are allowed to use standard React and TypeScript features. No external libraries are permitted for this challenge.
Notes
- Consider using CSS for styling the lightbox and overlay. You can use inline styles or a CSS-in-JS solution.
- Think about how to handle the
isOpenstate effectively. - Pay close attention to accessibility best practices.
- Focus on creating a clean, reusable, and well-documented component.
- The focus should be on the core lightbox functionality; advanced features like image navigation (next/previous) are not required for this challenge.