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' import Image from 'next/image'
type ArrowProps = { type ArrowProps = {
direction: "left" | "right" direction: 'left' | 'right',
onClick?: () => void
} }
export const Arrow = ({direction}: ArrowProps) => { export const Arrow = ({ direction, onClick }: ArrowProps) => {
return ( 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); box-shadow: 3px 7px 26px -5px rgba(0, 0, 0, 0.15);
cursor: pointer; cursor: pointer;
overflow: hidden; overflow: hidden;
border-radius: $border-radius; border-top-left-radius: $border-radius;
border-top-right-radius: $border-radius;
position: relative; position: relative;
} }
@ -17,12 +18,13 @@
text-align: center; text-align: center;
font-size: 18px; font-size: 18px;
position: absolute; position: absolute;
bottom: 0px; bottom: 0;
width: 100%; width: 100%;
color: $base-color; color: $base-color;
padding: 10px 0; padding: 10px 0;
transition: padding 0.3s ease-out; 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 { .container:hover .title {

View file

@ -32,6 +32,12 @@ export const Default: Story = {
src: "https://i1.sndcdn.com/artworks-6CIZtxsNOaYIm98h-mL41yA-t500x500.jpg", src: "https://i1.sndcdn.com/artworks-6CIZtxsNOaYIm98h-mL41yA-t500x500.jpg",
title: "Erntedankfest", title: "Erntedankfest",
href: "https://somelink" 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 { ImageCard } from '@/components/ImageCard/ImageCard'
import styles from "./styles.module.scss" import styles from "./styles.module.scss"
import { StaticImageData } from 'next/image' import { StaticImageData } from 'next/image'
import { Arrow } from '@/components/Arrow/Arrow' import { Arrow } from '@/components/Arrow/Arrow'
import { useEffect, useMemo, useState } from 'react'
import classNames from 'classnames'
export type Slide = { export type Slide = {
id: string, id: string,
@ -15,20 +19,59 @@ type ImageCardSliderProps = {
} }
export const ImageCardSlider = ({slides}: 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 ( return (
<div className={styles.wrapper}> <div className={styles.wrapper}>
<div className={styles.arrowLeft}> <div className={classNames({
<Arrow direction={"left"} /> [styles.arrowLeft]: true,
[styles.disabled]: prevDisabled,
})}>
<Arrow
direction={"left"}
onClick={() => setPage(page - 1)}
/>
</div> </div>
<div className={styles.container}> <div className={styles.container}>
{ {
slides.map(slide => <div key={slide.id} className={styles.item}> pagedSlides.map(slide =>
<ImageCard src={slide.src} title={slide.title} href={slide.href} /> <div key={slide.id} className={styles.item}>
</div>) <ImageCard src={slide.src} title={slide.title} href={slide.href} />
</div>
)
} }
</div> </div>
<div className={styles.arrowRight}> <div className={classNames({
<Arrow direction={"right"} /> [styles.arrowRight]: true,
[styles.disabled]: nextDisabled,
})}>
<Arrow
direction={"right"}
onClick={() => setPage(page + 1)}
/>
</div> </div>
</div> </div>

View file

@ -8,12 +8,14 @@
position: absolute; position: absolute;
top: calc(50% - 25px); top: calc(50% - 25px);
left: -50px; left: -50px;
cursor: pointer;
} }
.arrowRight { .arrowRight {
position: absolute; position: absolute;
right: -50px; right: -50px;
top: calc(50% - 25px); top: calc(50% - 25px);
cursor: pointer;
} }
.container { .container {
@ -24,8 +26,24 @@
} }
.item { .item {
flex: 1 1 calc(33.333% - 20px); flex: 0 1 calc(33.333% - 20px);
aspect-ratio: 1 / 1; 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) { @media screen and (max-width: 576px) {
@ -33,7 +51,9 @@
flex: 0 0 100%; flex: 0 0 100%;
margin-bottom: 20px; margin-bottom: 20px;
} }
}
@media screen and (max-width: 1200px) {
.arrowLeft, .arrowRight { .arrowLeft, .arrowRight {
display: none; display: none;
} }

View file

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