Tabs

Last Updated on : 2023-10-12 08:00:22download

Overview

Tabs is written by pure gestures, which solves the problem of mutual nesting caused by ScrollView implementation. In addition, through the new lazy loading function, the TabContent component is split out for users to use alone.

Code demo

Note: for more information, see Demo.

Basic Tabs

One screen displays four tabs by default. The number of tabs displayed on one screen can be customized through maxItem.

Note: if the length of dataSource exceeds maxItem, it will automatically become split-screen.

import React from "react"; import { View } from "react-native"; import { Tabs } from "tuya-panel-kit"; import TesterTitle from "../../components/TesterTitle"; export default class OnlyTabsScene extends React.PureComponent { constructor(props) { super(props); this.state = { activeKey1: "1", activeKey2: "3", d1: [ { value: "1", label: "Sensor" }, { value: "2", label: "Remote control" }, { value: "3", label: "RFID" }, { value: "4", label: "Limited sensor" }, ], d2: [ { value: "1", label: "1" }, { value: "2", label: "22" }, { value: "3", label: "333" }, { value: "4", label: "Limited sensor" }, { value: "5", label: "55555" }, { value: "6", label: "666666" }, { value: "7", label: "7777777" }, { value: "8", label: "88888888" }, ], }; } _handleD1Change = (tab) => { this.setState({ activeKey1: tab.value }); }; _handleD2Change = (tab) => { this.setState({ activeKey2: tab.value }); }; render() { return ( <View style={{ flex: 1 }}> <TesterTitle title="Basic Tabs" /> <Tabs activeKey={this.state.activeKey1} dataSource={this.state.d1} onChange={this._handleD1Change} /> <TesterTitle title="Split-screen Tabs" /> <Tabs activeKey={this.state.activeKey2} dataSource={this.state.d2} onChange={this._handleD2Change} /> <TesterTitle title="Basic Tabs (stateless components)" /> <Tabs dataSource={this.state.d1} /> <TesterTitle title="Split-screen Tabs (stateless components)" /> <Tabs dataSource={this.state.d2} /> <TesterTitle title="Tabs with fixed underline width" /> <Tabs underlineWidth={30} dataSource={this.state.d2} /> </View> ); } }

Use TabContent alone

It can be used in scenarios that do not require tabs, such as simulating page switching.

/* eslint-disable react/no-array-index-key */ import _ from "lodash"; import React from "react"; import { View } from "react-native"; import { Tabs } from "tuya-panel-kit"; import TesterTitle from "../../components/TesterTitle"; import Panel from "./components/Panel"; export default class OnlyContentTabsScene extends React.PureComponent { constructor(props) { super(props); this.state = { activeIndex: 0, d1: [ { value: "1", label: "111" }, { value: "2", label: "222" }, { value: "3", label: "333" }, { value: "4", label: "444" }, ], }; } _handleRelease = (gestureState, index) => { this.setState({ activeIndex: index }); }; render() { return ( <View style={{ flex: 1 }}> <TesterTitle title="My content is very lightweight and does not require preloading" /> <Tabs.TabContent preload={false} activeIndex={this.state.activeIndex} onRelease={this._handleRelease} > {this.state.d1.map((data, idx) => ( <Panel key={idx} title={`${idx}`} /> ))} </Tabs.TabContent> <TesterTitle title="Separate TabContent" /> <Tabs.TabContent activeIndex={this.state.activeIndex} onRelease={this._handleRelease} > {this.state.d1.map((data, idx) => ( <Panel key={idx} largeData={idx === 1} title={data.label} /> ))} </Tabs.TabContent> </View> ); } }

Tabs fits to TabContent

import _ from "lodash"; import React from "react"; import { View, ScrollView } from "react-native"; import { Tabs, TYListItem } from "tuya-panel-kit"; import TesterTitle from "../../components/TesterTitle"; import Panel from "./components/Panel"; export default class WithContentTabsScene extends React.PureComponent { constructor(props) { super(props); this.state = { activeKey1: "1", activeKey2: "3", d1: [ { value: "1", label: "Sensor" }, { value: "2", label: "Remote control" }, { value: "3", label: "RFID" }, { value: "4", label: "Limited sensor" }, ], d2: [ { value: "1", label: "1" }, { value: "2", label: "22" }, { value: "3", label: "333" }, { value: "4", label: "Limited sensor" }, { value: "5", label: "55555" }, { value: "6", label: "666666" }, { value: "7", label: "7777777" }, { value: "8", label: "88888888" }, ], }; } _handleD1Change = (tab) => { this.setState({ activeKey1: tab.value }); }; _handleD2Change = (tab) => { this.setState({ activeKey2: tab.value }); }; render() { return ( <View style={{ flex: 1 }}> {/* https://github.com/facebook/react-native/issues/11206 */} <TesterTitle title="There are Tabs with scrollable content on one screen" /> <Tabs activeKey={this.state.activeKey1} dataSource={this.state.d1} swipeable={true} onChange={this._handleD1Change} > <Tabs.TabPanel> <ScrollView> {_.times(10, (n) => ( <TYListItem key={n} title={`Test_${n}`} /> // <TYText key={n} text={`Test_${n}`} /> ))} </ScrollView> </Tabs.TabPanel> <Tabs.TabPanel> <TYListItem title="Page 2" /> </Tabs.TabPanel> <Tabs.TabPanel> <TYListItem title="Page 3" /> </Tabs.TabPanel> <Tabs.TabPanel> <TYListItem title="Page 4" /> </Tabs.TabPanel> </Tabs> <TesterTitle title="Tabs with content on split screens" /> <Tabs activeKey={this.state.activeKey2} dataSource={this.state.d2} onChange={this._handleD2Change} > {this.state.d2.map((data, idx) => ( <Panel key={idx} title={data.label} /> ))} </Tabs> <TesterTitle title="Split screens have content tabs that are located below" /> <Tabs tabPosition="bottom" activeKey={this.state.activeKey2} dataSource={this.state.d2} onChange={this._handleD2Change} > {this.state.d2.map((data, idx) => ( <Panel key={idx} title={data.label} /> ))} </Tabs> </View> ); } }

Nested Tabs

import React from "react"; import { View } from "react-native"; import { Tabs, TYListItem } from "tuya-panel-kit"; import TesterTitle from "../../components/TesterTitle"; import Panel from "./components/Panel"; export default class NestedTabsScene extends React.PureComponent { constructor(props) { super(props); this.state = { activeKey1: "1", activeKey2: "3", d1: [ { value: "1", label: "Sensor" }, { value: "2", label: "Remote control" }, { value: "3", label: "RFID" }, { value: "4", label: "Limited sensor" }, ], d2: [ { value: "1", label: "1" }, { value: "2", label: "22" }, { value: "3", label: "333" }, { value: "4", label: "4444" }, { value: "5", label: "55555" }, { value: "6", label: "666666" }, { value: "7", label: "7777777" }, { value: "8", label: "88888888" }, ], }; } _handleD1Change = (tab) => { this.setState({ activeKey1: tab.value }); }; _handleD2Change = (tab) => { this.setState({ activeKey2: tab.value }); }; render() { return ( <View style={{ flex: 1 }}> <TesterTitle title="Nested Tabs" /> <Tabs tabPosition="bottom" underlineStyle={{ backgroundColor: "transparent" }} activeKey={this.state.activeKey1} dataSource={this.state.d1} swipeable={false} onChange={this._handleD1Change} > <Tabs.TabPanel background="#fff"> <Tabs activeKey={this.state.activeKey2} dataSource={this.state.d2} onChange={this._handleD2Change} > {this.state.d2.map((data, idx) => ( <Panel key={idx} title={data.label} /> ))} </Tabs> </Tabs.TabPanel> <Tabs.TabPanel background="#fff"> <TYListItem title="Page 2" /> </Tabs.TabPanel> <Tabs.TabPanel background="#fff"> <TYListItem title="Page 3" /> </Tabs.TabPanel> <Tabs.TabPanel background="#fff"> <TYListItem title="Page 4" /> </Tabs.TabPanel> </Tabs> </View> ); } }

Tabs API

style

The style of Tabs.

Type Required Default value
ViewPropTypes.style No null

wrapperStyle

The container style that wraps Tabs and TabContent. It only takes effect when TabContent is configured.

Type Required Default value
ViewPropTypes.style No null

tabContentStyle

The style of TabContent. It only takes effect when TabContent is configured.

Type Required Default value
ViewPropTypes.style No null

tabActiveStyle

The style of the selected tab.

Type Required Default value
ViewPropTypes.style No null

tabTextStyle

The text style of the unselected Tab.

Type Required Default value
ViewPropTypes.style No null

tabActiveTextStyle

The selected text style.

Type Required Default value
ViewPropTypes.style No null

underlineStyle

Style of the underline.

Type Required Default value
ViewPropTypes.style No null

underlineWidth

The width of the underline. If not set, it will follow the text width by default.

Type Required Default value
number No null

defaultActiveKey

The default activation value. It is used when it is set to uncontrolled components.

Type Required Default value
number | string No 0

activeKey

Activation value. If the parameter value is set, it becomes a controlled component. It needs to be used with onChange.

Type Required Default value
number | string No null

dataSource

Data source.

Type Required Default value
ITabsDataSource Yes null
interface ITabsDataSource { value: string; // Label value label? : string; // Label text renderTab? : ( isActive: boolean, state: ITabState, props: ITabProps ) => React.Element; // Custom rendering tab label }

disabled

Whether to disable the Tabs page.

Note: only Tabs can be disabled, and TabContent cannot be disabled.

Type Required Default value
boolean No false

swipeable

Whether TabContent supports scrolling.

Type Required Default value
boolean No true

maxItem

The maximum number of Tab labels supported on a screen.

Type Required Default value
number No 4

tabPosition

When Tab and TabContent exist at the same time, the arrangement position of Tab.

Type Required Default value
top| bottom No top

activeColor

The color when activated.

Type Required Default value
ColorPropType No Theme color

background

The background color of Tab page.

Type Required Default value
ColorPropType No #fff

preload

Whether TabContent needs to be preloaded.

Type Required Default value
boolean No true

preloadTimeout

The preload delay time of TabContent.

Type Required Default value
number No null

renderPlaceholder

Custom rendering of the placeholder container in the preload.

Type Required Default value
(activeIndex, children) => React.Element No null

onChange

Callback for tab change.

Type Required Default value
(tab, index) => void No null

children

The child element of Tab, generally TabContent.

Type Required Default value
array No null

extraSpace

The extra white space on the right, in px.

This property is added in the @2.0.0-rc.2 version.

Type Required Default value
number No 0.5

velocityThreshold

The acceleration threshold of TabContent in px. If the sliding rate exceeds the threshold, it is directly judged as the next page.

This property is added in the @2.0.0-rc.2 version.

Type Required Default value
number No 0.5

animationConfig

Animation configuration.

Type Required Default value
IAnimationConfig No
  • duration: 200
  • easing: Easing.linear
  • delay: 0
  • useNativeDriver: true

Gradient example:

interface IAnimationConfig { duration? : number; easing? : EasingFunction; delay? : number; isInteraction? : bool; useNativeDriver? : bool; // tabs are always false, width animation is not supported } // Default value { duration: 200, easing: Easing.linear, delay: 0, isInteraction: true, useNativeDriver: false, }

Tabs.Content API

style

The style of TabContent.

Type Required Default value
ViewPropTypes.style No null

activeIndex

The currently activated index.

Type Required Default value
number Yes 0

disabled

Whether to disable TabContent.

Type Required Default value
boolean No false

preload

Whether TabContent needs to be preloaded.

Type Required Default value
boolean No true

preloadTimeout

The preload delay time of TabContent.

Type Required Default value
number No null

onMove

TabContent sliding callback.

Type Required Default value
(gestureState, index, percent) => void No null

onRelease

Callback of TabContent sliding end.

Type Required Default value
(gestureState, index, percent) => void No null

renderPlaceholder

Custom rendering of the placeholder container in the preload.

Type Required Default value
(activeIndex, children) => React.Element No null

children

Child element of TabContent.

Type Required Default value
array No null

velocityThreshold

The acceleration threshold of TabContent in px. If the sliding rate exceeds the threshold, it is directly judged as the next page.

This property is added in the @2.0.0-rc.2 version.

Type Required Default value
number No 0.5

animationConfig

Animation configuration.

Type Required Default value
IAnimationConfig No
  • duration: 200
  • easing: Easing.linear
  • delay: 0
  • useNativeDriver: true

Gradient example:

interface IAnimationConfig { duration? : number; easing? : EasingFunction; delay? : number; isInteraction? : bool; useNativeDriver? : bool; } // Default value { duration: 200, easing: Easing.linear, delay: 0, isInteraction: true, useNativeDriver: true, }