Custom underline Tabbar for react native
react-native-underline-tabbar
Custom Tabbar for https://github.com/skv-headless/react-native-scrollable-tab-view. It consists of some features e.g. scrollable content in tabs. Animations are build on matrix transformations and fully compatible with Animated library. In a new version there was significant improvement of tabbar behaviour.
Contribution
Issues are welcome. Please add a screenshot of bug and code snippet. Quickest way to solve issue is to reproduce it on one of the examples.
Pull requests are welcome. If you want to change API or making something big better to create issue and discuss it first. Before submiting PR please run eslint .
Also all eslint fixes are welcome.
Please attach video or gif to PR's and issues it is super helpful.
Instalation
npm install react-native-underline-tabbar --save
Or using Yarn
yarn add react-native-underline-tabbar
Showcase
Documentation
Property | Type | Default | Description |
---|---|---|---|
tabs |
{ label: string, badge:string, badgeColor?: string, [string]: any}[] |
required |
You don't have to pass this prop directly to tabbar. Istead, it's automatically passed from ScrollableTabView from tabLabel of your page. In defaultTabbar it is used only to pass a label, but we use it to pass there information about badges. Example tabLabel={{label: "Page #4", badge: 8, badgeColor: 'violet'}} . Also you can pass any data you need as it's used as Map |
underlineColor |
string |
"navy" |
Set a color for underline. You can use also transparent to hide underline |
underlineHeight |
number |
2 |
Set a height for underline |
underlineBottomPosition |
number |
0 |
Set a bottom for underline |
tabBarStyle |
Object |
{} |
Set styles to TabBar container |
activeTabTextStyle |
Object |
{} |
Set styles to text in tabs while tab is active |
tabBarTextStyle |
Object |
{} |
Set styles to text in tabs |
tabBadgeColor |
string |
{} |
Set a common color for all badges. To set badgeColor individually use badgeColor in tab property |
tabMargin |
number |
20 |
Set space between tabs |
tabStyles |
{ tab?: Object, badgeBubble?: Object, badgeText?: Object } |
{ tab: {}, badgeBubble: {}, badgeText: {} } |
Set styles for every tab and bubble |
Simple Usage
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View
} from 'react-native';
import ScrollableTabView from 'react-native-scrollable-tab-view';
import TabBar from "react-native-underline-tabbar";
const Page = ({label}) => (
<View style={styles.container}>
<Text style={styles.welcome}>
{label}
</Text>
<Text style={styles.instructions}>
To get started, edit index.ios.js
</Text>
<Text style={styles.instructions}>
Press Cmd+R to reload,{'\n'}
Cmd+D or shake for dev menu
</Text>
</View>
);
class example extends Component {
render() {
return (
<View style={[styles.container, {paddingTop: 20}]}>
<ScrollableTabView
tabBarActiveTextColor="#53ac49"
renderTabBar={() => <TabBar underlineColor="#53ac49" />}>
<Page tabLabel={{label: "Page #1"}} label="Page #1"/>
<Page tabLabel={{label: "Page #2 aka Long!", badge: 3}} label="Page #2 aka Long!"/>
<Page tabLabel={{label: "Page #3"}} label="Page #3"/>
<Page tabLabel={{label: "Page #4 aka Page"}} label="Page #4 aka Page"/>
<Page tabLabel={{label: "Page #5"}} label="Page #5"/>
</ScrollableTabView>
</View>
);
}
}
Advanced usage
import React, { Component } from 'react';
import { StyleSheet, Text, View, TouchableOpacity, Animated } from 'react-native';
import ScrollableTabView from 'react-native-scrollable-tab-view';
import TabBar from 'react-native-underline-tabbar';
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
instructions: {
textAlign: 'center',
color: '#333333',
marginBottom: 5,
fontSize: 28,
},
});
const Page = ({label, text = ''}) => (
<View style={styles.container}>
<Text style={styles.welcome}>
{label}
</Text>
<Text style={styles.instructions}>
{text}
</Text>
</View>
);
const iconsSet = {
hot: require('./images/ic_whatshot.png'),
trending: require('./images/ic_trending_up.png'),
fresh: require('./images/ic_fiber_new.png'),
funny: require('./images/ic_tag_faces.png'),
movieAndTv: require('./images/ic_live_tv.png'),
sport: require('./images/ic_rowing.png'),
};
const Tab = ({ tab, page, isTabActive, onPressHandler, onTabLayout, styles }) => {
const { label, icon } = tab;
const style = {
marginHorizontal: 20,
paddingVertical: 10,
};
const containerStyle = {
paddingHorizontal: 20,
paddingVertical: 5,
borderRadius: 25,
flexDirection: 'row',
alignItems: 'center',
backgroundColor: styles.backgroundColor,
opacity: styles.opacity,
transform: [{ scale: styles.opacity }],
};
const textStyle = {
color: styles.textColor,
fontWeight: '600',
};
const iconStyle = {
tintColor: styles.textColor,
resizeMode: 'contain',
width: 22,
height: 22,
marginLeft: 10,
};
return (
<TouchableOpacity style={style} onPress={onPressHandler} onLayout={onTabLayout} key={page}>
<Animated.View style={containerStyle}>
<Animated.Text style={textStyle}>{label}</Animated.Text>
<Animated.Image style={iconStyle} source={icon} />
</Animated.View>
</TouchableOpacity>
);
};
class UnderlineTabBarExample extends Component {
_scrollX = new Animated.Value(0);
// 6 is a quantity of tabs
interpolators = Array.from({ length: 6 }, (_, i) => i).map(idx => ({
scale: this._scrollX.interpolate({
inputRange: [idx - 1, idx, idx + 1],
outputRange: [1, 1.2, 1],
extrapolate: 'clamp',
}),
opacity: this._scrollX.interpolate({
inputRange: [idx - 1, idx, idx + 1],
outputRange: [0.9, 1, 0.9],
extrapolate: 'clamp',
}),
textColor: this._scrollX.interpolate({
inputRange: [idx - 1, idx, idx + 1],
outputRange: ['#000', '#fff', '#000'],
}),
backgroundColor: this._scrollX.interpolate({
inputRange: [idx - 1, idx, idx + 1],
outputRange: ['rgba(0,0,0,0.1)', '#000', 'rgba(0,0,0,0.1)'],
extrapolate: 'clamp',
}),
}));
render() {
return (
<View style={[styles.container, { paddingTop: 20 }]}>
<ScrollableTabView
renderTabBar={() => (
<TabBar
underlineColor="#000"
tabBarStyle={{ backgroundColor: "#fff", borderTopColor: '#d2d2d2', borderTopWidth: 1 }}
renderTab={(tab, page, isTabActive, onPressHandler, onTabLayout) => (
<Tab
key={page}
tab={tab}
page={page}
isTabActive={isTabActive}
onPressHandler={onPressHandler}
onTabLayout={onTabLayout}
styles={this.interpolators[page]}
/>
)}
/>
)}
onScroll={(x) => this._scrollX.setValue(x)}
>
<Page tabLabel={{label: "Hot", icon: iconsSet.hot}} label="Page #1 Hot" text="You can pass your own views to TabBar!"/>
<Page tabLabel={{label: "Trending", icon: iconsSet.trending}} label="Page #2 Trending" text="Yehoo!!!"/>
<Page tabLabel={{label: "Fresh", icon: iconsSet.fresh}} label="Page #3 Fresh" text="Hooray!"/>
<Page tabLabel={{label: "Funny", icon: iconsSet.funny}} label="Page #4 Funny"/>
<Page tabLabel={{label: "Movie & TV", icon: iconsSet.movieAndTv}} label="Page #5 Movie & TV"/>
<Page tabLabel={{label: "Sport", icon: iconsSet.sport}} label="Page #6 Sport"/>
</ScrollableTabView>
</View>
);
}
}
Notice! In case of using this tabbar we must pass object into tabLabel property. It is necessary to set labels and badges.