react-native-curved-tab-bar
Version:
A customizable curved tab bar component for React Native with smooth animations
337 lines (273 loc) • 9.29 kB
Markdown
# React Native Curved Tab Bar
A beautiful, customizable curved tab bar component for React Native with smooth animations and floating active tab button.
## Features
- 🎨 Customizable gradient backgrounds (pure SVG, no external dependencies)
- 🎯 Smooth spring animations
- 📱 Responsive design that adapts to different screen sizes
- 🔧 Highly configurable with TypeScript support
- 📋 Badge support for notifications
- ⌨️ Optional keyboard hiding
- 🎭 Custom icons and styling
- 📱 iOS and Android compatible
- 🚀 Lightweight with minimal dependencies (only react-native-svg required)
## 📱 Demo
<p>
<img src="https://raw.githubusercontent.com/AshharImam/react-native-curved-tab-bar/main/assets/animatedTabGif.gif" width="300" />
</p>
## Installation
```bash
npm install react-native-curved-tab-bar
# or
yarn add react-native-curved-tab-bar
```
### Peer Dependencies
Make sure you have this peer dependency installed:
```bash
npm install react-native-svg
# or
yarn add react-native-svg
```
#### Additional Setup
**For react-native-svg:**
- Follow the installation guide: https://github.com/react-native-svg/react-native-svg
## Basic Usage
```tsx
import React, { useState } from 'react';
import { View } from 'react-native';
import { CurvedTabBar, TabItem } from 'react-native-curved-tab-bar';
const tabs: TabItem[] = [
{
key: 'home',
label: 'Home',
icon: require('./assets/home-icon.png'),
},
{
key: 'search',
label: 'Search',
icon: require('./assets/search-icon.png'),
},
{
key: 'profile',
label: 'Profile',
icon: require('./assets/profile-icon.png'),
badgeCount: 3,
},
];
const App = () => {
const [activeTab, setActiveTab] = useState(0);
const handleTabPress = (index: number, tab: TabItem) => {
setActiveTab(index);
// Handle navigation or other logic here
console.log('Tab pressed:', tab.key);
};
return (
<View style={{ flex: 1 }}>
{/* Your app content */}
<CurvedTabBar
tabs={tabs}
activeIndex={activeTab}
onTabPress={handleTabPress}
gradientColors={['#6366f1', '#8b5cf6']}
/>
</View>
);
};
export default App;
```
## Advanced Usage
```tsx
import React, { useState } from 'react';
import { CurvedTabBar, TabItem } from 'react-native-curved-tab-bar';
const tabs: TabItem[] = [
{
key: 'dashboard',
label: 'Dashboard',
icon: require('./assets/dashboard.png'),
},
{
key: 'analytics',
label: 'Analytics',
icon: require('./assets/analytics.png'),
badgeCount: 12,
},
{
key: 'settings',
label: 'Settings',
icon: require('./assets/settings.png'),
},
];
const AdvancedExample = () => {
const [activeTab, setActiveTab] = useState(0);
return (
<CurvedTabBar
tabs={tabs}
activeIndex={activeTab}
onTabPress={(index, tab) => {
setActiveTab(index);
// Custom logic for each tab
if (tab.key === 'analytics') {
// Navigate to analytics screen
}
}}
gradientColors={['#ff6b6b', '#feca57']}
heightPercentage={10}
floatingButtonSize={7}
activeIconColor="#ffffff"
inactiveIconColor="#999999"
activeTextColor="#333333"
inactiveTextColor="#999999"
fontSize={14}
fontFamily="Arial"
hideOnKeyboard={true}
springConfig={{
damping: 15,
stiffness: 150,
}}
shadowConfig={{
shadowColor: '#000',
shadowOffset: { width: 0, height: 5 },
shadowOpacity: 0.3,
shadowRadius: 25,
elevation: 10,
}}
/>
);
};
```
## Props
| Prop | Type | Default | Description |
| -------------------- | --------------------------------------- | ------------------------------- | --------------------------------------------------- |
| `tabs` | `TabItem[]` | **Required** | Array of tab items |
| `activeIndex` | `number` | **Required** | Currently active tab index |
| `onTabPress` | `(index: number, tab: TabItem) => void` | **Required** | Callback when tab is pressed |
| `gradientColors` | `string[]` | `['#6366f1', '#8b5cf6']` | Background gradient colors |
| `heightPercentage` | `number` | `9` | Tab bar height as percentage of screen height |
| `floatingButtonSize` | `number` | `6` | Floating button size as percentage of screen height |
| `activeIconColor` | `string` | `'#ffffff'` | Active tab icon tint color |
| `inactiveIconColor` | `string` | `'#cccccc'` | Inactive tab icon tint color |
| `activeTextColor` | `string` | `activeIconColor` | Active tab text color |
| `inactiveTextColor` | `string` | `'#cccccc'` | Inactive tab text color |
| `fontSize` | `number` | `12` | Tab label font size |
| `fontFamily` | `string` | `undefined` | Custom font family for labels |
| `hideOnKeyboard` | `boolean` | `false` | Hide tab bar when keyboard is visible |
| `springConfig` | `object` | `{damping: 12, stiffness: 120}` | Animation spring configuration |
| `shadowConfig` | `object` | See below | Shadow configuration for floating button |
### TabItem Interface
```tsx
interface TabItem {
key: string; // Unique identifier
label: string; // Display label
icon: any; // Icon source (require() or URI)
badgeCount?: number; // Optional badge count
}
```
### Shadow Configuration
```tsx
shadowConfig?: {
shadowColor?: string;
shadowOffset?: { width: number; height: number };
shadowOpacity?: number;
shadowRadius?: number;
elevation?: number; // Android only
}
```
Default shadow configuration:
```tsx
{
shadowColor: '#000',
shadowOffset: { width: 0, height: 3 },
shadowOpacity: 0.2,
shadowRadius: 20,
elevation: 8,
}
```
## Customization Examples
### Single Color Gradient
```tsx
<CurvedTabBar
// ... other props
gradientColors={['#ff6b6b']} // Will use same color for both ends
/>
```
### Custom Colors
```tsx
<CurvedTabBar
// ... other props
gradientColors={['#667eea', '#764ba2']}
activeIconColor="#ffffff"
inactiveIconColor="#a0a0a0"
activeTextColor="#333333"
inactiveTextColor="#888888"
/>
```
### Different Heights and Sizes
```tsx
<CurvedTabBar
// ... other props
heightPercentage={12} // Taller tab bar
floatingButtonSize={8} // Larger floating button
fontSize={16} // Larger text
/>
```
## Integration with Navigation Libraries
### React Navigation v6
```tsx
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import { CurvedTabBar } from 'react-native-curved-tab-bar';
const Tab = createBottomTabNavigator();
function MyTabs() {
return (
<Tab.Navigator tabBar={(props) => <CustomTabBar {...props} />}>
<Tab.Screen name="Home" component={HomeScreen} />
<Tab.Screen name="Search" component={SearchScreen} />
<Tab.Screen name="Profile" component={ProfileScreen} />
</Tab.Navigator>
);
}
function CustomTabBar({ state, navigation }) {
const tabs = state.routes.map((route) => ({
key: route.key,
label: route.name,
icon: getIconForRoute(route.name), // Your icon mapping function
}));
return (
<CurvedTabBar
tabs={tabs}
activeIndex={state.index}
onTabPress={(index) => {
const route = state.routes[index];
navigation.navigate(route.name);
}}
gradientColors={['#6366f1', '#8b5cf6']}
/>
);
}
```
## Troubleshooting
### Icons not showing
Make sure your icon images are properly imported and accessible:
```tsx
// Correct
icon: require('./assets/home.png');
// Also correct for remote images
icon: {
uri: 'https://example.com/icon.png';
}
```
### Animations not smooth
Try adjusting the spring configuration:
```tsx
springConfig={{
damping: 15, // Higher = less bouncy
stiffness: 100, // Higher = faster animation
}}
```
### Tab bar covering content
The tab bar uses absolute positioning. Make sure your content has appropriate bottom padding:
```tsx
<View style={{ flex: 1, paddingBottom: 80 }}>{/* Your content */}</View>
```
## License
MIT
## Contributing
Contributions are welcome! Please feel free to submit a Pull Request.