Simulator.Screen.Recording.-.iPhone.15.Pro.Max.-.2024-05-12.at.17.46.37.mp4
⚡ Lightning fast and customizable tinder-like swiper for React Native
rn-swiper-list
needs react-native-reanimated
and react-native-gesture-handler
package 💎
yarn add react-native-reanimated react-native-gesture-handler
👇 You also need to complete installations of these packages for more information use the links below 👇
Props |
type |
description |
required |
data |
array |
Array of data objects used to render the cards. |
Yes |
renderCard |
func(cardData,cardIndex) |
Function that renders a card based on the provided data and index. |
Yes |
cardStyle |
object |
CSS style properties applied to each card. These can be applied inline. |
|
children |
React.ReactNode |
Child components to be displayed inside the component. Used typically for composition. |
|
Props |
type |
description |
default |
onSwipeLeft |
func |
Function called when a card is swiped left. It receives the index of the card as a parameter. |
(cardIndex) => {} |
onSwipeRight |
func |
Function called when a card is swiped right. It receives the index of the card as a parameter. |
(cardIndex) => {} |
onSwipeTop |
func |
Function called when a card is swiped top. It receives the index of the card as a parameter. |
(cardIndex) => {} |
onSwipedAll |
func |
Function called when all cards have been swiped. |
() => {} |
onSwipeStart |
func |
Function called when a swipe event starts. |
() => {} |
onSwipeEnd |
func |
Function called when a swipe event ends. |
() => {} |
onSwipeActive |
func |
Function called when a swipe event is active. |
() => {} |
props |
type |
description |
default |
disableLeftSwipe |
bool |
If true, disables the ability to swipe left. |
false |
disableRightSwipe |
bool |
If true, disables the ability to swipe right. |
false |
disableTopSwipe |
bool |
If true, disables the ability to swipe upwards. |
false |
props |
type |
description |
default |
translateXRange |
array |
Translates the card horizontally. |
[-windowWidth / 3, 0, windowWidth / 3] |
translateYRange |
array |
Translates the card vertically. |
[-windowHeight / 3, 0, windowHeight / 3] |
rotateInputRange |
array |
Array specifying the range of x values for rotation mapping. |
[-windowWidth / 3, 0, windowWidth / 3] |
outputRotationRange |
array |
Array of rotation values corresponding to rotateInputRange . |
[-Math.PI / 20, 0, Math.PI / 20] |
Overlay Labels Animation Props
props |
type |
description |
default |
inputOverlayLabelRightOpacityRange |
array |
Array defining the input range for animating the opacity of the right overlay label. |
[0, windowWidth / 3] |
outputOverlayLabelRightOpacityRange |
array |
Array defining the output opacity values for the right overlay label, corresponding to the input range. |
[0, 1] |
inputOverlayLabelLeftOpacityRange |
array |
Array defining the input range for animating the opacity of the left overlay label. |
[0, -(windowWidth / 3)] |
outputOverlayLabelLeftOpacityRange |
array |
Array defining the output opacity values for the left overlay label, corresponding to the input range. |
[0, 1] |
inputOverlayLabelTopOpacityRange |
array |
Array defining the input range for animating the opacity of the top overlay label. |
[0, -(windowHeight / 3)] |
outputOverlayLabelTopOpacityRange |
array |
Array defining the output opacity values for the top overlay label, corresponding to the input range. |
[0, 1] |
OverlayLabelRight |
() => JSX.Element |
Component rendered as an overlay label for right swipes. |
|
OverlayLabelLeft |
() => JSX.Element |
Component rendered as an overlay label for left swipes. |
|
OverlayLabelTop |
() => JSX.Element |
Component rendered as an overlay label for top swipes. |
|
props |
type |
description |
swipeBack |
callback |
Resets the card position after a swipe event |
swipeRight |
callback |
Animates the card to fling to the right and calls onSwipeRight |
swipeLeft |
callback |
Animates the card to fling to the left and calls onSwipeLeft |
swipeTop |
callback |
Animates the card to fling to the top and calls onSwipeTop |
props |
type |
description |
default |
chunkSize |
number |
The number of cards rendered at a given time |
3 |
/* eslint-disable react-native/no-inline-styles */
import React, { useCallback, useRef } from 'react';
import {
Image,
StyleSheet,
View,
type ImageSourcePropType,
} from 'react-native';
import { GestureHandlerRootView } from 'react-native-gesture-handler';
import { AntDesign } from '@expo/vector-icons';
import { Swiper, type SwiperCardRefType } from 'rn-swiper-list';
import { ActionButton } from '../components';
const IMAGES: ImageSourcePropType[] = [
require('../assets/images/1.jpg'),
require('../assets/images/2.jpg'),
require('../assets/images/3.jpg'),
require('../assets/images/4.jpg'),
require('../assets/images/5.jpg'),
require('../assets/images/6.jpg'),
];
const App = () => {
const ref = useRef<SwiperCardRefType>();
const renderCard = useCallback(
(image: ImageSourcePropType) => {
return (
<View style={styles.renderCardContainer}>
<Image
source={image}
style={styles.renderCardImage}
resizeMode="cover"
/>
</View>
);
},
[]
);
const OverlayLabelRight = useCallback(() => {
return (
<View
style={[
styles.overlayLabelContainer,
{
backgroundColor: 'green',
},
]}
/>
);
}, []);
const OverlayLabelLeft = useCallback(() => {
return (
<View
style={[
styles.overlayLabelContainer,
{
backgroundColor: 'red',
},
]}
/>
);
}, []);
const OverlayLabelTop = useCallback(() => {
return (
<View
style={[
styles.overlayLabelContainer,
{
backgroundColor: 'blue',
},
]}
/>
);
}, []);
return (
<GestureHandlerRootView style={styles.container}>
<View style={styles.subContainer}>
<Swiper
ref={ref}
cardStyle={styles.cardStyle}
data={IMAGES}
renderCard={renderCard}
onSwipeRight={(cardIndex) => {
console.log('cardIndex', cardIndex);
}}
onSwipedAll={() => {
console.log('onSwipedAll');
}}
onSwipeLeft={(cardIndex) => {
console.log('onSwipeLeft', cardIndex);
}}
onSwipeTop={(cardIndex) => {
console.log('onSwipeTop', cardIndex);
}}
OverlayLabelRight={OverlayLabelRight}
OverlayLabelLeft={OverlayLabelLeft}
OverlayLabelTop={OverlayLabelTop}
onSwipeActive={() => {
console.log('onSwipeActive');
}}
onSwipeStart={() => {
console.log('onSwipeStart');
}}
onSwipeEnd={() => {
console.log('onSwipeEnd');
}}
/>
</View>
<View style={styles.buttonsContainer}>
<ActionButton
style={styles.button}
onTap={() => {
ref.current?.swipeLeft();
}}
>
<AntDesign name="close" size={32} color="white" />
</ActionButton>
<ActionButton
style={[styles.button, { height: 60, marginHorizontal: 10 }]}
onTap={() => {
ref.current?.swipeBack();
}}
>
<AntDesign name="reload1" size={24} color="white" />
</ActionButton>
<ActionButton
style={styles.button}
onTap={() => {
ref.current?.swipeTop();
}}
>
<AntDesign name="arrowup" size={32} color="white" />
</ActionButton>
<ActionButton
style={styles.button}
onTap={() => {
ref.current?.swipeRight();
}}
>
<AntDesign name="heart" size={32} color="white" />
</ActionButton>
</View>
</GestureHandlerRootView>
);
};
export default App;
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
},
buttonsContainer: {
flexDirection: 'row',
bottom: 34,
alignItems: 'center',
justifyContent: 'center',
},
button: {
height: 80,
borderRadius: 40,
marginHorizontal: 20,
aspectRatio: 1,
backgroundColor: '#3A3D45',
elevation: 4,
justifyContent: 'center',
alignItems: 'center',
shadowColor: 'black',
shadowOpacity: 0.1,
shadowOffset: {
width: 0,
height: 4,
},
},
buttonText: {
fontSize: 20,
fontWeight: 'bold',
},
cardStyle: {
width: '95%',
height: '75%',
borderRadius: 15,
marginVertical: 20,
},
renderCardContainer: {
flex: 1,
borderRadius: 15,
height: '75%',
width: '100%',
},
renderCardImage: {
height: '100%',
width: '100%',
borderRadius: 15,
},
subContainer: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
},
overlayLabelContainer: {
width: '100%',
height: '100%',
borderRadius: 15,
},
});
For more examples check out the example folder 📂
type SwiperCardRefType =
| {
swipeRight: () => void;
swipeLeft: () => void;
swipeBack: () => void;
swipeTop: () => void;
}
| undefined;
type SwiperOptions<T> = {
/*
* Card data and render function
*/
data: T[];
renderCard: (item: T, index: number) => JSX.Element;
cardStyle?: StyleProp<ViewStyle>;
/*
* Children components
*/
onSwipeLeft?: (cardIndex: number) => void;
onSwipeRight?: (cardIndex: number) => void;
onSwipeTop?: (cardIndex: number) => void;
onSwipedAll?: () => void;
onSwipeStart?: () => void;
onSwipeEnd?: () => void;
onSwipeActive?: () => void;
/*
* Swipe methods
*/
disableRightSwipe?: boolean;
disableLeftSwipe?: boolean;
disableTopSwipe?: boolean;
/*
* Rotation Animation Props
*/
translateXRange?: number[];
translateYRange?: number[];
rotateInputRange?: number[];
rotateOutputRange?: number[];
/*
* Overlay Labels Animation Props
*/
inputOverlayLabelRightOpacityRange?: number[];
outputOverlayLabelRightOpacityRange?: number[];
inputOverlayLabelLeftOpacityRange?: number[];
outputOverlayLabelLeftOpacityRange?: number[];
inputOverlayLabelTopOpacityRange?: number[];
outputOverlayLabelTopOpacityRange?: number[];
OverlayLabelRight?: () => JSX.Element;
OverlayLabelLeft?: () => JSX.Element;
OverlayLabelTop?: () => JSX.Element;
/*
* Misc Props
*/
chunkSize?: number;
};
See the contributing guide to learn how to contribute to the repository and the development workflow.
MIT