Skip to content

Commit

Permalink
Updating Simple Carousel Documentation and Contribution Documention (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
sblinde authored Oct 14, 2024
1 parent 2cd8335 commit 5005742
Show file tree
Hide file tree
Showing 4 changed files with 148 additions and 23 deletions.
23 changes: 18 additions & 5 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ We encourage pull requests concerning:

## Development

Initial install & setup, with **node 10+** & **yarn v1**, run `yarn install`.
Initial install & setup, with **node 16** & **yarn v1**, run `yarn install`.

Make changes/updates to the `src/index.ts` file.

Expand All @@ -27,12 +27,10 @@ Make changes/updates to the `src/index.ts` file.
Build, run, and test examples locally:

```sh
# Go into examples folder
react-swipeable$ cd examples
# Yarn install
react-swipeable/examples$ yarn
yarn install
# Run the start:dev:local command
react-swipeable/examples$ yarn start:dev:local
yarn start:examples:local
```

Then open a browser tab to `http://localhost:8080/`.
Expand All @@ -50,6 +48,19 @@ All these steps can be verified via a single command.
yarn test
```

## Documentation

Documentation is managed within the `docs` directory. In order to test and preview changes, you'll require Node 18+ to run locally.

```sh
# navigate to docs directory
cd docs
# install modules
docs$ yarn install
# start locally and view at http://localhost:3000/
docs$ yarn start
```

### Unit Testing

All unit tests are located in:
Expand Down Expand Up @@ -193,4 +204,6 @@ examples$ python -m http.server 8080
```sh
# From root - build and publish the examples app to github pages
$ yarn examples:build:publish


```
131 changes: 130 additions & 1 deletion docs/docs/examples/simple-carousel.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,136 @@ import SimpleCarousel from '@site/src/components/examples/SimpleCarousel'

# Simple Carousel

Below is an example implementation of a simple carousel which utilizes the hooks provided by react-swipeable.
Below is an example implementation of a simple carousel which utilizes the hooks provided by `react-swipeable` within a TypeScript context.


## Simple Carousel Code Source

You can see this full example as pure code within the [Carousel.tsx](https://github.com/FormidableLabs/react-swipeable/blob/main/examples/app/SimpleCarousel/Carousel.tsx) file within the React-Swipeable repo directly.

## Simple Carousel Live Preview

<SimpleCarousel />

Note: The action of swiping must have a duration of `500ms` or lower in order to trigger the swipe action.

## Simple Carousel Code Explained

Import the hook directly from the `react-swipeable` library. In our example, we built and imported a local set of UI components: you can utilize your own UI and styling, or use your favorite UI component library of choice.

```typescript
import { useSwipeable } from 'react-swipeable';
import {
Wrapper,
CarouselContainer,
CarouselSlot,
SlideButtonContainer,
SlideButton,
PREV,
NEXT
} from '../components';
```

Below, we set up types and an interface for some of the work we'll be building. Next, we write a function called `getOrder`, which will drive the position of each item in the carousel, and what order of position each will be displayed in context of the carousel. Finally, we have a simple `getInitialState` position that sets the `CarouselState` of the carousel we'll be building.

```typescript
type Direction = typeof PREV | typeof NEXT;

interface CarouselState {
pos: number;
sliding: boolean;
dir: Direction;
}

type CarouselAction =
| { type: Direction, numItems: number }
| { type: 'stopSliding' };


const getOrder = (index: number, pos: number, numItems: number) => {
return index - pos < 0 ? numItems - Math.abs(index - pos) : index - pos;
};

const getInitialState = (numItems: number): CarouselState => ({ pos: numItems - 1, sliding: false, dir: NEXT });
```

Next, we build a reducer for controlling the action of the Carousel, using a switch to set `CarouselState` logic.

```typescript
function reducer(state: CarouselState, action: CarouselAction): CarouselState {
switch (action.type) {
case PREV:
return {
...state,
dir: PREV,
sliding: true,
pos: state.pos === 0 ? action.numItems - 1 : state.pos - 1
};
case NEXT:
return {
...state,
dir: NEXT,
sliding: true,
pos: state.pos === action.numItems - 1 ? 0 : state.pos + 1
};
case 'stopSliding':
return { ...state, sliding: false };
default:
return state;
}
}
```

Then, building upon the reducer logic, the `<Carousel>` is constructed. We hold the number of items within a count of `numItems`. We utilize the reducer within the `React.useReducer` hook.

By creating `slide`, as a `const`, we can utilize that later in the component, calling it within `useSwipeable`: called upon `slide(NEXT)` and `slide(PREV)`, invoking the `dispatch` and the `timeout` we built within `slide`. Within the use of `useSwippeable`, we set `swipeDuration` to `500ms`. We set `preventScrollOnSwipe` to `true`, and `trackMouse` to `true`.

At the end, we return the component itself, built with the components we've created, with `handlers` passed into the wrapping `<div>` around the surrounding container. The `<CarouselContainer>` holds the directional and sliding state, and within that container the items we want to display are mapped as `React.Children`, utilizing `getOrder`.

When we put it all together, our `<Carousel>` is complete!

```typescript
const Carousel: FunctionComponent<{children: ReactNode}> = (props) => {
const numItems = React.Children.count(props.children);
const [state, dispatch] = React.useReducer(reducer, getInitialState(numItems));

const slide = (dir: Direction) => {
dispatch({ type: dir, numItems });
setTimeout(() => {
dispatch({ type: 'stopSliding' });
}, 50);
};

const handlers = useSwipeable({
onSwipedLeft: () => slide(NEXT),
onSwipedRight: () => slide(PREV),
swipeDuration: 500,
preventScrollOnSwipe: true,
trackMouse: true
});

return (
<div {...handlers}>
<Wrapper>
<CarouselContainer dir={state.dir} sliding={state.sliding}>
{React.Children.map(props.children, (child, index) => (
<CarouselSlot
order={getOrder(index, state.pos, numItems)}
>
{child}
</CarouselSlot>
))}
</CarouselContainer>
</Wrapper>
<SlideButtonContainer>
<SlideButton onClick={() => slide(PREV)} float="left">
Prev
</SlideButton>
<SlideButton onClick={() => slide(NEXT)} float="right">
Next
</SlideButton>
</SlideButtonContainer>
</div>
);
};
```
9 changes: 0 additions & 9 deletions docs/src/components/examples/SimpleCarousel/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,6 @@ function SimpleCarousel() {
<Item src={Product4} />
<Item src={Product5} />
</Carousel>
<b>Note: swipe must be "faster" than 500ms to trigger.</b>
<h6>
<a href="https://github.com/FormidableLabs/react-swipeable/blob/main/examples/app/SimpleCarousel/Carousel.tsx">
See code
</a>{" "}
for example usage of{" "}
<code style={{ whiteSpace: "nowrap" }}>swipeDuration</code> and{" "}
<code>preventScrollOnSwipe</code>.
</h6>
</div>
);
}
Expand Down
8 changes: 0 additions & 8 deletions examples/app/SimpleCarousel/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,13 @@ import Carousel from './Carousel';
function SimpleCarousel() {
return (
<div>
<h5 style={{ marginBottom: '20px' }}>
<strong>🖼 Image Carousel</strong>
</h5>

<Carousel>
<Item img="https://unsplash.it/475/205" />
<Item img="https://unsplash.it/476/205" />
<Item img="https://unsplash.it/477/205" />
<Item img="https://unsplash.it/478/205" />
<Item img="https://unsplash.it/479/205" />
</Carousel>
<b>Note: swipe must be "faster" then 500ms to trigger.</b>
<h6>
<a href="https://github.com/FormidableLabs/react-swipeable/blob/main/examples/app/SimpleCarousel/Carousel.tsx">See code</a> for example usage of <code style={{ whiteSpace: "nowrap" }}>swipeDuration</code> and <code>preventScrollOnSwipe</code>.
</h6>
</div>
);
}
Expand Down

0 comments on commit 5005742

Please sign in to comment.