128 lines
2.6 KiB
TypeScript
128 lines
2.6 KiB
TypeScript
import React from 'react'
|
|
import {
|
|
View,
|
|
Text,
|
|
Pressable,
|
|
ScrollView,
|
|
StyleSheet,
|
|
ViewStyle,
|
|
} from 'react-native'
|
|
import { DownArrowIcon } from '@/components/icon'
|
|
|
|
interface TabNavigationProps {
|
|
tabs: string[]
|
|
activeIndex: number
|
|
onTabPress: (index: number) => void
|
|
showArrow?: boolean
|
|
onArrowPress?: () => void
|
|
isSticky?: boolean
|
|
wrapperStyle?: ViewStyle
|
|
onLayout?: (y: number, height: number) => void
|
|
}
|
|
|
|
export function TabNavigation({
|
|
tabs,
|
|
activeIndex,
|
|
onTabPress,
|
|
showArrow = false,
|
|
onArrowPress,
|
|
isSticky = false,
|
|
wrapperStyle,
|
|
onLayout,
|
|
}: TabNavigationProps): JSX.Element {
|
|
return (
|
|
<View
|
|
testID="tab-navigation"
|
|
style={[
|
|
styles.tabsWrapper,
|
|
isSticky && styles.stickyWrapper,
|
|
wrapperStyle,
|
|
]}
|
|
onLayout={(e) => {
|
|
const { y, height } = e.nativeEvent.layout
|
|
onLayout?.(y, height)
|
|
}}
|
|
>
|
|
<View style={styles.tabsContainer}>
|
|
<ScrollView
|
|
horizontal
|
|
showsHorizontalScrollIndicator={false}
|
|
contentContainerStyle={styles.tabsScrollContent}
|
|
>
|
|
{tabs.map((tab, index) => (
|
|
<Pressable
|
|
key={index}
|
|
testID={`tab-${index}`}
|
|
style={[styles.tab, activeIndex === index && styles.activeTab]}
|
|
onPress={() => onTabPress(index)}
|
|
>
|
|
<Text
|
|
style={[
|
|
styles.tabText,
|
|
activeIndex === index && styles.activeTabText,
|
|
]}
|
|
>
|
|
{tab}
|
|
</Text>
|
|
</Pressable>
|
|
))}
|
|
</ScrollView>
|
|
{showArrow && (
|
|
<Pressable
|
|
testID="tab-arrow"
|
|
style={styles.tabArrow}
|
|
onPress={onArrowPress}
|
|
>
|
|
<DownArrowIcon />
|
|
</Pressable>
|
|
)}
|
|
</View>
|
|
</View>
|
|
)
|
|
}
|
|
|
|
const styles = StyleSheet.create({
|
|
tabsWrapper: {
|
|
paddingHorizontal: 16,
|
|
paddingVertical: 8,
|
|
backgroundColor: '#090A0B',
|
|
},
|
|
stickyWrapper: {
|
|
position: 'absolute',
|
|
top: 0,
|
|
left: 0,
|
|
right: 0,
|
|
zIndex: 100,
|
|
},
|
|
tabsContainer: {
|
|
flexDirection: 'row',
|
|
alignItems: 'center',
|
|
},
|
|
tabsScrollContent: {
|
|
gap: 8,
|
|
},
|
|
tab: {
|
|
paddingHorizontal: 16,
|
|
paddingVertical: 8,
|
|
borderRadius: 20,
|
|
backgroundColor: '#1C1E22',
|
|
},
|
|
activeTab: {
|
|
backgroundColor: '#F5F5F5',
|
|
},
|
|
tabText: {
|
|
color: '#F5F5F5',
|
|
fontSize: 14,
|
|
fontWeight: '500',
|
|
},
|
|
activeTabText: {
|
|
color: '#090A0B',
|
|
},
|
|
tabArrow: {
|
|
marginLeft: 8,
|
|
padding: 8,
|
|
backgroundColor: '#1C1E22',
|
|
borderRadius: 20,
|
|
},
|
|
})
|