Skip to content

Commit

Permalink
v4.1.0 #62
Browse files Browse the repository at this point in the history
  • Loading branch information
iRoachie authored Jul 14, 2019
2 parents 53f5c30 + ec1ed7c commit 7684195
Show file tree
Hide file tree
Showing 5 changed files with 214 additions and 79 deletions.
78 changes: 32 additions & 46 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,39 @@ Start using the component

```jsx
import MaterialTabs from 'react-native-material-tabs';
```

## Usage

![Demo](https://user-images.githubusercontent.com/5962998/59991843-f2e43600-9616-11e9-913b-b8fb8a566d68.gif)

```jsx
import React, { useState } from 'react';
import { StyleSheet, SafeAreaView } from 'react-native';
import MaterialTabs from 'react-native-material-tabs';

<MaterialTabs
items={['One', 'Two', 'Three']}
selectedIndex={this.state.selectedTab}
onChange={index => this.setState({ selectedTab: index })}
/>;
const Example = () => {
const [selectedTab, setSelectedTab] = useState(0);

return (
<SafeAreaView style={styles.container}>
<MaterialTabs
items={['One', 'Two', 'Three', 'Four', 'Five']}
selectedIndex={selectedTab}
onChange={setSelectedTab}
barColor="#1fbcd2"
indicatorColor="#fffe94"
activeTextColor="white"
/>
</SafeAreaView>
);
};

const styles = StyleSheet.create({
container: {
flex: 1,
},
});
```

## Available Props
Expand All @@ -67,44 +94,3 @@ import MaterialTabs from 'react-native-material-tabs';
| allowFontScaling | true | boolean | Specifies whether fonts should scale to respect Text Size accessibility settings |
| uppercase | true | boolean | Specifies whether to uppercase the tab labels |
| keyboardShouldPersistTaps | never | string | Specifies how the [ScrollView](https://facebook.github.io/react-native/docs/scrollview#keyboardshouldpersisttaps) should respond to taps while keyboard is open |

## Example

![Demo](https://user-images.githubusercontent.com/5962998/59991843-f2e43600-9616-11e9-913b-b8fb8a566d68.gif)

```jsx
import React from 'react';
import { StyleSheet, Text, SafeAreaView } from 'react-native';
import MaterialTabs from 'react-native-material-tabs';

export default class Example extends React.Component {
state = {
selectedTab: 0,
};

setTab = selectedTab => {
this.setState({ selectedTab });
};

render() {
return (
<SafeAreaView style={styles.container}>
<MaterialTabs
items={['One', 'Two', 'Three', 'Four', 'Five']}
selectedIndex={this.state.selectedTab}
onChange={this.setTab}
barColor="#1fbcd2"
indicatorColor="#fffe94"
activeTextColor="white"
/>
</SafeAreaView>
);
}
}

const styles = StyleSheet.create({
container: {
flex: 1,
},
});
```
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "react-native-material-tabs",
"version": "4.0.0",
"version": "4.1.0",
"description": "Material Design implementation of Tabs",
"keywords": [
"react",
Expand Down
158 changes: 158 additions & 0 deletions src/__tests__/__snapshots__/main.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -480,6 +480,164 @@ exports[`Main should display tab labels not uppercased 1`] = `
</View>
`;

exports[`Main should render scrollable without errors 1`] = `
<View
barColor="#13897b"
barHeight={48}
onLayout={[Function]}
style={
Array [
Object {
"backgroundColor": "#13897b",
"height": 48,
},
]
}
>
<RCTScrollView
horizontal={true}
keyboardShouldPersistTaps="never"
scrollEnabled={true}
showsHorizontalScrollIndicator={false}
>
<View>
<View
barHeight={48}
style={
Array [
Object {
"flexDirection": "row",
"height": 46,
},
]
}
>
<View
accessible={true}
isTVSelectable={true}
onResponderGrant={[Function]}
onResponderMove={[Function]}
onResponderRelease={[Function]}
onResponderTerminate={[Function]}
onResponderTerminationRequest={[Function]}
onStartShouldSetResponder={[Function]}
style={
Object {
"opacity": 1,
"width": 0,
}
}
>
<View
style={
Array [
Object {
"alignItems": "center",
"height": 48,
"justifyContent": "center",
"paddingLeft": 12,
"paddingRight": 12,
},
]
}
tabHeight={48}
>
<Text
allowFontScaling={true}
color="#fff"
style={
Array [
Object {
"color": "#fff",
"fontFamily": "System",
"fontSize": 14,
"fontWeight": "500",
"minWidth": "100%",
"textAlign": "center",
},
Object {},
]
}
>
TAB1
</Text>
</View>
</View>
<View
accessible={true}
isTVSelectable={true}
onResponderGrant={[Function]}
onResponderMove={[Function]}
onResponderRelease={[Function]}
onResponderTerminate={[Function]}
onResponderTerminationRequest={[Function]}
onStartShouldSetResponder={[Function]}
style={
Object {
"opacity": 1,
"width": 0,
}
}
>
<View
style={
Array [
Object {
"alignItems": "center",
"height": 48,
"justifyContent": "center",
"paddingLeft": 12,
"paddingRight": 12,
},
]
}
tabHeight={48}
>
<Text
allowFontScaling={true}
color="rgba(255, 255, 255, 0.7)"
style={
Array [
Object {
"color": "rgba(255, 255, 255, 0.7)",
"fontFamily": "System",
"fontSize": 14,
"fontWeight": "500",
"minWidth": "100%",
"textAlign": "center",
},
Object {},
]
}
>
TAB2
</Text>
</View>
</View>
</View>
<View
color="#fff"
style={
Object {
"backgroundColor": "#fff",
"bottom": 0,
"height": 2,
"position": "absolute",
"transform": Array [
Object {
"translateX": 0,
},
],
"width": 0,
}
}
tabWidth={0}
/>
</View>
</RCTScrollView>
</View>
`;

exports[`Main should render without errors 1`] = `
<View
barColor="#13897b"
Expand Down
7 changes: 7 additions & 0 deletions src/__tests__/main.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,13 @@ describe('Main', () => {
expect(tree).toMatchSnapshot();
});

it('should render scrollable without errors', () => {
const tree = create(
<MaterialTabs selectedIndex={0} items={['Tab1', 'Tab2']} scrollable />
).toJSON();
expect(tree).toMatchSnapshot();
});

it('should render with correct tabs', () => {
const wrapper = shallow(component);
const tabs = wrapper.find('Tab');
Expand Down
48 changes: 16 additions & 32 deletions src/components/MaterialTabs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
ScrollViewProps,
StyleProp,
TextStyle,
I18nManager,
} from 'react-native';

import Tab from './Tab';
Expand Down Expand Up @@ -69,43 +70,24 @@ const MaterialTabs: React.FC<Props> = ({
const getAnimateValues = () => {
const scrollValue = !scrollable ? tabWidth : barWidth * 0.4;

const indicator = I18nManager.isRTL
? -selectedIndex * scrollValue
: selectedIndex * scrollValue;

// All props for fixed tabs are the same
if (!scrollable) {
return {
indicatorPosition:
selectedIndex === 0 ? 0 : selectedIndex * scrollValue,
indicatorPosition: indicator,
scrollPosition: 0,
};
}

switch (selectedIndex) {
case 0: // First tab
return {
indicatorPosition: 0,
scrollPosition: 0,
};
case 1: // Second tab
return {
indicatorPosition: barWidth * 0.5 - scrollValue / 4,
scrollPosition: scrollValue * 0.25,
};
case items.length - 1: // Last tab
return {
indicatorPosition:
scrollValue * (selectedIndex - 1) +
(barWidth * 0.5 - scrollValue / 4),
scrollPosition: scrollValue * (selectedIndex - 2) + scrollValue * 0.5,
};
default:
// Any tabs between second and last
return {
indicatorPosition:
scrollValue * (selectedIndex - 1) +
(barWidth * 0.5 - scrollValue / 4),
scrollPosition:
scrollValue * 0.25 + scrollValue * (selectedIndex - 1),
};
}
return {
indicatorPosition: indicator,
scrollPosition: I18nManager.isRTL
? scrollValue * 0.25 + scrollValue * (items.length - selectedIndex - 2)
: scrollValue * 0.25 + scrollValue * (selectedIndex - 1),
};
};

const getTabWidth = (width: number) => {
Expand All @@ -117,16 +99,18 @@ const MaterialTabs: React.FC<Props> = ({
};

const selectTab = () => {
const values = getAnimateValues();

Animated.spring(indicatorPosition, {
toValue: getAnimateValues().indicatorPosition,
toValue: values.indicatorPosition,
tension: 300,
friction: 20,
useNativeDriver: true,
}).start();

if (scrollView.current) {
scrollView.current.scrollTo({
x: getAnimateValues().scrollPosition,
x: values.scrollPosition,
});
}
};
Expand Down

0 comments on commit 7684195

Please sign in to comment.