fix: make image slider more beautiful

This commit is contained in:
Benno Tielen 2024-11-26 17:02:38 +01:00
parent 9e024ef1eb
commit 7aa901a355
6 changed files with 94 additions and 16 deletions

View file

@ -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)` }}
/>
)
}

View file

@ -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 {

View file

@ -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"
}
]
},

View file

@ -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>

View file

@ -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;
}

View file

@ -10,7 +10,8 @@ export const fetchBlog = async (): Promise<PaginatedDocs<Blog> | undefined> => {
title: true,
date: true,
photo: true
}
},
limit: 18
},
{ addQueryPrefix: true },
)