-
Notifications
You must be signed in to change notification settings - Fork 273
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(ImageGallery): adds ImageGallery and ImageGalleryImage component (…
…#315) * chore: checking in progress work * chore:check in progress * chore: check in progress * feature: adds imageGallery and ImageGalleryImage to create gallery view for images * chore: add comment explaining eslint-disable-next-line * chore: style changes to fix butotn click space * chore: remove unnecessary images from static folder * chore: remove unnecessary packages * chore: remove accidentally added gallery page * chore: add tokens and fix mobile view * refactor: add Row to ImageGallery * docs: update imagegallery.mdx * chore: adds focus outline to ImageGallery and check to verify type of element * chore: fixes addNoScroll staying, adds color token and adds a11y annotation * chore: removes margin on AddNoScroll, scopes column changes, adds dark mode * chore: add margin to image * chore: remove dark theme * chore: center image and restyle title * refactor: adds markdown image ability, updates styles, fixes firefox issue, and updates image gallery mdx * chore: remove comments * chore: adds styling to remove outline and change margins * chore: updates margins on arrows, close button, and title position
- Loading branch information
1 parent
1fc4b98
commit eb31926
Showing
20 changed files
with
610 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
--- | ||
title: Image Gallery | ||
--- | ||
|
||
<PageDescription> | ||
|
||
A small scale example of the Image Gallery from the [IBM Design Language Gallery](https://www.ibm.com/design/language/gallery). | ||
|
||
</PageDescription> | ||
|
||
## Image Gallery Example | ||
|
||
Click on an image to open the gallery. | ||
|
||
<ImageGallery> | ||
|
||
<ImageGalleryImage alt="IBM Design" title="IBM Design" col={4}> | ||
|
||
![IBM Design](/images/IBM_Design_landing.jpg) | ||
|
||
</ImageGalleryImage> | ||
|
||
<ImageGalleryImage alt="IBM Cloud Logo" title="IBM Cloud" col={4}> | ||
|
||
![IBM Cloud Logo](/images/IBM_Cloud_Logo.png) | ||
|
||
</ImageGalleryImage> | ||
<ImageGalleryImage alt="IBM Cloud Developers" title="IBM Cloud Developers" col={4}> | ||
|
||
![IBM Cloud Developers](/images/IBM_Cloud_Developers.jpg) | ||
|
||
</ImageGalleryImage> | ||
<ImageGalleryImage alt="IBM Cloud Data Center" title="IBM Cloud Data Center" col={8}> | ||
|
||
![IBM Cloud Data Center](/images/IBM_Cloud_Data_Center.jpg) | ||
|
||
</ImageGalleryImage> | ||
<ImageGalleryImage alt="IBM Cloud Interconnect" title="IBM Cloud Interconnect" col={4}> | ||
|
||
![IBM Cloud Interconnect](/images/IBM_Cloud_Interconnect.jpg) | ||
|
||
</ImageGalleryImage> | ||
<ImageGalleryImage alt="IBM Cloud Notebook" title="IBM Cloud Notebook" col={4}> | ||
|
||
![IBM Cloud Notebook](/images/IBM_Cloud_Notebook.jpg) | ||
|
||
</ImageGalleryImage> | ||
<ImageGalleryImage alt="IBM Cloud Platform Prototype" title="IBM Cloud Platform" col={8}> | ||
|
||
![IBM Cloud Platform Prototype](/images/IBM_Cloud_Platform_Prototype.gif) | ||
|
||
</ImageGalleryImage> | ||
<ImageGalleryImage alt="IBM Cloud Pictograms" title="IBM Cloud Pictograms" col={4}> | ||
|
||
![IBM Cloud Pictograms](/images/IBM_Cloud_Pictograms.gif) | ||
|
||
</ImageGalleryImage> | ||
<ImageGalleryImage alt="IBM Cloud Server" title="IBM Cloud Server" col={4}> | ||
|
||
![IBM Cloud Server](/images/IBM_Cloud_Server.png) | ||
|
||
</ImageGalleryImage> | ||
<ImageGalleryImage alt="IBM Cloud Think" title="IBM Cloud Think" col={4}> | ||
|
||
![IBM Cloud Think](/images/IBM_Cloud_Think_Keynote.jpg) | ||
|
||
</ImageGalleryImage> | ||
|
||
</ImageGallery> | ||
|
||
## Markdown Code | ||
|
||
You can use the ImageGallery component in markdown by nesting your images inside the ImageGallery component and using the ImageGalleryImage component to define the image's location, title, alt tag, and the columns the image on the page will span at the medium and large breakpoints. There is no gallery view for mobile so the small breakpoint is not defined. | ||
|
||
Here's an example of how to use the ImageGallery and the ImageGalleryImage components in markdown. | ||
|
||
```markdown path=/components/ImageGallery.mdx src=https://gatsby-theme-carbon.now.sh | ||
<ImageGallery> | ||
<ImageGalleryImage alt="IBM Design" title="IBM Design" col={4}> | ||
|
||
![IBM Design](/images/IBM_Design_landing.jpg) | ||
|
||
</ImageGalleryImage> | ||
|
||
<ImageGalleryImage alt="IBM Cloud Logo" title="IBM Cloud" col={4}> | ||
|
||
![IBM Cloud Logo](/images/IBM_Cloud_Logo.png) | ||
|
||
</ImageGalleryImage> | ||
<ImageGalleryImage alt="IBM Cloud Developers" title="IBM Cloud Developers" col={4}> | ||
|
||
![IBM Cloud Developers](/images/IBM_Cloud_Developers.jpg) | ||
|
||
</ImageGalleryImage> | ||
<ImageGalleryImage alt="IBM Cloud Data Center" title="IBM Cloud Data Center" col={8}> | ||
|
||
![IBM Cloud Data Center](/images/IBM_Cloud_Data_Center.jpg) | ||
|
||
</ImageGalleryImage> | ||
<ImageGalleryImage alt="IBM Cloud Interconnect" title="IBM Cloud Interconnect" col={4}> | ||
|
||
![IBM Cloud Interconnect](/images/IBM_Cloud_Interconnect.jpg) | ||
|
||
</ImageGalleryImage> | ||
<ImageGalleryImage alt="IBM Cloud Notebook" title="IBM Cloud Notebook" col={4}> | ||
|
||
![IBM Cloud Notebook](/images/IBM_Cloud_Notebook.jpg) | ||
|
||
</ImageGalleryImage> | ||
<ImageGalleryImage alt="IBM Cloud Platform Prototype" title="IBM Cloud Platform" col={8}> | ||
|
||
![IBM Cloud Platform Prototype](/images/IBM_Cloud_Platform_Prototype.gif) | ||
|
||
</ImageGalleryImage> | ||
<ImageGalleryImage alt="IBM Cloud Pictograms" title="IBM Cloud Pictograms" col={4}> | ||
|
||
![IBM Cloud Pictograms](/images/IBM_Cloud_Pictograms.gif) | ||
|
||
</ImageGalleryImage> | ||
<ImageGalleryImage alt="IBM Cloud Server" title="IBM Cloud Server" col={4}> | ||
|
||
![IBM Cloud Server](/images/IBM_Cloud_Server.png) | ||
|
||
</ImageGalleryImage> | ||
<ImageGalleryImage alt="IBM Cloud Think" title="IBM Cloud Think" col={4}> | ||
|
||
![IBM Cloud Think](/images/IBM_Cloud_Think_Keynote.jpg) | ||
|
||
</ImageGalleryImage> | ||
</ImageGallery> | ||
``` |
Binary file added
BIN
+224 KB
packages/example/src/pages/components/images/IBM_Cloud_Data_Center.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+546 KB
packages/example/src/pages/components/images/IBM_Cloud_Interconnect.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+261 KB
packages/example/src/pages/components/images/IBM_Cloud_Platform_Prototype.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+254 KB
packages/example/src/pages/components/images/IBM_Cloud_Think_Keynote.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
194 changes: 194 additions & 0 deletions
194
packages/gatsby-theme-carbon/src/components/ImageGallery/ImageGallery.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,194 @@ | ||
import React, { useState, useEffect, Children } from 'react'; | ||
import ReactDOM from 'react-dom'; | ||
import { breakpoints } from '@carbon/elements'; | ||
import { ChevronRight32, ChevronLeft32, Close32 } from '@carbon/icons-react'; | ||
import cx from 'classnames'; | ||
import FocusTrap from 'focus-trap-react'; | ||
import useMedia from 'use-media'; | ||
import PropTypes from 'prop-types'; | ||
import { Grid, Row, Column } from '../Grid'; | ||
import { | ||
galleryContainer, | ||
inDialogGalleryContainer, | ||
galleryGrid, | ||
galleryRow, | ||
navButtons, | ||
closeButton, | ||
icon, | ||
navButtonsContainer, | ||
firstRightNav, | ||
rightNav, | ||
leftNav, | ||
addNoScroll, | ||
} from './ImageGallery.module.scss'; | ||
|
||
function ImageGallery({ children }) { | ||
const [portalsNode, updateNode] = useState(null); | ||
const [isGalleryOpen, setIsGalleryOpen] = useState(false); | ||
const [activeImageIndex, updateActiveImageIndex] = useState(null); | ||
const childrenAsArray = Children.toArray(children); | ||
const rightNavButton = cx({ | ||
[rightNav]: true, | ||
[firstRightNav]: activeImageIndex === 0, | ||
[navButtons]: activeImageIndex > 0, | ||
}); | ||
const leftNavButton = cx([leftNav], [navButtons]); | ||
const isMobile = useMedia({ maxWidth: breakpoints.md.width }); | ||
|
||
// Creates the node to go into the portalsNode state. | ||
useEffect(() => { | ||
const node = document.createElement('div'); | ||
document.body.appendChild(node); | ||
updateNode(node); | ||
|
||
return () => { | ||
node.parentNode.removeChild(node); | ||
}; | ||
}, []); | ||
|
||
// Depending on if the gallery is open or not, this adds the addNoScroll class so the screen behind the modal doesn't scroll when opened. | ||
useEffect(() => { | ||
if (isGalleryOpen) { | ||
document.body.classList.add(addNoScroll); | ||
} | ||
|
||
return () => { | ||
document.body.classList.remove(addNoScroll); | ||
}; | ||
}, [isGalleryOpen]); | ||
|
||
// Removes addNoScroll if view is shrunk to mobile view when the gallery is open | ||
useEffect(() => { | ||
if ( | ||
(isMobile && document.body.classList.contains(addNoScroll)) || | ||
!isGalleryOpen | ||
) { | ||
document.body.classList.remove(addNoScroll); | ||
} | ||
|
||
return () => { | ||
if (!isMobile && isGalleryOpen) { | ||
document.body.classList.add(addNoScroll); | ||
} | ||
}; | ||
}, [isGalleryOpen, isMobile]); | ||
|
||
// Opens gallery if the breakpoint isn't mobile | ||
function openGalleryForImage(index) { | ||
return () => { | ||
if (!isMobile) { | ||
setIsGalleryOpen(true); | ||
updateActiveImageIndex(index); | ||
} | ||
}; | ||
} | ||
|
||
function closeGallery() { | ||
setIsGalleryOpen(false); | ||
updateActiveImageIndex(null); | ||
} | ||
|
||
function selectNextImage() { | ||
if (activeImageIndex + 1 < childrenAsArray.length) { | ||
updateActiveImageIndex(activeImageIndex + 1); | ||
} | ||
} | ||
|
||
function selectPrevImage() { | ||
if (activeImageIndex - 1 >= 0) { | ||
updateActiveImageIndex(activeImageIndex - 1); | ||
} | ||
} | ||
|
||
function onKeyDown(event) { | ||
if (event.key === 'Escape') { | ||
closeGallery(); | ||
return; | ||
} | ||
if (event.key === 'ArrowLeft') { | ||
selectPrevImage(); | ||
return; | ||
} | ||
if (event.key === 'ArrowRight') { | ||
selectNextImage(); | ||
} | ||
} | ||
|
||
return ( | ||
<> | ||
<figure role="group" aria-label="Gallery of Various Media"> | ||
<Row className={galleryContainer}> | ||
{Children.map(children, (child, index) => | ||
React.cloneElement(child, { | ||
onClick: openGalleryForImage(index), | ||
}) | ||
)} | ||
</Row> | ||
</figure> | ||
{portalsNode && | ||
isGalleryOpen && | ||
!isMobile && | ||
ReactDOM.createPortal( | ||
<FocusTrap> | ||
{/* Because of FocusTrap, the key down events will propagate up removing the accessibility problem that would be created by having a keydown event listener on a non-interactive element. */} | ||
{/* eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions */} | ||
<div | ||
role="group" | ||
className={inDialogGalleryContainer} | ||
onKeyDown={onKeyDown} | ||
> | ||
<Row> | ||
<Column colLg={2}> | ||
<button | ||
type="button" | ||
className={closeButton} | ||
onClick={closeGallery} | ||
> | ||
<Close32 className={icon} /> | ||
</button> | ||
</Column> | ||
</Row> | ||
<Grid className={cx('bx--grid--full-width', galleryGrid)}> | ||
<Row className={galleryRow}> | ||
<Column colLg={3} className={navButtonsContainer}> | ||
{activeImageIndex - 1 >= 0 && ( | ||
<button | ||
type="button" | ||
className={leftNavButton} | ||
onClick={selectPrevImage} | ||
> | ||
<ChevronLeft32 className={icon} /> | ||
</button> | ||
)} | ||
</Column> | ||
<Column colLg={6}> | ||
{React.cloneElement(childrenAsArray[activeImageIndex], { | ||
isInDialog: true, | ||
})} | ||
</Column> | ||
<Column colLg={3} className={navButtonsContainer}> | ||
{activeImageIndex + 1 < childrenAsArray.length && ( | ||
<button | ||
type="button" | ||
className={rightNavButton} | ||
onClick={selectNextImage} | ||
> | ||
<ChevronRight32 className={icon} /> | ||
</button> | ||
)} | ||
</Column> | ||
</Row> | ||
</Grid> | ||
</div> | ||
</FocusTrap>, | ||
portalsNode | ||
)} | ||
</> | ||
); | ||
} | ||
|
||
ImageGallery.propTypes = { | ||
children: PropTypes.arrayOf(PropTypes.element).isRequired, | ||
}; | ||
|
||
export default ImageGallery; |
Oops, something went wrong.
eb31926
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Successfully aliased the URL https://gatsby-theme-carbon-mmu41oybf.now.sh to the following aliases: