As I am a photographer, I love being able to showcase my photos in a grid, and clicking on a grid should launch a lightbox where I can browse through photos.
I investigated various react gallery packages and finally settled on react-photo-gallery for the masonry grid and react-bnb-gallery for the lightbox.
I implemented two additional frontmatter variables called gallery
and
images
.
images
is an array of user-specified images (can be external
images) that will result in a masonry grid gallery being displayed with the
blog post.
gallery
is the name of a folder in public/gallery
that will be used
as the source for images to be displayed.
The Gallery images are retrieved using GetStaticProps
:
if (data.gallery) {
const galleryPath = path.join(GALLERY_PATH, data.gallery)
const images = fs.readdirSync(galleryPath)
data.images = images.map((image) => path.join('/gallery', data.gallery, image))
data.image_dimensions = images.map((image) =>
ImageSize(path.join(GALLERY_PATH, data.gallery, image))
)
}
If an array of images exist, then it is automatically displayed in a Gallery
from BlogLayout
{meta.images && <MyGallery photos={meta.images} dimensions={meta.image_dimensions}/>}
My Gallery is currently defined as
import React, { useCallback, useState } from 'react'
import ReactBnbGallery from 'react-bnb-gallery'
import 'react-bnb-gallery/dist/style.css'
import Gallery from 'react-photo-gallery'
import { ISizeCalculationResult } from 'image-size/dist/types/interface'
const MyGallery: React.FC<{ photos: string[]; dimensions?: ISizeCalculationResult[] }> = ({
photos,
dimensions
}) => {
const [isOpen, setIsOpen] = useState(false)
const [currentImage, setCurrentImage] = useState(0)
const openLightbox = useCallback((event, { _photo, index }) => {
setCurrentImage(index)
setIsOpen(true)
}, [])
const closeLightbox = () => {
setCurrentImage(0)
setIsOpen(false)
}
return (
<>
<div className="container flex flex-col items-center mx-auto">
<button
className="inline-flex items-center text-white bg-rosely10 border-0 py-2 px-6 focus:outline-none hover:bg-rosely9 rounded text-lg mb-4"
onClick={() => setIsOpen(true)}
>
View gallery
</button>
</div>
<div className="container mx-auto">
<Gallery
photos={photos.map((photo, i) => ({
src: photo,
width: dimensions ? dimensions[i].width : 1,
height: dimensions ? dimensions[i].height : 1
}))}
direction="column"
onClick={openLightbox}
/>
</div>
<ReactBnbGallery
show={isOpen}
photos={photos}
onClose={closeLightbox}
activePhotoIndex={currentImage}
/>
</>
)
}
export default MyGallery
Here is a sample image gallery attached to this post.