Commit eaf55b41 by tungnq

TODO: Bổ sung componet tab view

parent 21d5a486
# TabView Component
A reusable TabView component that supports both filter and navigation modes.
## Features
- **Auto-generate tabs** from data array
- **Two modes**: Filter mode and Navigate mode
- **Scrollable tabs** when there are many tabs
- **Icon support** for each tab
- **Active state styling** with underline indicator
- **Disabled state** support
- **Auto-scroll** to active tab when scrollable
- **Edge case handling** (empty data, duplicate keys, etc.)
## Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `data` | Array | `[]` | Array of tab objects |
| `mode` | String | `'filter'` | `'filter'` or `'navigate'` |
| `defaultActiveKey` | String | `null` | Initial active tab key |
| `scrollable` | Boolean | `false` | Enable horizontal scrolling |
| `onTabChange` | Function | `null` | Called when tab changes |
| `onFilterChange` | Function | `null` | Called in filter mode |
| `onNavigate` | Function | `null` | Called in navigate mode |
| `style` | Object | `{}` | Container style |
| `tabStyle` | Object | `{}` | Individual tab style |
| `activeTabStyle` | Object | `{}` | Active tab style |
| `textStyle` | Object | `{}` | Tab text style |
| `activeTextStyle` | Object | `{}` | Active tab text style |
## Data Object Structure
```javascript
{
key: 'unique_key', // Required: unique identifier
label: 'Tab Label', // Required: display text
icon: 'icon_name', // Optional: MaterialIcons name
disabled: false, // Optional: disable tab
// ... any other custom properties
}
```
## Usage Examples
### 1. Filter Mode (Default)
```javascript
import React, { useState } from 'react';
import { View } from 'react-native';
import TabView from '../components/TabView';
const FilterScreen = () => {
const [filteredData, setFilteredData] = useState([]);
const [allData] = useState([
// Your data array
]);
const tabData = [
{ key: 'all', label: 'Tất cả', icon: 'list' },
{ key: 'public', label: 'Công khai', icon: 'public' },
{ key: 'private', label: 'Hạn chế', icon: 'lock' },
{ key: 'draft', label: 'Nháp', icon: 'edit' },
];
const handleFilterChange = (item) => {
if (item.key === 'all') {
setFilteredData(allData);
} else {
const filtered = allData.filter(data => data.status === item.key);
setFilteredData(filtered);
}
};
return (
<View>
<TabView
data={tabData}
mode="filter"
defaultActiveKey="all"
scrollable={true}
onFilterChange={handleFilterChange}
/>
{/* Render your filtered list here */}
</View>
);
};
```
### 2. Navigate Mode
```javascript
import React from 'react';
import { View } from 'react-native';
import TabView from '../components/TabView';
const NavigationScreen = ({ navigation }) => {
const tabData = [
{ key: 'home', label: 'Trang chủ', icon: 'home' },
{ key: 'profile', label: 'Hồ sơ', icon: 'person' },
{ key: 'settings', label: 'Cài đặt', icon: 'settings' },
{ key: 'help', label: 'Trợ giúp', icon: 'help' },
];
const handleNavigate = (item) => {
switch (item.key) {
case 'home':
navigation.navigate('HomeScreen');
break;
case 'profile':
navigation.navigate('ProfileScreen');
break;
case 'settings':
navigation.navigate('SettingsScreen');
break;
case 'help':
navigation.navigate('HelpScreen');
break;
}
};
return (
<View>
<TabView
data={tabData}
mode="navigate"
defaultActiveKey="home"
onNavigate={handleNavigate}
/>
</View>
);
};
```
### 3. Custom Styling
```javascript
<TabView
data={tabData}
style={{ backgroundColor: '#f8f9fa' }}
tabStyle={{
paddingHorizontal: 20,
paddingVertical: 15
}}
activeTabStyle={{
backgroundColor: '#e3f2fd'
}}
textStyle={{
fontSize: 16,
color: '#333'
}}
activeTextStyle={{
color: '#1976d2',
fontWeight: 'bold'
}}
/>
```
### 4. With Disabled Tabs
```javascript
const tabData = [
{ key: 'tab1', label: 'Available', icon: 'check' },
{ key: 'tab2', label: 'Disabled', icon: 'block', disabled: true },
{ key: 'tab3', label: 'Coming Soon', icon: 'schedule', disabled: true },
];
```
## Edge Cases Handled
- **Empty data**: Shows "Không có tab" placeholder
- **Invalid defaultActiveKey**: Falls back to first tab
- **Duplicate keys**: Shows warning in console
- **Many tabs**: Use `scrollable={true}` for horizontal scrolling
## Styling Notes
- Active tab has blue color (`#007AFF`) and underline
- Inactive tabs have gray color (`#666`)
- Disabled tabs have reduced opacity (0.5)
- Tab height is 40px with 16px horizontal padding
- Icons are 16px size with 6px right margin
import TabViewComponent from './view';
export default TabViewComponent;
...@@ -6,16 +6,32 @@ import SubButton from '../../components/FAB/sub_button'; ...@@ -6,16 +6,32 @@ import SubButton from '../../components/FAB/sub_button';
import Header from '../../components/Header/Header'; import Header from '../../components/Header/Header';
import Dropdown from '../../components/DropdownAlert/Dropdown'; import Dropdown from '../../components/DropdownAlert/Dropdown';
import R from '../../assets/R'; import R from '../../assets/R';
import TabViewComponent from '../../components/TabView';
const ListWorkView = (props) => { const ListWorkView = (props) => {
const { } = props; const { } = props;
const handleFilterChange = (item) => {
console.log(item);
};
return ( return (
<View <View
style={styles.container}> style={styles.container}>
<Header title={'Danh sách công việc'} isBack /> <Header title={'Danh sách công việc'} isBack />
<View style = {styles.body}> <View style = {styles.body}>
<TabViewComponent
data={[
{key: 'all', label: 'Tất cả', icon: 'list'},
{key: 'public', label: 'Công khai', icon: 'public'},
{key: 'private', label: 'Hạn chế', icon: 'lock'},
{key: 'draft', label: 'Nháp', icon: 'edit'},
]}
mode="filter"
defaultActiveKey="all"
scrollable={true}
onFilterChange={handleFilterChange}
/>
</View> </View>
<FAB> <FAB>
<SubButton <SubButton
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment