react-photoswipe-gallery
A configurable and flexible React component wrapper around PhotoSwipe.
ℹ️ Current version of react-photoswipe-gallery is compatible with PhotoSwipe v5.
If you need PhotoSwipe v4, use react-photoswipe-gallery v1.
Basic Usage
import 'photoswipe/dist/photoswipe.css'
import { Gallery, Item } from 'react-photoswipe-gallery'
const MyGallery = () => (
<Gallery>
<Item
original="https://placekitten.com/1024/768?image=1"
thumbnail="https://placekitten.com/80/60?image=1"
width="1024"
height="768"
>
{({ ref, open }) => (
<img ref={ref} onClick={open} src="https://placekitten.com/80/60?image=1" />
)}
</Item>
<Item
original="https://placekitten.com/1024/768?image=2"
thumbnail="https://placekitten.com/80/60?image=2"
width="1024"
height="768"
>
{({ ref, open }) => (
<img ref={ref} onClick={open} src="https://placekitten.com/80/60?image=2" />
)}
</Item>
</Gallery>
)
Demo
Check out the Storybook to see it in action 🚀
Stories are written as real-world examples, so you can see them at the bottom of Storybook UI in the Story tab. Or browse the source code on GitHub. It covers most of the use-cases and provides examples for configuration options.
Installation
yarn add photoswipe react-photoswipe-gallery
or
npm install photoswipe react-photoswipe-gallery --save
Hash Navigation
You should pass a unique id
prop to <Gallery />
component, to enable hash navigation.
Optionally, you can also pass the id
to <Item />
component. Otherwise, the index will be used.
const MyGallery = () => (
<Gallery id="my-gallery">
<Item
id="first-pic"
{/*...*/}
/>
<Item
id="second-pic"
{/*...*/}
/>
</Gallery>
)
Example
Captions
If you want to add captions to your slides, you need to pass withCaption
prop to the <Gallery />
and pass caption
prop to each <Item />
. It accepts html as well. If caption
isn't provided - it will use alt
prop.
const MyGallery = () => (
<Gallery withCaption>
<Item
caption="Foo"
{/*...*/}
/>
<Item
alt="Bar"
{/*...*/}
/>
</Gallery>
)
Example
Plugins
You can use native PhotoSwipe plugins with plugins
prop. It accepts the function in which you should register all of your plugins, providing pswpLightbox
to the plugin constructor.
Example for photoswipe-dynamic-caption-plugin:
import 'photoswipe-dynamic-caption-plugin/photoswipe-dynamic-caption-plugin.css'
import PhotoSwipeDynamicCaption from 'photoswipe-dynamic-caption-plugin'
const MyGallery = () => (
<Gallery
plugins={(pswpLightbox) => {
// register plugin
const captionPlugin = new PhotoSwipeDynamicCaption(pswpLightbox, {
captionContent: (slide) => slide.data.alt,
})
// register another plugin
// ...
}}
>
{/*...*/}
</Gallery>
)
Example
Custom UI Elements
You can add custom UI elements to PhotoSwipe with uiElements
prop. It accepts an array of configuration objects for custom UI elements.
const uiElements = [
{
name: 'custom-button',
ariaLabel: 'Custom button',
order: 9,
isButton: true,
html: {
isCustomSVG: true,
inner:
'<path d="<ICON_PATH>" id="pswp__icn-cstm-btn"/>',
outlineID: 'pswp__icn-cstm-btn',
},
appendTo: 'bar',
onInit: (el, pswpInstance) => {
},
onClick: (e, el, pswpInstance) => {
},
},
]
const MyGallery = () => (
<Gallery uiElements={uiElements}>
{/*...*/}
</Gallery>
)
Example
Custom slide content
You can add your own custom slide content with content
and html
props.
const MyGallery = () => (
<Gallery>
<Item
content={<h1>Hi!</h1>}
{/*...*/}
/>
<Item
html="<h1>Hi!</h1>"
{/*...*/}
/>
</Gallery>
)
Example
Access to Photoswipe instance
If you need to get access to Photoswipe instance (for example, to subscribe on Photoswipe events or call some Photoswipe method),
you can do it via onOpen
and onBeforeOpen
props of Gallery
component.
onBeforeOpen
triggers before PhotoSwipe.init()
call.
onOpen
triggers after PhotoSwipe.init()
call.
onBeforeOpen
and onOpen
will receive PhotoSwipe instance as the first argument.
const onBeforeOpen = (pswpInstance) => {
pswpInstance.on('change', () => {
console.log('slide was changed')
})
}
const onOpen = (pswpInstance) => {
pswpInstance.currSlide.zoomTo(
1,
{ x: 0, y: 0 },
2000,
false
)
}
const MyGallery = () => (
<Gallery onBeforeOpen={onBeforeOpen} onOpen={onOpen}>
{/*...*/}
</Gallery>
)
Photoswipe customization
If you need to customize Photoswipe options or Photoswipe styling
you can do it via options
prop of Gallery
component.
const options = {
arrowPrev: false,
arrowNext: false,
zoom: false,
close: false,
counter: false,
bgOpacity: 0.2,
padding: { top: 20, bottom: 40, left: 100, right: 100 },
}
const MyGallery = () => (
<Gallery options={options}>
{/*...*/}
</Gallery>
)
Props
Gallery
Prop | Type | Required | Description |
---|
id | Number or String | ✓ (for hash navigation) | Item ID, for hash navigation |
options | Object | | Object containing PhotoSwipe options and styling properties |
plugins | Function | | Function for registering PhotoSwipe plugins. You should pass photoswipeLightbox to each plugin constructor (example) |
uiElements | Array | | Array of configuration objects for custom UI elements. Use it for adding custom UI elements (example) |
onBeforeOpen | Function | | Triggers before PhotoSwipe.init() call. Use it for accessing PhotoSwipe API. It will receive PhotoSwipe instance as the first argument: (photoswipe: PhotoSwipe) => void |
onOpen | Function | | Triggers after PhotoSwipe.init() call. Use it for accessing PhotoSwipe API. It will receive PhotoSwipe instance as the first argument: (photoswipe: PhotoSwipe) => void |
withCaption | Boolean | ✓ (for default captions) | Enables built-in caption display. Use the caption prop of the Item component to control caption text (example) |
withDownloadButton | Boolean | ✓ (for download button) | Adds UI control for downloading the original image of the current slide (example) |
Item
Should be children of the Gallery
.
Prop | Type | Required | Description |
---|
children | Function | ✓ | Render prop for exposing Gallery API |
original | String | | Url of original image |
originalSrcset | String | | Srcset of original image (example) |
thumbnail | String | | Url of thumbnail |
width | Number or String | | Width of original image |
height | Number or String | | Height of original image |
alt | String | | Alternate text for original image |
caption | String | | Text or html for caption (example) |
cropped | Boolean | | Thumbnail is cropped (example) |
content | ReactElement | | Custom slide content (example) |
html | String | | Custom slide content (raw html) (example) |
id | Number or String | | Item ID, for hash navigation (example) |
Note about Item's children
render prop
Item accepts only function as children.
export interface ChildrenFnProps<NodeType extends HTMLElement> {
ref: (node: NodeType | null) => void
open: (e: MouseEvent) => void
}
<Item>
{({ ref, open }) => (
<img ref={ref} onClick={open} />
)}
</Item>
<Item>
{({ ref, open }) => (
<span
ref={(node) => {
ref(node)
console.log(node)
}}
onClick={open}
>
Open gallery
</span>
)}
</Item>
Hooks
useGallery
The useGallery
hook returns an object with some useful methods.
Property | Type | Description |
---|
open | (index: number) => void | This function allows programmatically open Photoswipe UI at index |
useGallery
hook gets context provided by Gallery
component.
So to use useGallery
hook you need to store your gallery content as separate component and then wrap it into Gallery
component.
const GalleryContent = () => {
const { open } = useGallery()
useEffect(() => {
open(1)
}, [open])
return (
<div>
{/* or you can open second slide on button click */}
<button onClick={() => open(1)}>Open second slide</button>
<div>
<Item>...</Item>
<Item>...</Item>
<Item>...</Item>
</div>
</div>
)
}
const MyGallery = () => {
return (
{}
<Gallery>
<GalleryContent />
</Gallery>
)
}
Example
Requirements
Development
yarn install
yarn sdks vscode
then
yarn storybook
or
yarn start
License
MIT