rn-swipeable-card-carousel
v1.0.1
Published
A beautiful, swipeable card carousel component for React Native with smooth animations and touch gestures
Maintainers
Readme
RN Swipeable Card Carousel
A beautiful, swipeable card carousel component for React Native with smooth animations, touch gestures, and fully customizable styling.
📸 Preview
Features
✨ Smooth Animations - Fluid card transitions with spring animations
👆 Swipe Gestures - Intuitive left/right swipe to navigate cards
🎯 Tap to Select - Tap background cards to bring them to focus
🎨 100% Dynamic - Works with ANY number of cards, all dimensions configurable
🌈 Data-Driven Colors - All colors from your data, no hardcoding
📐 Every Dimension Customizable - Card sizes, fonts, buttons, spacing - everything!
📱 React Native - Works on iOS and Android
⚡ TypeScript Support - Full type definitions included
🪶 Lightweight - Zero dependencies (except React Native peer deps)
🔄 Auto-Positioning - Background cards automatically position themselves
🎛️ 50+ Props - Complete control over every aspect
Installation
npm install rn-swipeable-card-carouselor
yarn add rn-swipeable-card-carouselUsage
Basic Example
import React from 'react';
import { View } from 'react-native';
import { GiftCardCarousel } from 'rn-swipeable-card-carousel';
const App = () => {
const cards = [
{
id: '1',
title: 'Basic Package',
subtitle: 'Coupon Balance',
value: '250 Coupons',
price: '$10',
color: '#48B0A7',
},
{
id: '2',
title: 'Silver Package',
subtitle: 'Coupon Balance',
value: '750 Coupons',
price: '$30',
color: '#97A3A7',
},
{
id: '3',
title: 'Gold Package',
subtitle: 'Coupon Balance',
value: '1500 Coupons',
price: '$50',
color: '#FBCD2C',
},
{
id: '4',
title: 'Diamond Package',
subtitle: 'Coupon Balance',
value: '2000 Coupons',
price: '$75',
color: '#1F313F',
},
];
const handlePurchase = (card) => {
console.log('Purchase:', card.title);
// Handle purchase logic
};
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<GiftCardCarousel
cards={cards}
onPurchase={handlePurchase}
/>
</View>
);
};
export default App;Advanced Example with Custom Styling
import React, { useState } from 'react';
import { View, Alert } from 'react-native';
import { GiftCardCarousel } from 'rn-swipeable-card-carousel';
const App = () => {
const [selectedCard, setSelectedCard] = useState(null);
const cards = [
{
id: 'basic',
title: 'Basic',
subtitle: 'Starter Plan',
value: '100 Credits',
price: '$9.99',
color: '#4ECDC4',
},
{
id: 'pro',
title: 'Pro',
subtitle: 'Professional Plan',
value: '500 Credits',
price: '$29.99',
color: '#F38181',
},
{
id: 'premium',
title: 'Premium',
subtitle: 'Premium Plan',
value: '1000 Credits',
price: '$49.99',
color: '#AA96DA',
},
];
const handlePurchase = (card) => {
Alert.alert(
'Confirm Purchase',
`Purchase ${card.title} package for ${card.price}?`,
[
{ text: 'Cancel', style: 'cancel' },
{
text: 'Buy',
onPress: () => console.log('Purchased:', card.id)
},
]
);
};
const handleCardChange = (card, index) => {
setSelectedCard(card);
console.log('Active card:', card.title, 'at index:', index);
};
return (
<View style={{ flex: 1, justifyContent: 'center', backgroundColor: '#F5F5F5' }}>
<GiftCardCarousel
cards={cards}
initialCardIndex={1}
onPurchase={handlePurchase}
onCardChange={handleCardChange}
purchaseButtonText="Buy Now"
swipeThreshold={60}
containerStyle={{ marginVertical: 20 }}
mainCardStyle={{
shadowColor: '#000',
shadowOffset: { width: 0, height: 10 },
shadowOpacity: 0.3,
shadowRadius: 20,
}}
purchaseButtonStyle={{
backgroundColor: '#FFD700',
}}
purchaseButtonTextStyle={{
fontWeight: '800',
}}
/>
</View>
);
};
export default App;API Reference
📚 See DYNAMIC_FEATURES.md for complete guide on dynamic features!
Core Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| cards | GiftCard[] | required | Array of gift card data - works with ANY number! |
| initialCardIndex | number | 0 | Index of the card to show initially |
| onPurchase | (card: GiftCard) => void | undefined | Callback when purchase button is pressed |
| onCardChange | (card: GiftCard, index: number) => void | undefined | Callback when the active card changes |
Container Dimensions
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| containerStyle | ViewStyle | undefined | Custom styles for the container |
| containerHeight | number | 384 | Height of the card container |
| containerWidth | number | mainCardWidth | Width of the card container |
Main Card Dimensions
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| mainCardStyle | ViewStyle | undefined | Custom styles for the main card |
| mainCardWidth | number | 320 | Width of the main card |
| mainCardHeight | number | 371 | Height of the main card |
| mainCardBorderRadius | number | 20 | Border radius of main card |
| mainCardPaddingVertical | number | 40 | Vertical padding inside main card |
| mainCardPaddingHorizontal | number | 40 | Horizontal padding inside main card |
| mainCardGap | number | 20 | Gap between elements in main card |
Background Card Dimensions
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| backgroundCardStyle | ViewStyle | undefined | Custom styles for background cards |
| backgroundCardWidth | number | 200 | Width of background cards |
| backgroundCardHeight | number | 314 | Height of background cards |
| backgroundCardBorderRadius | number | 20 | Border radius of background cards |
| backgroundCardPaddingVertical | number | 30 | Vertical padding inside background cards |
| backgroundCardPaddingHorizontal | number | 10 | Horizontal padding inside background cards |
| backgroundCardGap | number | 20 | Gap between elements in background cards |
| backgroundCardOpacity | number | 0.6 | Opacity of background cards (0-1) |
Text Styles & Sizes
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| titleStyle | TextStyle | undefined | Custom text styles for card title |
| mainCardTitleFontSize | number | 28 | Font size for main card title |
| backgroundCardTitleFontSize | number | 24 | Font size for background card title |
| subtitleStyle | TextStyle | undefined | Custom text styles for card subtitle |
| mainCardSubtitleFontSize | number | 14 | Font size for main card subtitle |
| backgroundCardSubtitleFontSize | number | 12 | Font size for background card subtitle |
| valueStyle | TextStyle | undefined | Custom text styles for card value |
| mainCardValueFontSize | number | 18 | Font size for main card value |
| backgroundCardValueFontSize | number | 14 | Font size for background card value |
| priceStyle | TextStyle | undefined | Custom text styles for card price |
| priceFontSize | number | 24 | Font size for price |
Button Customization
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| purchaseButtonText | string | "Purchase" | Text for the purchase button |
| purchaseButtonStyle | ViewStyle | undefined | Custom styles for the purchase button |
| purchaseButtonTextStyle | TextStyle | undefined | Custom text styles for purchase button |
| mainCardButtonHeight | number | 74 | Height of main card button |
| mainCardButtonWidth | number | auto | Width of main card button |
| backgroundCardButtonHeight | number | 56 | Height of background card button |
| backgroundCardButtonWidth | number | auto | Width of background card button |
| buttonBorderRadius | number | 10 | Border radius of buttons |
| mainCardButtonFontSize | number | 18 | Font size for main card button text |
| backgroundCardButtonFontSize | number | 14 | Font size for background card button text |
Positioning & Layout
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| backgroundCardRotations | string[] | ['15deg', '-15deg', '5deg', '-5deg'] | Rotation angles (cycles for any card count) |
| backgroundCardOffsets | number[] | [-50, -50, -20, -20] | Horizontal offsets (cycles for any card count) |
| backgroundCardPositions | ('left' \| 'right' \| 'center')[] | ['left', 'right', 'left', 'right'] | Positions (cycles for any card count) |
Gestures & Behavior
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| swipeThreshold | number | 50 | Swipe distance to trigger card change |
| swipeEnabled | boolean | true | Enable/disable swipe gestures |
| tapToSelectEnabled | boolean | true | Enable/disable tap on background cards |
Animation
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| animationDuration | number | 200 | Animation duration in ms |
| animationFriction | number | 9 | Spring friction for animations |
| animationTension | number | 50 | Spring tension for animations |
GiftCard Type
interface GiftCard {
id: string; // Unique identifier
title: string; // Card title
subtitle: string; // Card subtitle
value: string; // Card value (e.g., "250 Coupons")
price: string; // Card price (e.g., "$10")
color: string; // Card background color (hex or named)
buttonTextColor?: string; // Optional: Override button text color for this card
subtitleColor?: string; // Optional: Override subtitle color for this card
}Gestures
- Swipe Left - Navigate to the next card
- Swipe Right - Navigate to the previous card
- Tap Background Card - Bring that card to focus
- Tap Purchase Button - Trigger
onPurchasecallback
Customization Examples
🎨 Dynamic Card Colors (Works with ANY Number!)
// 3 cards
const cards = [
{ id: '1', title: 'Card 1', color: '#FF6B6B', ...data },
{ id: '2', title: 'Card 2', color: '#4ECDC4', ...data },
{ id: '3', title: 'Card 3', color: '#45B7D1', ...data },
];
// 100 cards - auto-generate!
const manyCards = Array.from({ length: 100 }, (_, i) => ({
id: `card-${i}`,
title: `Package ${i + 1}`,
subtitle: 'Dynamic',
value: `${(i + 1) * 100} Credits`,
price: `$${(i + 1) * 5}`,
color: `hsl(${i * 3.6}, 70%, 50%)`, // Rainbow colors!
}));📐 Fully Custom Dimensions
<GiftCardCarousel
cards={cards}
// Main card - make it bigger!
mainCardWidth={400}
mainCardHeight={500}
mainCardBorderRadius={30}
mainCardPaddingVertical={50}
// Background cards
backgroundCardWidth={250}
backgroundCardHeight={400}
// Buttons
mainCardButtonHeight={90}
buttonBorderRadius={20}
// Fonts
mainCardTitleFontSize={32}
priceFontSize={28}
mainCardButtonFontSize={20}
/>🔄 Custom Background Card Positioning
<GiftCardCarousel
cards={cards}
// Define your own pattern (cycles through for any number of cards)
backgroundCardRotations={['25deg', '-25deg', '12deg', '-12deg']}
backgroundCardOffsets={[-70, -70, -35, -35]}
backgroundCardPositions={['left', 'right', 'left', 'right']}
backgroundCardOpacity={0.5}
/>📱 Responsive Sizing
import { Dimensions } from 'react-native';
const { width, height } = Dimensions.get('window');
<GiftCardCarousel
cards={cards}
mainCardWidth={width * 0.85}
mainCardHeight={height * 0.5}
backgroundCardWidth={width * 0.6}
mainCardTitleFontSize={width * 0.07}
priceFontSize={width * 0.06}
/>⚡ Fast Animations
<GiftCardCarousel
cards={cards}
animationDuration={150}
animationFriction={12}
animationTension={70}
/>🎯 Disable Swipe, Enable Tap Only
<GiftCardCarousel
cards={cards}
swipeEnabled={false}
tapToSelectEnabled={true}
/>🌍 Right-to-Left (RTL) Support
For RTL languages like Arabic:
<View style={{ transform: [{ scaleX: -1 }] }}>
<GiftCardCarousel cards={cards} />
</View>🎨 Per-Card Color Overrides
const cards = [
{
id: '1',
title: 'Special',
color: '#1F313F',
buttonTextColor: '#FFD700', // Gold button text
subtitleColor: '#FFFFFF', // White subtitle
...
},
];Requirements
- React Native >= 0.60.0
- React >= 16.8.0
License
MIT © boss-mazhar
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
Support
If you like this package, please ⭐ star it on GitHub!
Changelog
1.0.0
- Initial release
- Swipeable card carousel
- Tap to select functionality
- Fully customizable styling
- TypeScript support
