fix: make image slider more beautiful
This commit is contained in:
parent
9e024ef1eb
commit
7aa901a355
6 changed files with 94 additions and 16 deletions
|
|
@ -1,12 +1,18 @@
|
|||
import arrow from "./Arrow.svg"
|
||||
import arrow from './Arrow.svg'
|
||||
import Image from 'next/image'
|
||||
|
||||
type ArrowProps = {
|
||||
direction: "left" | "right"
|
||||
direction: 'left' | 'right',
|
||||
onClick?: () => void
|
||||
}
|
||||
|
||||
export const Arrow = ({direction}: ArrowProps) => {
|
||||
export const Arrow = ({ direction, onClick }: ArrowProps) => {
|
||||
return (
|
||||
<Image src={arrow} alt={""} style={{transform: `rotate(${direction === 'left' ? 0 : 180}deg)`}}/>
|
||||
<Image
|
||||
onClick={onClick}
|
||||
src={arrow}
|
||||
alt={''}
|
||||
style={{ transform: `rotate(${direction === 'left' ? 0 : 180}deg)` }}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
|
@ -8,7 +8,8 @@
|
|||
box-shadow: 3px 7px 26px -5px rgba(0, 0, 0, 0.15);
|
||||
cursor: pointer;
|
||||
overflow: hidden;
|
||||
border-radius: $border-radius;
|
||||
border-top-left-radius: $border-radius;
|
||||
border-top-right-radius: $border-radius;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
|
|
@ -17,12 +18,13 @@
|
|||
text-align: center;
|
||||
font-size: 18px;
|
||||
position: absolute;
|
||||
bottom: 0px;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
color: $base-color;
|
||||
padding: 10px 0;
|
||||
transition: padding 0.3s ease-out;
|
||||
border-radius: $border-radius;
|
||||
border-top-left-radius: $border-radius;
|
||||
border-top-right-radius: $border-radius;
|
||||
}
|
||||
|
||||
.container:hover .title {
|
||||
|
|
|
|||
|
|
@ -32,6 +32,12 @@ export const Default: Story = {
|
|||
src: "https://i1.sndcdn.com/artworks-6CIZtxsNOaYIm98h-mL41yA-t500x500.jpg",
|
||||
title: "Erntedankfest",
|
||||
href: "https://somelink"
|
||||
},
|
||||
{
|
||||
id: "id4",
|
||||
src: "https://i1.sndcdn.com/artworks-6CIZtxsNOaYIm98h-mL41yA-t500x500.jpg",
|
||||
title: "Slide4",
|
||||
href: "https://somelink"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,7 +1,11 @@
|
|||
"use client"
|
||||
|
||||
import { ImageCard } from '@/components/ImageCard/ImageCard'
|
||||
import styles from "./styles.module.scss"
|
||||
import { StaticImageData } from 'next/image'
|
||||
import { Arrow } from '@/components/Arrow/Arrow'
|
||||
import { useEffect, useMemo, useState } from 'react'
|
||||
import classNames from 'classnames'
|
||||
|
||||
export type Slide = {
|
||||
id: string,
|
||||
|
|
@ -15,20 +19,59 @@ type ImageCardSliderProps = {
|
|||
}
|
||||
|
||||
export const ImageCardSlider = ({slides}: ImageCardSliderProps) => {
|
||||
|
||||
const itemsPerPage = 3;
|
||||
const [page, setPage] = useState(0)
|
||||
const [prevDisabled, setPrevDisabled] = useState(true)
|
||||
const [nextDisabled, setNextDisabled] = useState(true)
|
||||
|
||||
useEffect(() => {
|
||||
if (page === 0) {
|
||||
setPrevDisabled(true)
|
||||
} else {
|
||||
setPrevDisabled(false)
|
||||
}
|
||||
|
||||
if ((page + 1) * itemsPerPage > slides.length) {
|
||||
setNextDisabled(true)
|
||||
} else {
|
||||
setNextDisabled(false)
|
||||
}
|
||||
|
||||
}, [slides, page, setNextDisabled, setPrevDisabled])
|
||||
|
||||
const pagedSlides = useMemo(() => {
|
||||
return slides.slice(page * itemsPerPage, (page + 1) * itemsPerPage)
|
||||
}, [slides, page])
|
||||
|
||||
return (
|
||||
<div className={styles.wrapper}>
|
||||
<div className={styles.arrowLeft}>
|
||||
<Arrow direction={"left"} />
|
||||
<div className={classNames({
|
||||
[styles.arrowLeft]: true,
|
||||
[styles.disabled]: prevDisabled,
|
||||
})}>
|
||||
<Arrow
|
||||
direction={"left"}
|
||||
onClick={() => setPage(page - 1)}
|
||||
/>
|
||||
</div>
|
||||
<div className={styles.container}>
|
||||
{
|
||||
slides.map(slide => <div key={slide.id} className={styles.item}>
|
||||
<ImageCard src={slide.src} title={slide.title} href={slide.href} />
|
||||
</div>)
|
||||
pagedSlides.map(slide =>
|
||||
<div key={slide.id} className={styles.item}>
|
||||
<ImageCard src={slide.src} title={slide.title} href={slide.href} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
<div className={styles.arrowRight}>
|
||||
<Arrow direction={"right"} />
|
||||
<div className={classNames({
|
||||
[styles.arrowRight]: true,
|
||||
[styles.disabled]: nextDisabled,
|
||||
})}>
|
||||
<Arrow
|
||||
direction={"right"}
|
||||
onClick={() => setPage(page + 1)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -8,12 +8,14 @@
|
|||
position: absolute;
|
||||
top: calc(50% - 25px);
|
||||
left: -50px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.arrowRight {
|
||||
position: absolute;
|
||||
right: -50px;
|
||||
top: calc(50% - 25px);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.container {
|
||||
|
|
@ -24,8 +26,24 @@
|
|||
}
|
||||
|
||||
.item {
|
||||
flex: 1 1 calc(33.333% - 20px);
|
||||
flex: 0 1 calc(33.333% - 20px);
|
||||
aspect-ratio: 1 / 1;
|
||||
animation: fadein 0.3s ease-out;
|
||||
}
|
||||
|
||||
.disabled {
|
||||
opacity: 0.6;
|
||||
pointer-events: none;
|
||||
cursor: inherit;
|
||||
}
|
||||
|
||||
@keyframes fadein {
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 576px) {
|
||||
|
|
@ -33,7 +51,9 @@
|
|||
flex: 0 0 100%;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1200px) {
|
||||
.arrowLeft, .arrowRight {
|
||||
display: none;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,8 @@ export const fetchBlog = async (): Promise<PaginatedDocs<Blog> | undefined> => {
|
|||
title: true,
|
||||
date: true,
|
||||
photo: true
|
||||
}
|
||||
},
|
||||
limit: 18
|
||||
},
|
||||
{ addQueryPrefix: true },
|
||||
)
|
||||
|
|
|
|||
Loading…
Reference in a new issue