mirror of https://git.lenooby09.tech/LeNooby09/social-app.git
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at offline-indicator 136 lines 3.8 kB view raw
1import React, {useRef, useMemo, useEffect, useState, useCallback} from 'react' 2import {StyleSheet, View, ScrollView, LayoutChangeEvent} from 'react-native' 3import {Text} from '../util/text/Text' 4import {PressableWithHover} from '../util/PressableWithHover' 5import {usePalette} from 'lib/hooks/usePalette' 6import {isDesktopWeb, isMobileWeb} from 'platform/detection' 7import {DraggableScrollView} from './DraggableScrollView' 8 9export interface TabBarProps { 10 testID?: string 11 selectedPage: number 12 items: string[] 13 indicatorColor?: string 14 onSelect?: (index: number) => void 15 onPressSelected?: () => void 16} 17 18export function TabBar({ 19 testID, 20 selectedPage, 21 items, 22 indicatorColor, 23 onSelect, 24 onPressSelected, 25}: TabBarProps) { 26 const pal = usePalette('default') 27 const scrollElRef = useRef<ScrollView>(null) 28 const [itemXs, setItemXs] = useState<number[]>([]) 29 const indicatorStyle = useMemo( 30 () => ({borderBottomColor: indicatorColor || pal.colors.link}), 31 [indicatorColor, pal], 32 ) 33 34 // scrolls to the selected item when the page changes 35 useEffect(() => { 36 scrollElRef.current?.scrollTo({ 37 x: itemXs[selectedPage] || 0, 38 }) 39 }, [scrollElRef, itemXs, selectedPage]) 40 41 const onPressItem = useCallback( 42 (index: number) => { 43 onSelect?.(index) 44 if (index === selectedPage) { 45 onPressSelected?.() 46 } 47 }, 48 [onSelect, selectedPage, onPressSelected], 49 ) 50 51 // calculates the x position of each item on mount and on layout change 52 const onItemLayout = React.useCallback( 53 (e: LayoutChangeEvent, index: number) => { 54 const x = e.nativeEvent.layout.x 55 setItemXs(prev => { 56 const Xs = [...prev] 57 Xs[index] = x 58 return Xs 59 }) 60 }, 61 [], 62 ) 63 64 return ( 65 <View testID={testID} style={[pal.view, styles.outer]}> 66 <DraggableScrollView 67 horizontal={true} 68 showsHorizontalScrollIndicator={false} 69 ref={scrollElRef} 70 contentContainerStyle={styles.contentContainer}> 71 {items.map((item, i) => { 72 const selected = i === selectedPage 73 return ( 74 <PressableWithHover 75 key={item} 76 onLayout={e => onItemLayout(e, i)} 77 style={[styles.item, selected && indicatorStyle]} 78 hoverStyle={pal.viewLight} 79 onPress={() => onPressItem(i)}> 80 <Text 81 type={isDesktopWeb ? 'xl-bold' : 'lg-bold'} 82 testID={testID ? `${testID}-${item}` : undefined} 83 style={selected ? pal.text : pal.textLight}> 84 {item} 85 </Text> 86 </PressableWithHover> 87 ) 88 })} 89 </DraggableScrollView> 90 </View> 91 ) 92} 93 94const styles = isDesktopWeb 95 ? StyleSheet.create({ 96 outer: { 97 flexDirection: 'row', 98 width: 598, 99 }, 100 contentContainer: { 101 columnGap: 8, 102 marginLeft: 14, 103 paddingRight: 14, 104 backgroundColor: 'transparent', 105 }, 106 item: { 107 paddingTop: 14, 108 paddingBottom: 12, 109 paddingHorizontal: 10, 110 borderBottomWidth: 3, 111 borderBottomColor: 'transparent', 112 justifyContent: 'center', 113 }, 114 }) 115 : StyleSheet.create({ 116 outer: { 117 flex: 1, 118 flexDirection: 'row', 119 backgroundColor: 'transparent', 120 maxWidth: '100%', 121 }, 122 contentContainer: { 123 columnGap: isMobileWeb ? 0 : 20, 124 marginLeft: isMobileWeb ? 0 : 18, 125 paddingRight: isMobileWeb ? 0 : 36, 126 backgroundColor: 'transparent', 127 }, 128 item: { 129 paddingTop: 10, 130 paddingBottom: 10, 131 paddingHorizontal: isMobileWeb ? 8 : 0, 132 borderBottomWidth: 3, 133 borderBottomColor: 'transparent', 134 justifyContent: 'center', 135 }, 136 })