diff options
author | Marcin Zelent <marcin@zelent.net> | 2021-01-08 19:47:37 +0100 |
---|---|---|
committer | Marcin Zelent <marcin@zelent.net> | 2021-01-08 19:47:37 +0100 |
commit | 628632ff5092f1e3cf6c968d9bdfbd9a24f59541 (patch) | |
tree | feddb4e82267bba700a15a6a7091f922f48cae40 /components/Gallery |
Initial commit
Diffstat (limited to 'components/Gallery')
-rw-r--r-- | components/Gallery/Gallery.module.css | 63 | ||||
-rw-r--r-- | components/Gallery/Gallery.tsx | 80 |
2 files changed, 143 insertions, 0 deletions
diff --git a/components/Gallery/Gallery.module.css b/components/Gallery/Gallery.module.css new file mode 100644 index 0000000..01e8037 --- /dev/null +++ b/components/Gallery/Gallery.module.css @@ -0,0 +1,63 @@ +.galleryContainer { + padding: 20px; + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 99999; + background: rgba(0, 0, 0, 0.8); +} + +.photoContainer { + width: 100%; + height: 100%; + padding: 20px; + position: relative; +} + +.photo { + max-width: 100%; + max-height: 100%; + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); +} + +.btn { + position: absolute; + z-index: 99999; + font-size: 2rem; + color: #eee; + background: none; + border: none; + cursor: pointer; + outline: currentcolor none medium; +} + +.btn:hover { + color: #fff; +} + +.arrowLeft { + top: 50%; + left: 0; + transform: translateY(-50%); +} + +.arrowRight { + top: 50%; + right: 0; + transform: translateY(-50%); +} + +.closeBtn { + width: 64px; + height: 64px; + top: 0; + right: 0; + font-size: 4rem; + line-height: 4rem; + font-weight: 300; +} diff --git a/components/Gallery/Gallery.tsx b/components/Gallery/Gallery.tsx new file mode 100644 index 0000000..dfadbc0 --- /dev/null +++ b/components/Gallery/Gallery.tsx @@ -0,0 +1,80 @@ +import { useEffect, useRef } from 'react'; + +import { Photo } from 'models'; +import useEvent from 'lib/useEvent'; +import styles from './Gallery.module.css'; + +interface Props { + currentPhoto: Photo; + handleClose: () => void; + handlePhotoChange: (direction: boolean) => void; +} + +export default function Gallery({ + currentPhoto, + handleClose, + handlePhotoChange, +}: Props): JSX.Element { + const wrapperRef = useRef(null); + + useEffect(() => { + function handleClickOutside(e: MouseEvent) { + if ( + wrapperRef.current && + !wrapperRef.current.contains(e.target) && + (e.target as Node).nodeName !== 'BUTTON' + ) { + handleClose(); + } + } + + document.addEventListener('mousedown', handleClickOutside); + return () => { + document.removeEventListener('mousedown', handleClickOutside); + }; + }, [wrapperRef]); + + useEvent('keydown', (e: KeyboardEvent) => { + if (e.key === 'ArrowLeft') { + handlePhotoChange(false); + } else if (e.key === 'ArrowRight') { + handlePhotoChange(true); + } else if (e.key === 'Escape') { + handleClose(); + } + }); + + return ( + <div className={styles.galleryContainer} role="region"> + <button + type="button" + className={`${styles.arrowLeft} ${styles.btn}`} + onClick={() => handlePhotoChange(false)} + > + 〈 + </button> + <div className={styles.photoContainer}> + <img + ref={wrapperRef} + src={currentPhoto.src} + alt={currentPhoto.name} + className={styles.photo} + /> + </div> + <button + type="button" + className={`${styles.arrowRight} ${styles.btn}`} + onClick={() => handlePhotoChange(true)} + > + 〉 + </button> + <button + type="button" + className={`${styles.closeBtn} ${styles.btn}`} + onClick={() => handleClose()} + > + × + </button> + </div> + ); +} |