Gathering detailed insights and metrics for react-snap-carousel
Gathering detailed insights and metrics for react-snap-carousel
Gathering detailed insights and metrics for react-snap-carousel
Gathering detailed insights and metrics for react-snap-carousel
npm install react-snap-carousel
Module System
Min. Node Version
Typescript Support
Node Version
NPM Version
310 Stars
78 Commits
13 Forks
3 Watching
7 Branches
4 Contributors
Updated on 21 Nov 2024
Minified
Minified + Gzipped
TypeScript (78.17%)
CSS (19.89%)
JavaScript (1.94%)
Cumulative downloads
Total Downloads
Last day
-34.6%
4,492
Compared to previous day
Last week
4.1%
31,861
Compared to previous week
Last month
6%
127,597
Compared to previous month
Last year
83.9%
1,427,397
Compared to previous year
1
28
DOM-first, headless carousel for React.
React Snap Carousel leaves the DOM in charge of scrolling and simply computes derived state from the layout, allowing you to progressively enhance a scroll element with responsive carousel controls.
ð§ Utilizes native browser scrolling & CSS scroll snap points for best performance and UX
ð Computes responsive page state from DOM layout & scroll position
ðē Dynamic page-based CSS snap point rendering
ð Headless design, giving you full control over UI using React Hooks API
ðïļ Written in TypeScript
ðŠķ Lightweight (~1kB) + zero dependencies
npm install react-snap-carousel
ðĨStoryBook ExamplesðĨ
React Snap Carousel doesn't expose a ready-made <Carousel />
component and instead offers a single export useSnapCarousel
which provides the state & functions necessary to build your own carousel component.
The following code snippet is a good starting point.
Inline styles are used for simplicity. You can use whichever CSS framework you prefer.
You can see it in action on CodeSandbox.
1// Carousel.tsx 2import React, { CSSProperties } from 'react'; 3import { useSnapCarousel } from 'react-snap-carousel'; 4 5const styles = { 6 root: {}, 7 scroll: { 8 position: 'relative', 9 display: 'flex', 10 overflow: 'auto', 11 scrollSnapType: 'x mandatory' 12 }, 13 item: { 14 width: '250px', 15 height: '250px', 16 flexShrink: 0 17 }, 18 itemSnapPoint: { 19 scrollSnapAlign: 'start' 20 }, 21 controls: { 22 display: 'flex', 23 justifyContent: 'center', 24 alignItems: 'center' 25 }, 26 nextPrevButton: {}, 27 nextPrevButtonDisabled: { opacity: 0.3 }, 28 pagination: { 29 display: 'flex' 30 }, 31 paginationButton: { 32 margin: '10px' 33 }, 34 paginationButtonActive: { opacity: 0.3 }, 35 pageIndicator: { 36 display: 'flex', 37 justifyContent: 'center' 38 } 39} satisfies Record<string, CSSProperties>; 40 41interface CarouselProps<T> { 42 readonly items: T[]; 43 readonly renderItem: ( 44 props: CarouselRenderItemProps<T> 45 ) => React.ReactElement<CarouselItemProps>; 46} 47 48interface CarouselRenderItemProps<T> { 49 readonly item: T; 50 readonly isSnapPoint: boolean; 51} 52 53export const Carousel = <T extends any>({ 54 items, 55 renderItem 56}: CarouselProps<T>) => { 57 const { 58 scrollRef, 59 pages, 60 activePageIndex, 61 hasPrevPage, 62 hasNextPage, 63 prev, 64 next, 65 goTo, 66 snapPointIndexes 67 } = useSnapCarousel(); 68 return ( 69 <div style={styles.root}> 70 <ul style={styles.scroll} ref={scrollRef}> 71 {items.map((item, i) => 72 renderItem({ 73 item, 74 isSnapPoint: snapPointIndexes.has(i) 75 }) 76 )} 77 </ul> 78 <div style={styles.controls} aria-hidden> 79 <button 80 style={{ 81 ...styles.nextPrevButton, 82 ...(!hasPrevPage ? styles.nextPrevButtonDisabled : {}) 83 }} 84 onClick={() => prev()} 85 disabled={!hasPrevPage} 86 > 87 Prev 88 </button> 89 {pages.map((_, i) => ( 90 <button 91 key={i} 92 style={{ 93 ...styles.paginationButton, 94 ...(activePageIndex === i ? styles.paginationButtonActive : {}) 95 }} 96 onClick={() => goTo(i)} 97 > 98 {i + 1} 99 </button> 100 ))} 101 <button 102 style={{ 103 ...styles.nextPrevButton, 104 ...(!hasNextPage ? styles.nextPrevButtonDisabled : {}) 105 }} 106 onClick={() => next()} 107 disabled={!hasNextPage} 108 > 109 Next 110 </button> 111 </div> 112 <div style={styles.pageIndicator}> 113 {activePageIndex + 1} / {pages.length} 114 </div> 115 </div> 116 ); 117}; 118 119interface CarouselItemProps { 120 readonly isSnapPoint: boolean; 121 readonly children?: React.ReactNode; 122} 123 124export const CarouselItem = ({ isSnapPoint, children }: CarouselItemProps) => ( 125 <li 126 style={{ 127 ...styles.item, 128 ...(isSnapPoint ? styles.itemSnapPoint : {}) 129 }} 130 > 131 {children} 132 </li> 133);
1// App.tsx 2import { Carousel, CarouselItem } from './Carousel'; 3 4const items = Array.from({ length: 20 }).map((_, i) => ({ 5 id: i, 6 src: `https://picsum.photos/500?idx=${i}` 7})); 8 9const App = () => ( 10 <Carousel 11 items={items} 12 renderItem={({ item, isSnapPoint }) => ( 13 <CarouselItem key={item.id} isSnapPoint={isSnapPoint}> 14 <img src={item.src} width="250" height="250" alt="" /> 15 </CarouselItem> 16 )} 17 /> 18); 19 20export default App;
useSnapCarousel(options)
1interface SnapCarouselOptions { 2 // Horizontal or vertical carousel 3 readonly axis?: 'x' | 'y'; 4 // Allows you to render pagination during SSR 5 readonly initialPages?: number[][]; 6}
1export interface SnapCarouselResult { 2 readonly pages: number[][]; 3 readonly activePageIndex: number; 4 readonly snapPointIndexes: Set<number>; 5 readonly hasPrevPage: boolean; 6 readonly hasNextPage: boolean; 7 readonly prev: (opts?: SnapCarouselGoToOptions) => void; 8 readonly next: (opts?: SnapCarouselGoToOptions) => void; 9 readonly goTo: (pageIndex: number, opts?: SnapCarouselGoToOptions) => void; 10 readonly refresh: () => void; 11 readonly scrollRef: (el: HTMLElement | null) => void; 12}
No vulnerabilities found.
No security vulnerabilities found.