react-native-wallet-card-stack
v1.0.15
Published
A customizable React Native component for displaying animated stacks of card groups with smooth scrolling and TypeScript support.
Downloads
53
Maintainers
Readme
react-native-wallet-card-stack
A customizable React Native component for displaying animated stacks of card groups. Each group scrolls with smooth animations, and within each group, up to 3 cards are stacked with their own animation effects. Ideal for creating visually engaging card-based UIs like wallets, galleries, or dashboards.

Check out the CardStack component in action:
Note :
The whole card stack moving animation currently only works smoothly on iOS.
Features
Animated Scrolling: Card groups animate as you scroll, with the entire stack shifting based on a configurable top offset.
Customizable: Adjust card height, padding, spacing, and more via props.
Group Limit: Automatically limits each group to a maximum of 3 cards.
TypeScript Support: Fully typed for better developer experience.
Installation
Install the package via npm:
npm install react-native-card-stack
Or with yarn:
yarn add react-native-card-stack
Dependencies
Ensure you have the following peer dependencies installed:
react
react-native
Usage
Here’s a basic example of how to use CardStack in your React Native app:
import React from "react";
import { SafeAreaView, StyleSheet, Text, View } from "react-native";
import CardStack from "react-native-wallet-card-stack";
const Base = () => {
const [selectedGroup, setSelectedGroup] = React.useState<string | null>(null);
// Handler for card press events
const handleCardPress = (groupIndex: number) => {
setSelectedGroup(testData[groupIndex][0].city);
console.log(
`Pressed group at index: ${groupIndex} - ${testData[groupIndex][0].city}`
);
};
return (
<SafeAreaView style={styles.container}>
<Text style={styles.header}>Card Stack Demo</Text>
{/* Display selected group info */}
<View style={styles.infoContainer}>
{selectedGroup !== null ? (
<Text style={styles.infoText}>Selected Group: {selectedGroup}</Text>
) : (
<Text style={styles.placeholderText}>Tap a card group to select</Text>
)}
</View>
{/* Spacer before the card stack */}
<View style={styles.spacer} />
{/* Card Stack Component */}
<CardStack
data={testData}
renderCard={(item, groupIndex, cardIndex) => (
<View style={{ padding: 10 }}>
<Text>{item.city}</Text>
</View>
)}
cardHeight={400}
cardPadding={50}
cardSpace={10}
topOffset={200}
onCardPress={handleCardPress}
/>
</SafeAreaView>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#f5f5f5",
},
header: {
fontSize: 24,
fontWeight: "bold",
padding: 20,
textAlign: "center",
},
infoContainer: {
paddingHorizontal: 20,
paddingVertical: 10,
alignItems: "center",
},
infoText: {
fontSize: 18,
color: "#fff",
backgroundColor: "#4CAF50",
padding: 10,
borderRadius: 8,
},
placeholderText: {
fontSize: 16,
color: "#666",
},
spacer: {
height: 200, // Reduced from 300 for better balance
},
cardContent: {
padding: 15,
backgroundColor: "#fff",
borderRadius: 8,
height: "100%", // Ensure it fills the card height
justifyContent: "center",
},
cardTitle: {
fontSize: 20,
fontWeight: "bold",
marginBottom: 5,
},
cardDescription: {
fontSize: 14,
color: "#333",
},
});
export default Base;
export const testData = [
// New York
[
{ city: 'New York', sold: 75 },
{ city: 'New York', sold: 60 },
],
// Philadelphia
[
{ city: 'Philadelphia', sold: 85 },
{ city: 'Philadelphia', sold: 65 },
],
// Los Angeles
[
{ city: 'Los Angeles', sold: 40 },
{ city: 'Los Angeles', sold: 70 },
],
// Chicago
[
{ city: 'Chicago', sold: 55 },
{ city: 'Chicago', sold: 45 },
],
// Miami
[
{ city: 'Miami', sold: 65 },
{ city: 'Miami', sold: 50 },
],
];Props
SmartyPants converts ASCII punctuation characters into "smart" typographic punctuation HTML entities. For example:
Props
| Prop | ASCII Type | ASCII Default | Description |
| -------------------- | ----------------------------------------------------------------- | ----------------------------------------------------- | ------------------------------------------------------------------------------ |
| data | T[][] | Required | Array of card groups, where each group is an array of card data objects. |
| renderCard | (item: T, groupIndex: number, cardIndex: number) => JSX.Element | Required | Function to render each card, receiving the item, group index, and card index. |
| cardHeight | number | 400 | Height of each card in pixels. |
| cardPadding | number | 57 | Padding between card groups in the animation. |
| cardSpace | number | 6 | Space between cards within a group in the animation. |
| topOffset | number | Dimensions.get('window').height * 0.35 | Top offset for the stack animation trigger. |
| keyExtractor | (item: T[], groupIndex: number) => string | (item, index) => ${index} | Key extractor for card groups. |
| cardKeyExtractor | (item: T, cardIndex: number, groupIndex: number) => string | (item, index, groupIndex) => ${groupIndex}-${index} | Key extractor for cards within a group. |
| onCardPress | (groupIndex: number) => void | undefined | Callback when a card group is pressed, receives the group index. |
| flatListProps | Partial<FlatListProps<T[]>> | undefined | Additional props for the outer FlatList. |
| innerFlatListProps | Partial<FlatListProps<T>> | undefined | Additional props for the inner FlatList (per group). |
