diff options
-rw-r--r-- | src/screens/Hashtag.tsx | 2 | ||||
-rw-r--r-- | src/view/com/pager/TabBar.tsx | 58 | ||||
-rw-r--r-- | src/view/com/pager/TabBar.web.tsx | 21 |
3 files changed, 69 insertions, 12 deletions
diff --git a/src/screens/Hashtag.tsx b/src/screens/Hashtag.tsx index a87487150..3e98f364b 100644 --- a/src/screens/Hashtag.tsx +++ b/src/screens/Hashtag.tsx @@ -107,7 +107,7 @@ export default function HashtagScreen({ return ( <Layout.Screen> - <Layout.Header.Outer> + <Layout.Header.Outer noBottomBorder> <Layout.Header.BackButton /> <Layout.Header.Content> <Layout.Header.TitleText>{headerTitle}</Layout.Header.TitleText> diff --git a/src/view/com/pager/TabBar.tsx b/src/view/com/pager/TabBar.tsx index b08b364c5..b257559bc 100644 --- a/src/view/com/pager/TabBar.tsx +++ b/src/view/com/pager/TabBar.tsx @@ -51,6 +51,7 @@ export function TabBar({ const containerSize = useSharedValue(0) const scrollX = useSharedValue(0) const layouts = useSharedValue<{x: number; width: number}[]>([]) + const textLayouts = useSharedValue<{width: number}[]>([]) const itemsLength = items.length const scrollToOffsetJS = useCallback( @@ -211,21 +212,40 @@ export function TabBar({ [layouts], ) + const onTextLayout = useCallback( + (i: number, layout: {width: number}) => { + 'worklet' + textLayouts.modify(ls => { + ls[i] = layout + return ls + }) + }, + [textLayouts], + ) + const indicatorStyle = useAnimatedStyle(() => { if (!_WORKLET) { return {opacity: 0} } const layoutsValue = layouts.get() + const textLayoutsValue = textLayouts.get() if ( layoutsValue.length !== itemsLength || - layoutsValue.some(l => l === undefined) + textLayoutsValue.length !== itemsLength ) { return { opacity: 0, } } - if (layoutsValue.length === 1) { - return {opacity: 1} + if (textLayoutsValue.length === 1) { + return { + opacity: 1, + transform: [ + { + scaleX: textLayoutsValue[0].width / contentSize.get(), + }, + ], + } } return { opacity: 1, @@ -240,10 +260,8 @@ export function TabBar({ { scaleX: interpolate( dragProgress.get(), - layoutsValue.map((l, i) => i), - layoutsValue.map( - l => (l.width - ITEM_PADDING * 2) / contentSize.get(), - ), + textLayoutsValue.map((l, i) => i), + textLayoutsValue.map(l => l.width / contentSize.get()), ), }, ], @@ -287,7 +305,7 @@ export function TabBar({ onLayout={e => { contentSize.set(e.nativeEvent.layout.width) }} - style={{flexDirection: 'row'}}> + style={{flexDirection: 'row', flexGrow: 1}}> {items.map((item, i) => { return ( <TabBarItem @@ -298,6 +316,7 @@ export function TabBar({ item={item} onPressItem={onPressItem} onItemLayout={onItemLayout} + onTextLayout={onTextLayout} /> ) })} @@ -328,6 +347,7 @@ function TabBarItem({ item, onPressItem, onItemLayout, + onTextLayout, }: { index: number testID: string | undefined @@ -335,6 +355,7 @@ function TabBarItem({ item: string onPressItem: (index: number) => void onItemLayout: (index: number, layout: {x: number; width: number}) => void + onTextLayout: (index: number, layout: {width: number}) => void }) { const t = useTheme() const style = useAnimatedStyle(() => { @@ -358,8 +379,15 @@ function TabBarItem({ [index, onItemLayout], ) + const handleTextLayout = useCallback( + (e: LayoutChangeEvent) => { + runOnUI(onTextLayout)(index, e.nativeEvent.layout) + }, + [index, onTextLayout], + ) + return ( - <View onLayout={handleLayout}> + <View onLayout={handleLayout} style={{flexGrow: 1}}> <PressableWithHover testID={`${testID}-selector-${index}`} style={styles.item} @@ -370,7 +398,8 @@ function TabBarItem({ <Text emoji testID={testID ? `${testID}-${item}` : undefined} - style={[t.atoms.text, a.text_md, a.font_bold, {lineHeight: 20}]}> + style={[styles.itemText, t.atoms.text, a.text_md, a.font_bold]} + onLayout={handleTextLayout}> {item} </Text> </Animated.View> @@ -381,19 +410,28 @@ function TabBarItem({ const styles = StyleSheet.create({ contentContainer: { + flexGrow: 1, backgroundColor: 'transparent', paddingHorizontal: CONTENT_PADDING, }, item: { + flexGrow: 1, paddingTop: 10, paddingHorizontal: ITEM_PADDING, justifyContent: 'center', }, itemInner: { + alignItems: 'center', + flexGrow: 1, paddingBottom: 10, borderBottomWidth: 3, borderBottomColor: 'transparent', }, + itemText: { + lineHeight: 20, + minWidth: 45, + textAlign: 'center', + }, outerBottomBorder: { position: 'absolute', left: 0, diff --git a/src/view/com/pager/TabBar.web.tsx b/src/view/com/pager/TabBar.web.tsx index 789f88e75..f44e03368 100644 --- a/src/view/com/pager/TabBar.web.tsx +++ b/src/view/com/pager/TabBar.web.tsx @@ -115,12 +115,14 @@ export function TabBar({ hoverStyle={t.atoms.bg_contrast_25} onPress={() => onPressItem(i)} accessibilityRole="tab"> - <View style={[styles.itemInner, selected && indicatorStyle]}> + <View style={styles.itemInner}> <Text emoji testID={testID ? `${testID}-${item}` : undefined} style={[ + styles.itemText, selected ? t.atoms.text : t.atoms.text_contrast_medium, + selected && indicatorStyle, a.text_md, a.font_bold, {lineHeight: 20}, @@ -143,15 +145,23 @@ const desktopStyles = StyleSheet.create({ width: 598, }, contentContainer: { + flexGrow: 1, paddingHorizontal: 0, backgroundColor: 'transparent', }, item: { + flexGrow: 1, + alignItems: 'stretch', paddingTop: 14, paddingHorizontal: 14, justifyContent: 'center', }, itemInner: { + alignItems: 'center', + }, + itemText: { + textAlign: 'center', + minWidth: 45, paddingBottom: 12, borderBottomWidth: 3, borderBottomColor: 'transparent', @@ -170,15 +180,24 @@ const mobileStyles = StyleSheet.create({ flexDirection: 'row', }, contentContainer: { + flexGrow: 1, backgroundColor: 'transparent', paddingHorizontal: 6, }, item: { + flexGrow: 1, + alignItems: 'stretch', paddingTop: 10, paddingHorizontal: 10, justifyContent: 'center', }, itemInner: { + flexGrow: 1, + alignItems: 'center', + }, + itemText: { + textAlign: 'center', + minWidth: 45, paddingBottom: 10, borderBottomWidth: 2, borderBottomColor: 'transparent', |