The Lightbox kit is a popup window overlay that will appear on top of your webpage and cover the entirety of the screen. It can be used to display a group of images that the user can swipe through, zoom into and view. The button in the top left of the header can be used to close the overlay and exit back to your webpage. Click the images in the examples below to see Lightbox in action.
Lightbox contains several props: photos
(an array of urls), initialPhoto
(a number), onClickLeft
(an optional callback function for top left close button), title
and description
(string or custom components), icon
( optional prop for the close button in the top left of the header), navRight
(optional prop that renders clickable text in the top right section of the header), onClickRight
(optional callback function of navRight) and onChange
(optional event handler prop exposing index of current photo).
/* @flow */ /* eslint-disable jsx-control-statements/jsx-use-if-tag */ import React, { useState } from 'react' import { Flex, Image } from '../../' import Lightbox from '../_lightbox.tsx' const LightboxDefault = (props) => { const photos = [ 'https://images.unsplash.com/photo-1638727228877-d2a79ab75e68?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2668&q=80', ] const [selectedPhoto, setSelectedPhoto] = useState(0) const [showLightbox, toggleShowLightbox] = useState(false) const handleCloseLightbox = () => { toggleShowLightbox(!showLightbox) setSelectedPhoto(null) } const onPhotoClick = (photoIndex) => { toggleShowLightbox(!showLightbox) setSelectedPhoto(photoIndex) } return ( <> <div> {showLightbox ? ( <Lightbox icon="times" initialPhoto={selectedPhoto} onClose={handleCloseLightbox} photos={photos} {...props} /> ) : ( <div className="PhotoViewer"> <Flex> {photos.map((photo, index) => { return ( <div key={photo[index]} onClick={() => onPhotoClick(index)} > <Image cursor="pointer" marginRight="xl" rounded size="lg" url={photo} /> <div className="overlay" /> </div> ) })} </Flex> </div> )} </div> </> ) } export default LightboxDefault
When multiple images are passed to the Lightbox kit, it will also display scrollable thumbnails at the bottom of the screen for easier access to all images. In addition to the scrollable thumbnails, larger screens provide arrow buttons on the left and right of the image itself for easier scrolling while on mobile devices the kit allows for swiping.
This example also highlights the use of the optional onChange
prop which is an event handler prop that tracks the index of the image being viewed and exposes it for use by the developer.
/* @flow */ /* eslint-disable jsx-control-statements/jsx-use-if-tag */ import React, { useState } from 'react' import { Flex, Image } from '../../' import Lightbox from '../_lightbox.tsx' const LightboxMultiple = (props) => { const photos = [ 'https://images.unsplash.com/photo-1638727228877-d2a79ab75e68?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2668&q=80', 'https://images.unsplash.com/photo-1526657782461-9fe13402a841?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1984&q=80', 'https://images.unsplash.com/photo-1523057530100-383d7fbc77a1?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2669&q=80', 'https://images.unsplash.com/photo-1638727228877-d2a79ab75e68?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2668&q=80', 'https://images.unsplash.com/photo-1526657782461-9fe13402a841?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1984&q=80', 'https://images.unsplash.com/photo-1523057530100-383d7fbc77a1?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2669&q=80', 'https://images.unsplash.com/photo-1638727228877-d2a79ab75e68?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2668&q=80', 'https://images.unsplash.com/photo-1526657782461-9fe13402a841?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1984&q=80', 'https://images.unsplash.com/photo-1523057530100-383d7fbc77a1?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2669&q=80', 'https://images.unsplash.com/photo-1638727228877-d2a79ab75e68?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2668&q=80', 'https://images.unsplash.com/photo-1526657782461-9fe13402a841?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1984&q=80', 'https://images.unsplash.com/photo-1523057530100-383d7fbc77a1?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2669&q=80', 'https://images.unsplash.com/photo-1638727228877-d2a79ab75e68?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2668&q=80', 'https://images.unsplash.com/photo-1526657782461-9fe13402a841?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1984&q=80', 'https://images.unsplash.com/photo-1523057530100-383d7fbc77a1?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2669&q=80', 'https://images.unsplash.com/photo-1638727228877-d2a79ab75e68?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2668&q=80', 'https://images.unsplash.com/photo-1526657782461-9fe13402a841?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1984&q=80', 'https://images.unsplash.com/photo-1523057530100-383d7fbc77a1?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2669&q=80', 'https://images.unsplash.com/photo-1523057530100-383d7fbc77a1?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2669&q=80', 'https://images.unsplash.com/photo-1638727228877-d2a79ab75e68?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2668&q=80', 'https://images.unsplash.com/photo-1526657782461-9fe13402a841?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1984&q=80', 'https://images.unsplash.com/photo-1523057530100-383d7fbc77a1?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2669&q=80', ] const [selectedPhoto, setSelectedPhoto] = useState(0) const [light, toggleLight] = useState(false) const handleCloseLightbox = () => { toggleLight(!light) setSelectedPhoto(null) } const onPhotoClick = (photo) => { toggleLight(!light) setSelectedPhoto(photo) } const exampleStyles = { width: "100%", overflow: "auto" } return ( <div> {light ? ( <Lightbox icon="times" initialPhoto={selectedPhoto} onChange={(index) => console.log(`current photo index: ${index}`)} onClose={handleCloseLightbox} photos={photos} {...props} /> ) : ( <div className="PhotoViewer" style={exampleStyles} > <Flex> {photos.map((photo, index) => { return ( <div key={index} onClick={() => onPhotoClick(index)} > <Image cursor="pointer" marginRight="xl" rounded size="lg" url={photo} /> <div className="overlay" /> </div> ) })} </Flex> </div> )} </div> ) } export default LightboxMultiple
title
and description
are optional props that can be passed to the kit if needed. Each of these props can take a string OR a custom component. This example highlights what the kit will look like when only strings are passed as title
and description
.
/* @flow */ /* eslint-disable jsx-control-statements/jsx-use-if-tag */ import React, { useState } from 'react' import { Flex, Image } from '../../' import Lightbox from '../_lightbox.tsx' const LightboxCompoundComponent = (props) => { const photos = [ 'https://images.unsplash.com/photo-1638727228877-d2a79ab75e68?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2668&q=80', 'https://images.unsplash.com/photo-1501045337096-542a73dafa4f?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2052&q=80', 'https://images.unsplash.com/photo-1563693998336-93c10e5d8f91?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1470&q=80,', ] const [selectedPhoto, setSelectedPhoto] = useState(0) const [showLightbox, toggleShowLightbox] = useState(false) const handleCloseLightbox = () => { toggleShowLightbox(!showLightbox) setSelectedPhoto(null) } const onPhotoClick = (photo) => { toggleShowLightbox(!showLightbox) setSelectedPhoto(photo) } const exampleStyles = { width: "100%", overflow: "auto" } return ( <> <div> {showLightbox ? ( <Lightbox description='Description Content Goes Here.' initialPhoto={selectedPhoto} onClose={handleCloseLightbox} photos={photos} title='Windows, Sidings, & Gutters' {...props} /> ) : ( <div className="PhotoViewer" style={exampleStyles} > <Flex> {photos.map((photo, index) => { return ( <div key={index} onClick={() => onPhotoClick(index)} > <Image cursor="pointer" marginRight="xl" rounded size="lg" url={photo} /> <div className="overlay" /> </div> ) })} </Flex> </div> )} </div> </> ) } export default LightboxCompoundComponent
title
and description
props also accept custom components if needed. The optional navRight
prop only accepts a string that translates into a clickable button. onClickRight
prop can be used to pass in click function for navRight
.
/* @flow */ /* eslint-disable jsx-control-statements/jsx-use-if-tag */ import React, { useState } from "react"; import { Flex, Image, Title, Pill } from "../../"; import Lightbox from "../_lightbox.tsx"; const LightboxCustomHeader = (props) => { const photos = [ "https://images.unsplash.com/photo-1638727228877-d2a79ab75e68?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2668&q=80", "https://images.unsplash.com/photo-1501045337096-542a73dafa4f?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2052&q=80", "https://images.unsplash.com/photo-1563693998336-93c10e5d8f91?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1470&q=80,", ]; const [selectedPhoto, setSelectedPhoto] = useState(0); const [showLightbox, toggleShowLightbox] = useState(false); const handleCloseLightbox = () => { toggleShowLightbox(!showLightbox); setSelectedPhoto(null); }; const onPhotoClick = (photo) => { toggleShowLightbox(!showLightbox); setSelectedPhoto(photo); }; const exampleStyles = { width: "100%", overflow: "auto", }; const customTitle = ( <Title dark paddingBottom="xxs" size={4} > My Custom Title </Title> ); const customDescription = ( <> <Title dark size={4} text="Tags" /> <Pill text="3" variant="success" /> </> ); return ( <> <div> {showLightbox ? ( <Lightbox description={customDescription} initialPhoto={selectedPhoto} navRight="All Photos" onClickRight={()=> alert("Clicked!")} onClose={handleCloseLightbox} photos={photos} title={customTitle} {...props} /> ) : ( <div className="PhotoViewer" style={exampleStyles} > <Flex> {photos.map((photo, index) => { return ( <div key={index} onClick={() => onPhotoClick(index)} > <Image marginRight="xl" rounded size="lg" url={photo} /> <div className="overlay" /> </div> ); })} </Flex> </div> ) } </div> </> ); }; export default LightboxCustomHeader;