Skip to content

Commit c31ebd4

Browse files
committed
Initial Commit
1 parent 77e6441 commit c31ebd4

File tree

3 files changed

+378
-1
lines changed

3 files changed

+378
-1
lines changed

README.md

Lines changed: 122 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,122 @@
1-
# react-native-ui-segmented-control
1+
# react-native-segmented-control-ui(for Android/iOS) 🚀
2+
[![npm](https://img.shields.io/npm/v/react-native-segmented-control-ui.svg?style=flat-square "npm version")](https://www.npmjs.com/package/react-native-segmented-control-ui)
3+
[![Monthly Downloads](https://img.shields.io/npm/dm/react-native-segmented-control-ui.svg?style=flat-square )](https://npmjs.org/package/react-native-segmented-control-ui)
4+
[![GitHub stars](https://img.shields.io/github/stars/kirankalyan5/react-native-segmented-control-ui.svg?style=flat)](https://npmjs.org/package/react-native-segmented-control-ui)
5+
[ ![PRs Welcome](https://img.shields.io/badge/PRs-Welcome-brightgreen.svg?style=flat-square )](https://github.com/gbhasha/react-native-segmented-control-ui/pulls)
6+
7+
[![NPM](https://nodei.co/npm/react-native-segmented-control-ui.png?compact=true)](https://npmjs.org/package/react-native-segmented-control-ui)
8+
9+
10+
A react native component similar to iOS SegmentedControl, Primarily built to support both IOS and Android.
11+
12+
13+
## Usage
14+
15+
```javascript
16+
import SegmentedControlTab from 'react-native-segmented-control-ui'
17+
18+
class ConsumerComponent extends Component {
19+
20+
constructor(){
21+
super()
22+
this.state = {
23+
selectedIndex: 0,
24+
};
25+
}
26+
27+
handleIndexChange = (index) => {
28+
this.setState({
29+
...this.state,
30+
selectedIndex: index,
31+
});
32+
}
33+
34+
render() {
35+
return (
36+
<View>
37+
<SegmentedControlTab
38+
values={['First', 'Second', 'Third']}
39+
selectedIndex={this.state.selectedIndex}
40+
onTabPress={this.handleIndexChange}
41+
/>
42+
</View>
43+
);
44+
}
45+
}
46+
```
47+
48+
## Props
49+
Name | Description | Default | Type
50+
------|-------------|----------|-----------
51+
values | titles of tabs | `['One', 'Two', 'Three']` | array
52+
selectedIndex | index of tab item to be selected initially| [0] | number
53+
selectedIndices |Array of indices of tab items to be selected initially - when multiple prop is true else it will take selectedIndex| [0] | arrayOf(PropTypes.number)
54+
borderRadius | borderRadius of whole tab | 5 | number
55+
tabsContainerStyle | external styles can be passed to override the default styles of the segmentedControl wrapper| base styles added in SegmentedControlTab.js | object(styles)
56+
tabStyle | external styles can be passed to override the default styles of the tabs| base styles added in SegmentedControlTab.js | object(styles)
57+
tabTextStyle | external styles can be passed to override the default styles of the tab title| base styles added in SegmentedControlTab.js | object(styles)
58+
activeTabStyle | external styles can be passed to override the default styles of the active tab| base styles added in SegmentedControlTab.js | object(styles)
59+
activeTabTextStyle | external styles can be passed to override the default styles of the active tab text| base styles added in SegmentedControlTab.js | object(styles)
60+
badges | badges values to display | `[1, 2, 3]` | array
61+
tabBadgeContainerStyle | external style can be passed to override the default style of the badge container | base styles added in SegmentedControlTab.js | object(styles)
62+
activeTabBadgeContainerStyle | external style can be passed to override the default style of the active badge container | base styles added in SegmentedControlTab.js | object(styles)
63+
tabBadgeStyle | external style can be passed to override the default style of the badge text | base styles added in SegmentedControlTab.js | object(styles)
64+
activeTabBadgeStyle | external style can be passed to override the default style of the active badge text | base styles added in SegmentedControlTab.js | object(styles)
65+
onTabPress | call-back function when a tab is selected | () => {} | func
66+
allowFontScaling | whether the segment & badge text should allow font scaling (default matches React Native default) | true | bool
67+
accessible | enables accessibility for each tab | true | bool
68+
accessibilityLabels | Reads out the given text on each tab press when voice over is enabled. If not set, uses the text passed in as values in props as a fallback | ['Label 1', 'Label 2', 'Label 3'] | array
69+
70+
71+
## Custom styling
72+
```javascript
73+
<SegmentedControlTab tabsContainerStyle={styles.tabsContainerStyle}
74+
tabStyle={styles.tabStyle}
75+
tabTextStyle={styles.tabTextStyle}
76+
activeTabStyle={styles.activeTabStyle}
77+
activeTabTextStyle={styles.activeTabTextStyle}
78+
selectedIndex={1}
79+
allowFontScaling={false}
80+
values={['First', 'Second', 'Third']}
81+
onPress= {index => this.setState({selected:index})}
82+
/>
83+
84+
const styles = StyleSheet.create({
85+
tabsContainerStyle: {
86+
//custom styles
87+
},
88+
tabStyle: {
89+
//custom styles
90+
},
91+
tabTextStyle: {
92+
//custom styles
93+
},
94+
activeTabStyle: {
95+
//custom styles
96+
},
97+
activeTabTextStyle: {
98+
//custom styles
99+
},
100+
tabBadgeContainerStyle: {
101+
//custom styles
102+
},
103+
activeTabBadgeContainerStyle: {
104+
//custom styles
105+
},
106+
tabBadgeStyle: {
107+
//custom styles
108+
},
109+
activeTabBadgeStyle: {
110+
//custom styles
111+
}
112+
113+
})
114+
115+
```
116+
117+
## P.S.
118+
🙏 credits to all the other devs who had built the similar concept, had referred some of the their components on the github, to get a fair idea 💡 to build this.😊
119+
If you have any idea in implementing this further, let me know or you can update it and raise a PR.😊🚀
120+
121+
## License
122+
*MIT*

index.js

Lines changed: 232 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,232 @@
1+
import React from 'react'
2+
import { View, ViewPropTypes, TouchableOpacity, StyleSheet, Text } from 'react-native'
3+
import PropTypes from 'prop-types'
4+
5+
const handleTabPress = (index, selectedIndex, onTabPress) => {
6+
selectedIndex !== index && onTabPress(index)
7+
}
8+
9+
const TabOption = ({
10+
isTabActive, index, badge, text,
11+
firstTabStyle, lastTabStyle,
12+
tabStyle, activeTabStyle,
13+
tabTextStyle, activeTabTextStyle,
14+
tabBadgeContainerStyle, activeTabBadgeContainerStyle,
15+
tabBadgeStyle, activeTabBadgeStyle,
16+
onTabPress, textNumberOfLines,
17+
allowFontScaling,
18+
accessible,
19+
accessibilityLabel,
20+
}) => {
21+
return (
22+
<TouchableOpacity style={[
23+
styles.tabStyle,
24+
tabStyle,
25+
isTabActive ? [styles.activeTabStyle, activeTabStyle] : {},
26+
firstTabStyle,
27+
lastTabStyle]}
28+
accessible={accessible}
29+
accessibilityLabel={accessibilityLabel}
30+
accessibilityTraits={isTabActive ? "selected" : "button"}
31+
accessibilityComponentType={"button"}
32+
onPress={() => onTabPress(index)}
33+
activeOpacity={1}>
34+
<View style={{ flexDirection: "row" }}>
35+
<Text style={[
36+
styles.tabTextStyle,
37+
tabTextStyle,
38+
isTabActive ? [styles.activeTabTextStyle, activeTabTextStyle] : {}]}
39+
numberOfLines={textNumberOfLines}
40+
allowFontScaling={allowFontScaling}
41+
ellipsizeMode="tail">
42+
{text}
43+
</Text>
44+
{
45+
badge ?
46+
<View style={[
47+
styles.tabBadgeContainerStyle,
48+
tabBadgeContainerStyle,
49+
isTabActive ? [styles.activeTabBadgeContainerStyle, activeTabBadgeContainerStyle] : {}]}>
50+
<Text style={[
51+
styles.tabBadgeStyle,
52+
tabBadgeStyle,
53+
isTabActive ? [styles.activeTabBadgeStyle, activeTabBadgeStyle] : {}]}
54+
allowFontScaling={allowFontScaling}>
55+
{badge}
56+
</Text>
57+
</View> : false
58+
}
59+
</View>
60+
</TouchableOpacity>
61+
)
62+
}
63+
64+
const getAccessibilityLabelByIndex = (accessibilityLabels, index) => {
65+
return accessibilityLabels && accessibilityLabels.length > 0 && accessibilityLabels[index] ? accessibilityLabels[index] : undefined
66+
}
67+
68+
const SegmentedControlTab = ({
69+
selectedIndex, selectedIndices, values,
70+
badges, borderRadius, tabsContainerStyle,
71+
tabStyle, activeTabStyle,
72+
tabTextStyle, activeTabTextStyle,
73+
tabBadgeContainerStyle, activeTabBadgeContainerStyle,
74+
tabBadgeStyle, activeTabBadgeStyle,
75+
onTabPress, textNumberOfLines,
76+
allowFontScaling,
77+
accessible,
78+
accessibilityLabels,
79+
}) => {
80+
81+
const firstTabStyle = [{ borderRightWidth: values.length == 2 ? 1 : 0, borderTopLeftRadius: borderRadius, borderBottomLeftRadius: borderRadius }]
82+
const lastTabStyle = [{ borderLeftWidth: 0, borderTopRightRadius: borderRadius, borderBottomRightRadius: borderRadius }]
83+
84+
return (
85+
<View
86+
style={[styles.tabsContainerStyle, tabsContainerStyle]}
87+
removeClippedSubviews={false}>
88+
{
89+
values.map((item, index) => {
90+
const accessibilityText = getAccessibilityLabelByIndex(accessibilityLabels, index)
91+
return (
92+
<TabOption
93+
key={index}
94+
index={index}
95+
badge={badges && badges[index] ? badges[index] : false}
96+
isTabActive={selectedIndex === index}
97+
text={item}
98+
textNumberOfLines={textNumberOfLines}
99+
onTabPress={(index) => handleTabPress(index, selectedIndex, onTabPress)}
100+
firstTabStyle={index === 0 ? [{ borderRightWidth: 0 }, firstTabStyle] : {}}
101+
lastTabStyle={index === values.length - 1 ? [{ borderLeftWidth: 0 }, lastTabStyle] : {}}
102+
tabStyle={[tabStyle, index !== 0 && index !== values.length - 1 ? { marginLeft: -1 } : {}]}
103+
activeTabStyle={activeTabStyle}
104+
tabTextStyle={tabTextStyle}
105+
activeTabTextStyle={activeTabTextStyle}
106+
tabBadgeContainerStyle={tabBadgeContainerStyle}
107+
activeTabBadgeContainerStyle={activeTabBadgeContainerStyle}
108+
tabBadgeStyle={tabBadgeStyle}
109+
activeTabBadgeStyle={activeTabBadgeStyle}
110+
allowFontScaling={allowFontScaling}
111+
accessible={accessible}
112+
accessibilityLabel={accessibilityText ? accessibilityText : item }
113+
/>
114+
)
115+
})
116+
}
117+
</View>
118+
)
119+
}
120+
121+
SegmentedControlTab.propTypes = {
122+
accessibilityLabels: PropTypes.arrayOf(PropTypes.string),
123+
accessible: PropTypes.bool,
124+
activeTabBadgeContainerStyle: Text.propTypes.style,
125+
activeTabBadgeStyle: Text.propTypes.style,
126+
activeTabStyle: ViewPropTypes.style,
127+
activeTabTextStyle: Text.propTypes.style,
128+
allowFontScaling: PropTypes.bool,
129+
badges: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.number, PropTypes.string])),
130+
borderRadius: PropTypes.number,
131+
onTabPress: PropTypes.func,
132+
selectedIndex: PropTypes.number,
133+
selectedIndices: PropTypes.arrayOf(PropTypes.number),
134+
tabBadgeContainerStyle: Text.propTypes.style,
135+
tabBadgeStyle: Text.propTypes.style,
136+
tabStyle: ViewPropTypes.style,
137+
tabTextStyle: Text.propTypes.style,
138+
tabsContainerStyle: ViewPropTypes.style,
139+
textNumberOfLines: PropTypes.number,
140+
values: PropTypes.arrayOf(PropTypes.string),
141+
}
142+
143+
TabOption.propTypes = {
144+
accessibilityLabel: PropTypes.string,
145+
accessible: PropTypes.bool,
146+
activeTabBadgeContainerStyle: Text.propTypes.style,
147+
activeTabBadgeStyle: Text.propTypes.style,
148+
activeTabStyle: ViewPropTypes.style,
149+
activeTabTextStyle: Text.propTypes.style,
150+
allowFontScaling: PropTypes.bool,
151+
badge: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
152+
firstTabStyle: PropTypes.arrayOf(PropTypes.object),
153+
index: PropTypes.number,
154+
isTabActive: PropTypes.bool,
155+
lastTabStyle: PropTypes.arrayOf(PropTypes.object),
156+
onTabPress: PropTypes.func,
157+
tabBadgeContainerStyle: Text.propTypes.style,
158+
tabBadgeStyle: Text.propTypes.style,
159+
tabStyle: ViewPropTypes.style,
160+
tabTextStyle: Text.propTypes.style,
161+
tabsContainerStyle: ViewPropTypes.style,
162+
text: PropTypes.string,
163+
textNumberOfLines: PropTypes.number,
164+
}
165+
166+
SegmentedControlTab.defaultProps = {
167+
values: ['One', 'Two', 'Three'],
168+
accessible: true,
169+
accessibilityLabels: [],
170+
badges: ['', '', ''],
171+
selectedIndex: 0,
172+
selectedIndices: [0],
173+
onTabPress: () => { },
174+
tabsContainerStyle: {},
175+
tabStyle: {},
176+
activeTabStyle: {},
177+
tabTextStyle: {},
178+
activeTabTextStyle: {},
179+
tabBadgeContainerStyle: {},
180+
activeTabBadgeContainerStyle: {},
181+
tabBadgeStyle: {},
182+
activeTabBadgeStyle: {},
183+
borderRadius: 5,
184+
textNumberOfLines: 1,
185+
allowFontScaling: true,
186+
}
187+
188+
const styles = StyleSheet.create({
189+
tabsContainerStyle: {
190+
backgroundColor: 'transparent',
191+
flexDirection: 'row',
192+
},
193+
tabStyle: {
194+
paddingVertical: 5,
195+
flex: 1,
196+
justifyContent: 'center',
197+
alignItems: 'center',
198+
borderColor: '#0076FF',
199+
borderWidth: 1,
200+
backgroundColor: 'white',
201+
},
202+
activeTabStyle: {
203+
backgroundColor: '#0076FF'
204+
},
205+
tabTextStyle: {
206+
color: '#0076FF'
207+
},
208+
activeTabTextStyle: {
209+
color: 'white'
210+
},
211+
tabBadgeContainerStyle: {
212+
borderRadius: 20,
213+
backgroundColor: 'red',
214+
paddingLeft: 5,
215+
paddingRight: 5,
216+
marginLeft: 5,
217+
marginBottom: 3
218+
},
219+
activeTabBadgeContainerStyle: {
220+
backgroundColor: 'white'
221+
},
222+
tabBadgeStyle: {
223+
color: 'white',
224+
fontSize: 11,
225+
fontWeight: 'bold'
226+
},
227+
activeTabBadgeStyle: {
228+
color: 'black'
229+
}
230+
})
231+
232+
export default SegmentedControlTab

package.json

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
{
2+
"name": "react-native-segmented-control-ui",
3+
"version": "1.0.0",
4+
"description": "SegmentedControl using react-native,support android and ios",
5+
"main": "index.js",
6+
"scripts": {
7+
"test": "echo \"Error: no test specified\" && exit 1"
8+
},
9+
"repository": {
10+
"type": "git",
11+
"url": "git+https://github.com/gbhasha/react-native-segmented-control-ui.git"
12+
},
13+
"keywords": [
14+
"SegmentedControl",
15+
"react-native",
16+
"ui-components"
17+
],
18+
"author": "Galeel Bhasha Satthar <gbhasha@gmail.com>",
19+
"license": "MIT",
20+
"bugs": {
21+
"url": "https://github.com/gbhasha/react-native-segmented-control-ui/issues"
22+
},
23+
"homepage": "https://github.com/gbhasha/react-native-segmented-control-ui#readme"
24+
}

0 commit comments

Comments
 (0)