Skip to content

Commit 9bf41a3

Browse files
chore: refactoring tabs to reduce duplication and complexity
1 parent 961dbc3 commit 9bf41a3

File tree

4 files changed

+2252
-2420
lines changed

4 files changed

+2252
-2420
lines changed

app/component-library/components-temp/Tabs/Tab/Tab.tsx

Lines changed: 57 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// Third party dependencies.
2-
import React, { useRef, useCallback } from 'react';
3-
import { Pressable, View } from 'react-native';
2+
import React, { useRef, useEffect } from 'react';
3+
import { Pressable, Animated } from 'react-native';
44

55
// External dependencies.
66
import { useTailwind } from '@metamask/design-system-twrnc-preset';
@@ -9,6 +9,7 @@ import {
99
TextVariant,
1010
FontWeight,
1111
} from '@metamask/design-system-react-native';
12+
import { AnimationDuration } from '../../../constants/animation.constants';
1213

1314
// Internal dependencies.
1415
import { TabProps } from './Tab.types';
@@ -19,67 +20,69 @@ const Tab: React.FC<TabProps> = ({
1920
isDisabled = false,
2021
onPress,
2122
testID,
22-
onLayout,
2323
...pressableProps
2424
}) => {
2525
const tw = useTailwind();
26-
const viewRef = useRef<View>(null);
26+
const scaleAnim = useRef(new Animated.Value(isActive ? 1 : 0)).current;
2727

28-
const handleOnLayout = useCallback(
29-
(layoutEvent: Parameters<NonNullable<typeof onLayout>>[0]) => {
30-
if (onLayout) {
31-
onLayout(layoutEvent);
32-
}
33-
},
34-
[onLayout],
35-
);
28+
useEffect(() => {
29+
Animated.timing(scaleAnim, {
30+
toValue: isActive && !isDisabled ? 1 : 0,
31+
duration: AnimationDuration.Fast,
32+
useNativeDriver: true,
33+
}).start();
34+
}, [isActive, isDisabled, scaleAnim]);
3635

3736
return (
38-
<View
39-
ref={viewRef}
40-
onLayout={handleOnLayout}
41-
style={tw.style('flex-shrink-0')}
37+
<Pressable
38+
style={tw.style(
39+
'flex-shrink-0 px-0 py-1 flex-row items-center justify-center relative',
40+
isDisabled && 'opacity-50',
41+
)}
42+
onPress={isDisabled ? undefined : onPress}
43+
disabled={isDisabled}
44+
testID={testID}
45+
{...pressableProps}
4246
>
43-
<Pressable
44-
style={tw.style(
45-
'px-0 py-1 flex-row items-center justify-center relative',
46-
isDisabled && 'opacity-50',
47-
)}
48-
onPress={isDisabled ? undefined : onPress}
49-
disabled={isDisabled}
50-
testID={testID}
51-
{...pressableProps}
47+
{/* Hidden bold text that determines layout size */}
48+
<Text
49+
variant={TextVariant.BodyMd}
50+
fontWeight={FontWeight.Bold}
51+
numberOfLines={1}
52+
style={tw.style('opacity-0')}
53+
>
54+
{label}
55+
</Text>
56+
57+
{/* Visible text positioned absolutely over the hidden text */}
58+
<Text
59+
variant={TextVariant.BodyMd}
60+
fontWeight={
61+
isActive && !isDisabled ? FontWeight.Bold : FontWeight.Regular
62+
}
63+
twClassName={
64+
isDisabled
65+
? 'text-muted'
66+
: isActive
67+
? 'text-default'
68+
: 'text-alternative'
69+
}
70+
numberOfLines={1}
71+
style={tw.style('absolute inset-0 flex items-center justify-center')}
5272
>
53-
{/* Hidden bold text that determines layout size */}
54-
<Text
55-
variant={TextVariant.BodyMd}
56-
fontWeight={FontWeight.Bold}
57-
numberOfLines={1}
58-
style={tw.style('opacity-0')}
59-
>
60-
{label}
61-
</Text>
73+
{label}
74+
</Text>
6275

63-
{/* Visible text positioned absolutely over the hidden text */}
64-
<Text
65-
variant={TextVariant.BodyMd}
66-
fontWeight={
67-
isActive && !isDisabled ? FontWeight.Bold : FontWeight.Regular
68-
}
69-
twClassName={
70-
isDisabled
71-
? 'text-muted'
72-
: isActive
73-
? 'text-default'
74-
: 'text-alternative'
75-
}
76-
numberOfLines={1}
77-
style={tw.style('absolute inset-0 flex items-center justify-center')}
78-
>
79-
{label}
80-
</Text>
81-
</Pressable>
82-
</View>
76+
{/* Animated underline */}
77+
<Animated.View
78+
style={[
79+
tw.style('absolute bottom-0 left-0 right-0 h-0.5 bg-icon-default'),
80+
{
81+
transform: [{ scaleX: scaleAnim }],
82+
},
83+
]}
84+
/>
85+
</Pressable>
8386
);
8487
};
8588

app/component-library/components-temp/Tabs/Tab/Tab.types.ts

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// Third party dependencies.
2-
import { PressableProps, LayoutChangeEvent } from 'react-native';
2+
import { PressableProps } from 'react-native';
33

44
/**
55
* Tab component props
@@ -21,8 +21,4 @@ export interface TabProps extends PressableProps {
2121
* Callback when tab is pressed
2222
*/
2323
onPress: () => void;
24-
/**
25-
* Callback when tab layout changes
26-
*/
27-
onLayout?: (event: LayoutChangeEvent) => void;
2824
}

0 commit comments

Comments
 (0)