Created
December 9, 2023 21:20
-
-
Save devongovett/5cfd615a352e5cf629b66cb4f33c1371 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import {ChevronLeft, ChevronRight} from 'lucide-react'; | |
import {useEffect, useState} from 'react'; | |
export function Pagination({carousel}: {carousel: HTMLElement}) { | |
// Scroll by 1 page in the given direction (-1 or +1). | |
// This uses the width of the carousel minus the padding and gap between items. | |
// Use behavior: 'smooth' and the browser will animate the scrolling. | |
let scroll = (dir: number) => { | |
let style = window.getComputedStyle(carousel); | |
carousel.scrollBy({ | |
left: dir * (carousel.clientWidth - parseInt(style.paddingLeft, 10) - parseInt(style.paddingRight, 10) + parseInt(style.columnGap, 10)), | |
behavior: 'smooth' | |
}); | |
}; | |
let [isPrevDisabled, setPrevDisabled] = useState(true); | |
let [isNextDisabled, setNextDisabled] = useState(false); | |
// Use the scroll position to determine if we are at the start or end of the carousel. | |
// This controls whether the previous and next buttons are enabled. | |
useEffect(() => { | |
let update = () => { | |
setPrevDisabled(carousel.scrollLeft <= 0); | |
setNextDisabled(carousel.scrollLeft >= carousel.scrollWidth - carousel.clientWidth); | |
}; | |
update(); | |
// Use the scrollend event if supported for better perf, with fallback to regular scroll. | |
if ('onscrollend' in document) { | |
carousel.addEventListener('scrollend', update); | |
return () => carousel.removeEventListener('scrollend', update); | |
} else { | |
carousel.addEventListener('scroll', update); | |
return () => carousel.removeEventListener('scroll', update); | |
} | |
}, [carousel]); | |
return ( | |
<div className="flex gap-2 justify-end"> | |
<button | |
className="..." | |
aria-label="Previous Page" | |
disabled={isPrevDisabled} | |
onClick={() => scroll(-1)}> | |
<ChevronLeft className="w-5 h-5" /> | |
</button> | |
<button | |
className="..." | |
aria-label="Next Page" | |
disabled={isNextDisabled} | |
onClick={() => scroll(1)}> | |
<ChevronRight className="w-5 h-5" /> | |
</button> | |
</div> | |
); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This is awesome, it would be good if you could tell me how to implement this :)