Skip to content

Commit

Permalink
feat: gallery
Browse files Browse the repository at this point in the history
  • Loading branch information
jakepro657 committed Feb 9, 2024
1 parent 206b4a4 commit aefe23b
Show file tree
Hide file tree
Showing 10 changed files with 204 additions and 5 deletions.
4 changes: 3 additions & 1 deletion src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import classNames from 'classnames/bind'
import { useEffect, useState } from 'react'
import styles from './App.module.scss'
import Heading from './components/sections/Heading'
import ImageGallery from './components/sections/ImageGallery'
import Video from './components/sections/Video'

import FullScreenMessage from './components/shared/FullScreenMessage'
Expand Down Expand Up @@ -49,12 +50,13 @@ function App() {
return null
}

const { date } = wedding
const { date, galleryImages } = wedding

return (
<div className={cx('container')}>
<Heading date={date} />
<Video />
<ImageGallery images={galleryImages} />
{JSON.stringify(wedding)}
</div>
)
Expand Down
19 changes: 19 additions & 0 deletions src/components/imageViewer/ImageViewer.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
.dimmed {
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
background-color: #000;
z-index: 9999;

.icon-close {
width: 20px;
height: 20px;
fill: #fff;
position: absolute;
top: 10px;
right: 10px;
z-index: 2;
}
}
61 changes: 61 additions & 0 deletions src/components/imageViewer/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { Swiper, SwiperSlide } from 'swiper/react'
import classNames from 'classnames/bind'

import styles from './ImageViewer.module.scss'
import 'swiper/css'
import './swiper.css'

const cx = classNames.bind(styles)

function ImageViewer({
images,
open = false,
selectedIdx,
onClose,
}: {
images: string[]
open: boolean
selectedIdx: number
onClose: () => void
}) {
if (open === false) return null

return (
<div className={cx('dimmed')}>
<CloseButton className={cx('icon-close')} onClose={onClose} />
<Swiper
spaceBetween={20}
slidesPerView={1}
loop
initialSlide={selectedIdx}
>
{images.map((src, index) => (
<SwiperSlide key={index}>
<img src={src} alt="이미지 뷰어" />
</SwiperSlide>
))}
</Swiper>
</div>
)
}

function CloseButton({
onClose,
className,
}: {
onClose: () => void
className: string
}) {
return (
<svg
className={className}
onClick={onClose}
viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg"
>
<path d="M2.93 17.07A10 10 0 1 1 17.07 2.93 10 10 0 0 1 2.93 17.07zm1.41-1.41A8 8 0 1 0 15.66 4.34 8 8 0 0 0 4.34 15.66zm9.9-8.49L11.41 10l2.83 2.83-1.41 1.41L10 11.41l-2.83 2.83-1.41-1.41L8.59 10 5.76 7.17l1.41-1.41L10 8.59l2.83-2.83 1.41 1.41z" />
</svg>
)
}

export default ImageViewer
15 changes: 15 additions & 0 deletions src/components/imageViewer/swiper.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
.swiper,
.swiper-wrapper {
height: 100% !important;
}

.swiper-slide {
display: flex;
justify-content: center;
align-items: center;
height: 100%;
}

.swiper-slide img {
width: 100%;
}
26 changes: 26 additions & 0 deletions src/components/sections/ImageGallery.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
.wrap-images {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 6px;

.wrap-image {

width: 100%;
position: relative;

&::after {
display: block;
content: "";
padding-bottom: 100%;
}

img {
width: 100%;
height: 100%;
left: 0;
position: absolute;
object-fit: cover;
border-radius: 8px;
}
}
}
51 changes: 51 additions & 0 deletions src/components/sections/ImageGallery.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import classNames from 'classnames/bind'
import { useState } from 'react'
import ImageViewer from '../imageViewer'
import Section from '../shared/Section'
import styles from './ImageGallery.module.scss'

type Props = {
images: string[]
}

const cx = classNames.bind(styles)

function ImageGallery({ images }: Props) {
const [selectedIdx, setSelectedIdx] = useState<number>(-1)

const open = selectedIdx > -1

const handleSelectedImage = (idx: number) => {
setSelectedIdx(idx)
}

const handleClose = () => {
setSelectedIdx(-1)
}

return (
<>
<Section title="사진첩">
<ul className={cx('wrap-images')}>
{images.map((src, index) => (
<li
key={index}
className={cx('wrap-image')}
onClick={() => handleSelectedImage(index)}
>
<img src={src} alt="사진첩 이미지" />
</li>
))}
</ul>
</Section>
<ImageViewer
images={images}
open={open}
selectedIdx={selectedIdx}
onClose={handleClose}
/>
</>
)
}

export default ImageGallery
5 changes: 5 additions & 0 deletions src/components/sections/Video.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.container {
video {
width: 100%;
}
}
12 changes: 10 additions & 2 deletions src/components/sections/Video.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
import classNames from 'classnames/bind'
import Section from '../shared/Section'
import styles from './Video.module.scss'

// const cx = classNames.bind(styles)
const cx = classNames.bind(styles)

function Video() {
return <Section>Heading</Section>
return (
<Section className={cx('container')}>
<video autoPlay muted loop poster="/assets/poster.jpg">
<source src="/assets/main.mp4" type="video/mp4" />
</video>
</Section>
)
}

export default Video
6 changes: 6 additions & 0 deletions src/components/shared/Section.module.scss
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
.container {
padding: 24px;

.txt-title {
font-size: 18px;
font-weight: bold;
margin-bottom: 24px;
}
}
10 changes: 8 additions & 2 deletions src/components/shared/Section.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,19 @@ import styles from './Section.module.scss'
type Props = {
className?: string
children: React.ReactNode
title?: string
}

const cx = classNames.bind(styles)

function Section({ children, className }: Props) {
function Section({ children, className, title }: Props) {
return (
<section className={cx(['container', className])}>{children}</section>
<section className={cx(['container', className])}>
{title != null ? (
<div className={cx('txt-title')}>{title}</div>
) : null}
{children}
</section>
)
}

Expand Down

0 comments on commit aefe23b

Please sign in to comment.