fixed carousel
This commit is contained in:
@@ -16,6 +16,7 @@ interface ContentCardCarouselProps {
|
|||||||
cards: ContentCardItem[]
|
cards: ContentCardItem[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// correctly works
|
||||||
function getVisibleCardCount() {
|
function getVisibleCardCount() {
|
||||||
if (typeof window === 'undefined') return 1
|
if (typeof window === 'undefined') return 1
|
||||||
if (window.matchMedia('(min-width: 1024px)').matches) return 3
|
if (window.matchMedia('(min-width: 1024px)').matches) return 3
|
||||||
@@ -52,21 +53,26 @@ export default function ContentCardCarousel({ cards }: ContentCardCarouselProps)
|
|||||||
|
|
||||||
const maxIndex = useMemo(() => Math.max(cards.length - visibleCards, 0), [cards.length, visibleCards])
|
const maxIndex = useMemo(() => Math.max(cards.length - visibleCards, 0), [cards.length, visibleCards])
|
||||||
|
|
||||||
|
// custom mod function because JS does not have working modulus
|
||||||
|
function mod(n: number, m: number) {
|
||||||
|
return ((n % m) + m) % m;
|
||||||
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setCurrentIndex((previous) => Math.min(previous, maxIndex))
|
setCurrentIndex((previous) => Math.min(previous, maxIndex))
|
||||||
}, [maxIndex])
|
}, [maxIndex])
|
||||||
|
|
||||||
// % of track width — matches flex slide sizes (100% / 50% / 33.333% per breakpoint)
|
// % of track width — matches flex slide sizes (100% / 50% / 33.333% per breakpoint)
|
||||||
const trackOffsetPercent = cards.length > 0 ? (currentIndex * 100) / cards.length : 0
|
const trackOffsetPercent = cards.length > 0 ? ((currentIndex) * -100) / visibleCards : 0
|
||||||
|
|
||||||
const next = () => {
|
const next = () => {
|
||||||
if (maxIndex === 0) return
|
if (maxIndex === 0) return
|
||||||
setCurrentIndex((previous) => (previous >= maxIndex ? 0 : previous + 1))
|
setCurrentIndex(mod(Math.abs((currentIndex + 1)), (cards.length)))
|
||||||
}
|
}
|
||||||
|
|
||||||
const previous = () => {
|
const previous = () => {
|
||||||
if (maxIndex === 0) return
|
if (maxIndex === 0) return
|
||||||
setCurrentIndex((index) => (index <= 0 ? maxIndex : index - 1))
|
setCurrentIndex(mod((currentIndex - 1), (cards.length)))
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -76,7 +82,7 @@ export default function ContentCardCarousel({ cards }: ContentCardCarouselProps)
|
|||||||
<div className="carousel-viewport relative overflow-hidden">
|
<div className="carousel-viewport relative overflow-hidden">
|
||||||
<div
|
<div
|
||||||
className="carousel-track flex items-stretch transition-transform duration-500 ease-in-out"
|
className="carousel-track flex items-stretch transition-transform duration-500 ease-in-out"
|
||||||
style={{ transform: `translate3d(-${trackOffsetPercent}%, 0, 0)` }}
|
style={{ transform: `translate3d(${trackOffsetPercent}%, 0, 0)` }}
|
||||||
>
|
>
|
||||||
{cards.map((card, index) => {
|
{cards.map((card, index) => {
|
||||||
const isEdgeCard =
|
const isEdgeCard =
|
||||||
@@ -97,15 +103,14 @@ export default function ContentCardCarousel({ cards }: ContentCardCarouselProps)
|
|||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="pointer-events-none absolute inset-y-0 left-0 w-12 bg-gradient-to-r from-white to-transparent dark:from-black" />
|
<div className="absolute inset-y-0 left-0 w-12 bg-linear-to-r from-white to-transparent dark:from-black" />
|
||||||
<div className="pointer-events-none absolute inset-y-0 right-0 w-12 bg-gradient-to-l from-white to-transparent dark:from-black" />
|
<div className="absolute inset-y-0 right-0 w-12 bg-linear-to-l from-white to-transparent dark:from-black" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="carousel-controls relative z-20 mt-6 flex justify-center gap-4">
|
<div className="carousel-controls relative z-20 mt-6 flex justify-center gap-4">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={previous}
|
onClick={previous}
|
||||||
disabled={maxIndex === 0}
|
|
||||||
className="carousel-control-btn"
|
className="carousel-control-btn"
|
||||||
aria-label="Show previous content cards"
|
aria-label="Show previous content cards"
|
||||||
>
|
>
|
||||||
|
|||||||
Reference in New Issue
Block a user