UNPKG

react-native-wallet-card-stack

Version:

A customizable React Native component for displaying animated stacks of card groups with smooth scrolling and TypeScript support.

195 lines (158 loc) 7.72 kB
# 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. ![Demo Image](assets/demo.png) ### Check out the `CardStack` component in action: [Demo Video](https://www.youtube.com/shorts/y9ets6PTXmY) ## 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). | ``` ```