1- import React , { ReactElement , memo , useState } from 'react' ;
1+ import React , { ReactElement , memo , useEffect , useState } from 'react' ;
22import Animated , {
33 useAnimatedStyle ,
4+ useSharedValue ,
45 withTiming ,
56} from 'react-native-reanimated' ;
67import {
@@ -18,12 +19,10 @@ import colors from '../styles/colors';
1819import { CaptionB } from '../styles/text' ;
1920import { TActivityFilter } from '../utils/activity' ;
2021
21- const tabsGap = 4 ;
22-
23- export type TTab = {
24- id : string ;
25- filter : TActivityFilter ;
26- } ;
22+ export type TTab = { id : string ; filter : TActivityFilter } ;
23+ type TTabLayout = { width : number ; height : number ; x : number ; y : number } ;
24+ type TTabLayouts = Record < string , TTabLayout > ;
25+ const initialTabLayout : TTabLayout = { width : 0 , height : 0 , x : 0 , y : 0 } ;
2726
2827const Tab = ( {
2928 text,
@@ -62,28 +61,50 @@ const Tabs = ({
6261 onPress : ( index : number ) => void ;
6362} ) : ReactElement => {
6463 const { t } = useTranslation ( 'wallet' ) ;
65- const [ tabWidth , setTabWidth ] = useState ( 0 ) ;
64+ const activeTabLayout = useSharedValue < TTabLayout > ( initialTabLayout ) ;
65+ const [ layouts , setLayouts ] = useState < TTabLayouts > ( { } ) ;
66+
67+ useEffect ( ( ) => {
68+ // Set the active tab layout when the active tab changes
69+ const layout = layouts [ tabs [ activeTab ] . id ] ;
70+ if ( layout ) {
71+ activeTabLayout . value = withTiming ( layout ) ;
72+ }
73+ } , [ activeTab , layouts , tabs , activeTabLayout ] ) ;
6674
67- const animatedTabStyle = useAnimatedStyle ( ( ) => {
68- return { left : withTiming ( ( tabWidth + tabsGap ) * activeTab ) } ;
69- } , [ tabWidth , activeTab ] ) ;
75+ const animatedStyle = useAnimatedStyle ( ( ) => {
76+ return {
77+ height : activeTabLayout . value . height ,
78+ top : activeTabLayout . value . y ,
79+ width : activeTabLayout . value . width ,
80+ left : activeTabLayout . value . x ,
81+ } ;
82+ } ) ;
7083
71- const onLayout = ( event : LayoutChangeEvent ) : void => {
72- setTabWidth ( event . nativeEvent . layout . width ) ;
84+ const handleLayout = (
85+ id : string ,
86+ event : LayoutChangeEvent ,
87+ index : number ,
88+ ) : void => {
89+ const { layout } = event . nativeEvent ;
90+ setLayouts ( ( prevLayouts ) => ( { ...prevLayouts , [ id ] : layout } ) ) ;
91+
92+ if ( index === activeTab ) {
93+ // Set the active tab layout on initial render
94+ activeTabLayout . value = layout ;
95+ }
7396 } ;
7497
7598 return (
7699 < View style = { [ styles . root , style ] } testID = "Tabs" >
77- < Animated . View
78- style = { [ styles . activeTab , animatedTabStyle , { width : tabWidth } ] }
79- />
100+ < Animated . View style = { [ styles . activeTab , animatedStyle ] } />
80101 { tabs . map ( ( tab , index ) => (
81102 < Tab
82103 key = { tab . id }
83104 text = { t ( 'activity_tabs.' + tab . id ) }
84105 active = { activeTab === index }
85106 testID = { `Tab-${ tab . id } ` }
86- onLayout = { onLayout }
107+ onLayout = { ( event ) => handleLayout ( tab . id , event , index ) }
87108 onPress = { ( ) : void => onPress ( index ) }
88109 />
89110 ) ) }
@@ -94,7 +115,7 @@ const Tabs = ({
94115const styles = StyleSheet . create ( {
95116 root : {
96117 flexDirection : 'row' ,
97- gap : tabsGap ,
118+ gap : 4 ,
98119 } ,
99120 tab : {
100121 flex : 1 ,
@@ -105,10 +126,9 @@ const styles = StyleSheet.create({
105126 paddingVertical : 10 ,
106127 } ,
107128 activeTab : {
108- backgroundColor : colors . brand ,
109- height : 2 ,
129+ borderBottomWidth : 2 ,
130+ borderColor : colors . brand ,
110131 position : 'absolute' ,
111- top : '95%' ,
112132 zIndex : 1 ,
113133 } ,
114134} ) ;
0 commit comments