An open API service indexing awesome lists of open source software.

https://github.com/richardscarrott/react-snap-carousel

DOM-first, headless carousel for React
https://github.com/richardscarrott/react-snap-carousel

carousel react scrolling slideshow typescript

Last synced: 19 days ago
JSON representation

DOM-first, headless carousel for React

Awesome Lists containing this project

README

        

# React Snap Carousel ðŸŦ°

[![GitHub package.json version](https://img.shields.io/github/package-json/v/richardscarrott/react-snap-carousel.svg)](https://www.npmjs.com/package/react-snap-carousel)
[![npm downloads](https://img.shields.io/npm/dw/react-snap-carousel)](https://www.npmjs.com/package/react-snap-carousel)
[![CI](https://github.com/richardscarrott/react-snap-carousel/actions/workflows/node.js.yml/badge.svg)](https://github.com/richardscarrott/react-snap-carousel/actions/workflows/node.js.yml)
[![GitHub license](https://img.shields.io/github/license/richardscarrott/react-snap-carousel.svg)](https://github.com/richardscarrott/react-snap-carousel/blob/main/LICENSE)

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.

![Alt Text](react-snap-carousel.gif)

🧈 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)](https://bundlephobia.com/package/react-snap-carousel) + zero dependencies

## Install

```
npm install react-snap-carousel
```

## Resources

ðŸ”Ĩ[StoryBook Examples](https://richardscarrott.github.io/react-snap-carousel/)ðŸ”Ĩ

[CodeSandbox StarterKit](https://codesandbox.io/s/react-snap-carousel-49vu6p?file=/src/Carousel.tsx)

[Beginners Tutorial](https://dev.to/richardscarrott/build-your-own-carousel-component-with-react-snap-carousel-1e11)

## Usage

React Snap Carousel doesn't expose a ready-made `` 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](https://codesandbox.io/s/react-snap-carousel-49vu6p?file=/src/Carousel.tsx).

```tsx
// Carousel.tsx
import React, { CSSProperties } from 'react';
import { useSnapCarousel } from 'react-snap-carousel';

const styles = {
root: {},
scroll: {
position: 'relative',
display: 'flex',
overflow: 'auto',
scrollSnapType: 'x mandatory'
},
item: {
width: '250px',
height: '250px',
flexShrink: 0
},
itemSnapPoint: {
scrollSnapAlign: 'start'
},
controls: {
display: 'flex',
justifyContent: 'center',
alignItems: 'center'
},
nextPrevButton: {},
nextPrevButtonDisabled: { opacity: 0.3 },
pagination: {
display: 'flex'
},
paginationButton: {
margin: '10px'
},
paginationButtonActive: { opacity: 0.3 },
pageIndicator: {
display: 'flex',
justifyContent: 'center'
}
} satisfies Record;

interface CarouselProps {
readonly items: T[];
readonly renderItem: (
props: CarouselRenderItemProps
) => React.ReactElement;
}

interface CarouselRenderItemProps {
readonly item: T;
readonly isSnapPoint: boolean;
}

export const Carousel = ({
items,
renderItem
}: CarouselProps) => {
const {
scrollRef,
pages,
activePageIndex,
hasPrevPage,
hasNextPage,
prev,
next,
goTo,
snapPointIndexes
} = useSnapCarousel();
return (



    {items.map((item, i) =>
    renderItem({
    item,
    isSnapPoint: snapPointIndexes.has(i)
    })
    )}


prev()}
disabled={!hasPrevPage}
>
Prev

{pages.map((_, i) => (
goTo(i)}
>
{i + 1}

))}
next()}
disabled={!hasNextPage}
>
Next



{activePageIndex + 1} / {pages.length}


);
};

interface CarouselItemProps {
readonly isSnapPoint: boolean;
readonly children?: React.ReactNode;
}

export const CarouselItem = ({ isSnapPoint, children }: CarouselItemProps) => (


  • {children}

  • );
    ```

    ```tsx
    // App.tsx
    import { Carousel, CarouselItem } from './Carousel';

    const items = Array.from({ length: 20 }).map((_, i) => ({
    id: i,
    src: `https://picsum.photos/500?idx=${i}`
    }));

    const App = () => (
    (



    )}
    />
    );

    export default App;
    ```

    ## Api

    ### `useSnapCarousel(options)`

    #### Parameters

    ##### Options

    ```ts
    interface SnapCarouselOptions {
    // Horizontal or vertical carousel
    readonly axis?: 'x' | 'y';
    // Allows you to render pagination during SSR
    readonly initialPages?: number[][];
    }
    ```

    #### Return value

    ```ts
    export interface SnapCarouselResult {
    readonly pages: number[][];
    readonly activePageIndex: number;
    readonly snapPointIndexes: Set;
    readonly hasPrevPage: boolean;
    readonly hasNextPage: boolean;
    readonly prev: (opts?: SnapCarouselGoToOptions) => void;
    readonly next: (opts?: SnapCarouselGoToOptions) => void;
    readonly goTo: (pageIndex: number, opts?: SnapCarouselGoToOptions) => void;
    readonly refresh: () => void;
    readonly scrollRef: (el: HTMLElement | null) => void;
    }
    ```

    ## License

    [MIT](LICENSE)