Skip to content

An extension to react-native-tab-view which provides a vertical tab bar (great for landscape and tablet layouts)

License

Notifications You must be signed in to change notification settings

DaKaZ/react-native-vertical-tab-view

Repository files navigation

react-native-vertical-tab-view

An extension to react-native-tab-view which provides a vertical tab bar (great for landscape and tablet layouts). This work is largely derived from the excellent work that @satya164 has done on react-native-tab-view, including many of his suggestions for extracting this into a stand alone library.

This library is API compatible with react-native-tab-view and can be used as a drop in replacement as it re-exports all of the named exports from react-native-tab-view.

Vertical Tab Example

Installation

yarn add react-native-vertical-tab-view

Quick Start

See the docs at react-native-tab-view

A quick overview, first you need the TabView setup:

  <TabViewVertical
    initialLayout={initialLayout}
    renderTabBar={this._renderTabs}
    style={styles.container}
    navigationState={this.state}
    renderScene={this._renderScene}
    onIndexChange={this._handleIndexChange}
  />

and then you need the TabBar:

  _renderTabs = (landscape: boolean, otherProps: SceneRendererProps): Element<*> => {
    const SelectedTabBar = landscape ? TabBarVertical : TabBar;
    return (
      <SelectedTabBar
        {...otherProps}
        renderLabel={this._renderLabelFactory(otherProps)}
        renderIcon={this._renderIconFactory(otherProps)}
        style={styles.tabbar}
        tabStyle={styles.tab}
        indicatorStyle={styles.indicator}
        scrollEnabled
      />
    );
  };

Tab Style

This is IMPORTANT: make sure you pass in HEIGHT with your tab style:

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#EDECED'
  },
  tabbar: {
    backgroundColor: '#205493'
  },
  tab: {
    width: 110,
    height: 80
  },
  icon: {
    backgroundColor: 'transparent'
    color: '#ffffff'
  },
  indicator: {
    width: 110,
    height: 80,
    backgroundColor: '#F6F7F8'
  },
  label: {
    textAlign: 'center',
    fontSize: 12,
    fontFamily: 'Source Sans Pro',
    paddingTop: 5,
    color: '#F6F7F8',
    backgroundColor: 'transparent'
  }
});

Using with Orientation

One of the best use cases for the vertical tabs is when the device is used in landscape mode, you shift the tabs from the bottom to the left. Check out react-native-orientation for help getting the orientation setup, then look at an implementation like this:

class TabsScreen extends PureComponent<PropsType, StateType> {
  static defaultProps = {
    orientation: 'PORTRAIT'
  };

  constructor(props: PropsType) {
    super(props);
    this.state = {
      index: 0,
      routes: [
        { key: '1', title: 'DASHBOARD', icon: 'tachometer', path: 'dashboard' },
        { key: '2', title: 'EMERGENCY', icon: 'phone', path: 'emergency' },
        { key: '3', title: 'FINANCE', icon: 'pie-chart', path: 'finance' },
        { key: '4', title: 'PERFORMANCE', icon: 'line-chart', path: 'performance' },
        { key: '5', title: 'FACILITIES', icon: 'building', path: 'facilities' },
        { key: '6', title: 'HUMAN RESOURCES', icon: 'users', path: 'human_resources' }
      ]
    };
  }

  _handleIndexChange = (index: number) => {
    this.setState({ index });
  };

  _renderLabelFactory = (props: TabScreenSceneRenderPropsType): TabBarCallbackType => (
    ({ route }: TabScreenSceneType): Element<*> => {
      const index = props.navigationState.routes.indexOf(route);
      const inputRange =
        props.navigationState.routes.map((x: TabScreenRouteType, i: number): number => i);
      const outputRange = inputRange.map((inputIndex: number): string =>
        (inputIndex === index ? Colors.lightBlue : Colors.dhsWhite));
      const color = props.position.interpolate({
        inputRange,
        outputRange
      });
      return <Animated.Text style={[styles.label, { color }]}>{route.title}</Animated.Text>;
    }
  );

  _renderIconFactory = (props: TabScreenSceneRenderPropsType): TabBarCallbackType => (
    ({ route }: TabScreenSceneType): Element<*> => {
      const index = props.navigationState.routes.indexOf(route);
      const inputRange =
        props.navigationState.routes.map((x: TabScreenRouteType, i: number): number => i);
      const outputRange = inputRange.map((inputIndex: number): string =>
        (inputIndex === index ? Colors.lightBlue : Colors.dhsWhite));
      const color = props.position.interpolate({
        inputRange,
        outputRange
      });
      const AnimatedIcon = Animated.createAnimatedComponent(Icon);
      return <AnimatedIcon name={route.icon} size={30} style={[styles.icon, { color }]} />;
    }
  );

  _renderTabs = (landscape: boolean, otherProps: SceneRendererProps): Element<*> => {
    const SelectedTabBar = landscape ? TabBarVertical : TabBar;
    return (
      <SelectedTabBar
        {...otherProps}
        renderLabel={this._renderLabelFactory(otherProps)}
        renderIcon={this._renderIconFactory(otherProps)}
        style={styles.tabbar}
        tabStyle={styles.tab}
        indicatorStyle={styles.indicator}
        scrollEnabled
      />
    );
  };

  _renderScene = SceneMap({
    '1': Screen1,
    '2': Screen2,
    '3': Screen3,
    '4': Screen4,
    '5': Screen5,
    '6': Screen6
  });

  render(): Element<*> {
    // Orientation coming in from react-native-orientation
    const landscape = this.props.orientation.split('-')[0] === 'LANDSCAPE';
    const SelectedTabView = landscape ? TabViewVertical : TabView;
    const initialLayout = { width: 600, height: 400 };
    return (
      <SelectedTabView
        initialLayout={initialLayout}
        renderTabBar={(props: SceneRendererProps) => this._renderTabs(landscape, props)}
        style={styles.container}
        navigationState={this.state}
        renderScene={this._renderScene}
        onIndexChange={this._handleIndexChange}
        swipeEnabled
      />
    );
  }
}

About

An extension to react-native-tab-view which provides a vertical tab bar (great for landscape and tablet layouts)

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published