aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcin Zelent <marcin@zelent.net>2021-01-08 19:47:37 +0100
committerMarcin Zelent <marcin@zelent.net>2021-01-08 19:47:37 +0100
commit628632ff5092f1e3cf6c968d9bdfbd9a24f59541 (patch)
treefeddb4e82267bba700a15a6a7091f922f48cae40 /components/Gallery
Initial commit
Diffstat (limited to 'components/Gallery')
-rw-r--r--components/Gallery/Gallery.module.css63
-rw-r--r--components/Gallery/Gallery.tsx80
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>
+ );
+}