@momo-kits/foundation 0.167.1-duo.1 → 0.167.1-duo.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/Application/BottomSheet.tsx +115 -14
  2. package/Application/BottomTab/DuoTabBar.tsx +410 -0
  3. package/Application/BottomTab/index.tsx +38 -28
  4. package/Application/Components/DuoGlassBackground.tsx +177 -0
  5. package/Application/Components/HeaderExtendHeader.tsx +40 -27
  6. package/Application/Components/HeaderLeft.tsx +17 -0
  7. package/Application/Components/HeaderRight.tsx +59 -9
  8. package/Application/Components/HeaderTitle.tsx +53 -17
  9. package/Application/Components/OptionalGlassView.ts +11 -0
  10. package/Application/Components/SearchHeader.tsx +15 -14
  11. package/Application/Components/SideBarButton.tsx +128 -0
  12. package/Application/ModalScreen.tsx +16 -2
  13. package/Application/NavigationContainer.tsx +22 -32
  14. package/Application/Navigator.ts +1 -3
  15. package/Application/StackScreen.tsx +2 -5
  16. package/Application/WidgetContainer.tsx +9 -7
  17. package/Application/device.ts +29 -0
  18. package/Application/types.ts +5 -1
  19. package/Application/utils.tsx +10 -3
  20. package/Consts/index.ts +0 -1
  21. package/Consts/theme.ts +5 -6
  22. package/Input/Input.tsx +3 -4
  23. package/Input/InputMoney.tsx +31 -51
  24. package/Input/InputPhoneNumber.tsx +3 -4
  25. package/Input/InputSearch.tsx +3 -4
  26. package/Input/InputTextArea.tsx +3 -4
  27. package/Layout/Card.tsx +8 -26
  28. package/Layout/FloatingButton.tsx +3 -3
  29. package/Layout/Item.tsx +1 -10
  30. package/Layout/Screen.tsx +146 -40
  31. package/Layout/Section.tsx +5 -18
  32. package/Layout/index.ts +4 -4
  33. package/Layout/utils.ts +280 -5
  34. package/Popup/PopupNotify.tsx +33 -22
  35. package/Popup/PopupPromotion.tsx +20 -8
  36. package/Popup/utils.ts +32 -0
  37. package/Text/index.tsx +2 -11
  38. package/Text/utils.ts +1 -2
  39. package/package.json +4 -3
  40. package/Consts/designSystemFont.ts +0 -38
  41. package/Layout/GridSystem.tsx +0 -137
@@ -27,7 +27,9 @@ import StackScreen from '../StackScreen';
27
27
  import { BottomTabProps } from '../types';
28
28
  import { getOptions, getStackOptions, useAppState } from '../utils';
29
29
  import BottomTabBar from './BottomTabBar';
30
+ import { DuoTabBar } from './DuoTabBar';
30
31
  import { ApplicationContext, MiniAppContext } from '../../Context';
32
+ import { useScreenLayout } from '../../Layout';
31
33
 
32
34
  const Tab = createBottomTabNavigator();
33
35
  const Stack = createStackNavigator();
@@ -36,7 +38,13 @@ const TabScreen: React.FC<any> = ({ route, navigation }) => {
36
38
  const { navigator } = useContext(ApplicationContext);
37
39
  const context = useContext<any>(MiniAppContext);
38
40
  const { nested, options, screen, initialParams } = route?.params;
39
- const insets = useSafeAreaInsets();
41
+ const { headerHeight, headerStatusBarHeight } = useScreenLayout();
42
+ const headerStyleOptions = {
43
+ headerStyle: {
44
+ height: headerHeight,
45
+ },
46
+ headerStatusBarHeight,
47
+ };
40
48
 
41
49
  const opacityValue = 0.3;
42
50
  const scaleValue = 0.97;
@@ -139,11 +147,7 @@ const TabScreen: React.FC<any> = ({ route, navigation }) => {
139
147
  return (
140
148
  <Animated.View style={[styles.container, tabAnimatedStyle]}>
141
149
  <Stack.Navigator
142
- screenOptions={{
143
- headerStyle: {
144
- height: 52 + insets.top,
145
- },
146
- }}
150
+ screenOptions={headerStyleOptions}
147
151
  >
148
152
  <Stack.Screen
149
153
  name="Stack"
@@ -174,11 +178,7 @@ const TabScreen: React.FC<any> = ({ route, navigation }) => {
174
178
  <NavigationIndependentTree>
175
179
  <NavigationContainer>
176
180
  <Stack.Navigator
177
- screenOptions={{
178
- headerStyle: {
179
- height: 52 + insets.top,
180
- },
181
- }}
181
+ screenOptions={headerStyleOptions}
182
182
  >
183
183
  <Stack.Screen
184
184
  name="Stack"
@@ -207,6 +207,7 @@ const BottomTab: React.FC<BottomTabProps> = ({
207
207
  floatingButton,
208
208
  }) => {
209
209
  const { theme, navigator } = useContext(ApplicationContext);
210
+ const { isIPhoneDuo } = useScreenLayout();
210
211
  const dimensions = useWindowDimensions();
211
212
  const insets = useSafeAreaInsets();
212
213
  const initialIndex = tabs.findIndex(i => i.name === initialRouteName);
@@ -306,23 +307,32 @@ const BottomTab: React.FC<BottomTabProps> = ({
306
307
  </View>
307
308
  ),
308
309
  }}
309
- tabBar={props => (
310
- <BottomTabBar
311
- {...props}
312
- floatingButton={floatingButton}
313
- inactiveTintColor={theme.colors.text.hint}
314
- activeTintColor={theme.colors.primary}
315
- style={[
316
- {
317
- height:
318
- 64 +
319
- (Platform.OS === 'ios'
320
- ? Math.min(insets.bottom, 21)
321
- : insets.bottom),
322
- },
323
- ]}
324
- />
325
- )}
310
+ tabBar={props =>
311
+ isIPhoneDuo ? (
312
+ <DuoTabBar
313
+ {...props}
314
+ floatingButton={floatingButton}
315
+ inactiveTintColor={theme.colors.text.default}
316
+ activeTintColor={theme.colors.primary}
317
+ />
318
+ ) : (
319
+ <BottomTabBar
320
+ {...props}
321
+ floatingButton={floatingButton}
322
+ inactiveTintColor={theme.colors.text.hint}
323
+ activeTintColor={theme.colors.primary}
324
+ style={[
325
+ {
326
+ height:
327
+ 64 +
328
+ (Platform.OS === 'ios'
329
+ ? Math.min(insets.bottom, 21)
330
+ : insets.bottom),
331
+ },
332
+ ]}
333
+ />
334
+ )
335
+ }
326
336
  initialRouteName={initialRouteName}
327
337
  >
328
338
  {tabs.map((item, index) => {
@@ -0,0 +1,177 @@
1
+ import React, { useContext, useState } from 'react';
2
+ import { StyleSheet, View } from 'react-native';
3
+ import LinearGradient from 'react-native-linear-gradient';
4
+ import Animated, {
5
+ Extrapolation,
6
+ interpolate,
7
+ runOnJS,
8
+ useAnimatedReaction,
9
+ useAnimatedStyle,
10
+ } from 'react-native-reanimated';
11
+ import { ApplicationContext } from '../../Context';
12
+ import { Shadow } from '../../Consts';
13
+ import { Image } from '../../Image';
14
+ import { AnimatedCompatValue, useNormalizedSharedValue } from '../utils';
15
+ import { GlassView } from './OptionalGlassView';
16
+
17
+ // extended headers run their gradient this far below the header, as off Duo
18
+ const EXTENDED_GRADIENT_EXTRA = 52;
19
+ // scroll distance over which the extended gradient collapses to the header
20
+ const EXTENDED_COLLAPSE_DISTANCE = 100;
21
+ // scroll distance over which the bar material fades in
22
+ const FADE_DISTANCE = 16;
23
+ const TRANSLUCENT_ALPHA = 'CC';
24
+
25
+ /**
26
+ * iPhone Duo header background: glass running edge to edge, behind the status bar
27
+ * column too, shown once content scrolls under it
28
+ */
29
+ const DuoGlassBackground: React.FC<{
30
+ animatedValue?: AnimatedCompatValue;
31
+ // scroll offset where the bar starts to show, e.g. below an animated banner
32
+ fadeStart?: number;
33
+ }> = ({ animatedValue, fadeStart = 0 }) => {
34
+ const { theme } = useContext(ApplicationContext);
35
+ const sharedValue = useNormalizedSharedValue(animatedValue);
36
+ const [scrolled, setScrolled] = useState(false);
37
+
38
+ useAnimatedReaction(
39
+ () => sharedValue.value > fadeStart,
40
+ (isScrolled, wasScrolled) => {
41
+ if (GlassView && isScrolled !== wasScrolled) {
42
+ runOnJS(setScrolled)(isScrolled);
43
+ }
44
+ },
45
+ [fadeStart],
46
+ );
47
+
48
+ const fadeStyle = useAnimatedStyle(() => ({
49
+ opacity: interpolate(
50
+ sharedValue.value,
51
+ [fadeStart, fadeStart + FADE_DISTANCE],
52
+ [0, 1],
53
+ Extrapolation.CLAMP,
54
+ ),
55
+ }));
56
+
57
+ return (
58
+ <View pointerEvents={'none'} style={StyleSheet.absoluteFill}>
59
+ {GlassView ? (
60
+ // UIVisualEffectView breaks under alpha, so glass toggles its effect instead
61
+ <GlassView
62
+ effect={scrolled ? 'glass' : 'none'}
63
+ useShadow
64
+ style={StyleSheet.absoluteFill}
65
+ />
66
+ ) : (
67
+ <Animated.View
68
+ style={[
69
+ StyleSheet.absoluteFill,
70
+ styles.translucentBar,
71
+ {
72
+ backgroundColor:
73
+ theme.colors.background.surface + TRANSLUCENT_ALPHA,
74
+ borderBottomColor: theme.colors.border.default,
75
+ },
76
+ fadeStyle,
77
+ ]}
78
+ />
79
+ )}
80
+ </View>
81
+ );
82
+ };
83
+
84
+ /**
85
+ * pink header gradient drawn under the content: header-high for default headers
86
+ * (scrolls away), 52 taller for extended ones (collapses and fades, as off Duo)
87
+ */
88
+ const DuoScrollGradient: React.FC<{
89
+ animatedValue?: AnimatedCompatValue;
90
+ gradientColor?: string;
91
+ headerBackground?: string;
92
+ heightHeader: number;
93
+ extended?: boolean;
94
+ }> = ({
95
+ animatedValue,
96
+ gradientColor,
97
+ headerBackground,
98
+ heightHeader,
99
+ extended,
100
+ }) => {
101
+ const { theme } = useContext(ApplicationContext);
102
+ const sharedValue = useNormalizedSharedValue(animatedValue);
103
+ const color = gradientColor ?? theme.colors.gradient;
104
+ const image = headerBackground ?? theme.assets?.headerBackground;
105
+
106
+ const scrollStyle = useAnimatedStyle(() => {
107
+ if (!extended) {
108
+ return {
109
+ height: heightHeader,
110
+ transform: [{ translateY: -Math.max(sharedValue.value, 0) }],
111
+ };
112
+ }
113
+ return {
114
+ height: interpolate(
115
+ sharedValue.value,
116
+ [0, EXTENDED_COLLAPSE_DISTANCE],
117
+ [heightHeader + EXTENDED_GRADIENT_EXTRA, heightHeader],
118
+ Extrapolation.CLAMP,
119
+ ),
120
+ opacity: interpolate(
121
+ sharedValue.value,
122
+ [0, EXTENDED_GRADIENT_EXTRA],
123
+ [1, 0],
124
+ Extrapolation.CLAMP,
125
+ ),
126
+ };
127
+ });
128
+
129
+ if (!color) {
130
+ return null;
131
+ }
132
+
133
+ return (
134
+ <Animated.View
135
+ pointerEvents={'none'}
136
+ style={[styles.gradient, scrollStyle]}
137
+ >
138
+ {/* extended squeezes the whole fade into its box like main; default clips it */}
139
+ <View style={extended ? StyleSheet.absoluteFill : styles.gradientFill}>
140
+ <LinearGradient
141
+ colors={[color, color + '00']}
142
+ style={StyleSheet.absoluteFill}
143
+ >
144
+ {!!image && (
145
+ <Image
146
+ style={styles.gradientFill}
147
+ source={{ uri: image }}
148
+ loading={false}
149
+ />
150
+ )}
151
+ </LinearGradient>
152
+ </View>
153
+ </Animated.View>
154
+ );
155
+ };
156
+
157
+ const styles = StyleSheet.create({
158
+ translucentBar: {
159
+ borderBottomWidth: StyleSheet.hairlineWidth,
160
+ ...Shadow.Light,
161
+ },
162
+ gradient: {
163
+ position: 'absolute',
164
+ top: 0,
165
+ left: 0,
166
+ right: 0,
167
+ overflow: 'hidden',
168
+ },
169
+ // default header gradient keeps the off-Duo 375:154 shape, the header clips it
170
+ gradientFill: {
171
+ width: '100%',
172
+ position: 'absolute',
173
+ aspectRatio: 375 / 154,
174
+ },
175
+ });
176
+
177
+ export { DuoGlassBackground, DuoScrollGradient };
@@ -1,6 +1,6 @@
1
1
  import React, { Ref, useContext } from 'react';
2
2
  import LinearGradient from 'react-native-linear-gradient';
3
- import { Dimensions, Platform, StyleSheet, View } from 'react-native';
3
+ import { Platform, StyleSheet, View } from 'react-native';
4
4
  import Animated, {
5
5
  Extrapolation,
6
6
  interpolate,
@@ -14,21 +14,18 @@ import { Colors, Radius, Spacing } from '../../Consts';
14
14
  import { Image } from '../../Image';
15
15
  import { SearchHeaderProps } from '../types';
16
16
  import BackgroundImageView from './BackgroundImageView';
17
- import {
18
- AnimatedCompatValue,
19
- useNormalizedSharedValue,
20
- } from '../utils';
17
+ import { AnimatedCompatValue, useNormalizedSharedValue } from '../utils';
18
+ import { useScreenLayout } from '../../Layout';
21
19
 
22
20
  const SCREEN_PADDING = 12;
23
21
  const BACK_WIDTH = 28;
24
-
25
- const { width: screenWidth } = Dimensions.get('window');
22
+ const TOOLKIT_WIDTH = 73;
26
23
 
27
24
  const HeaderExtendHeader: React.FC<{
28
25
  headerType?: HeaderType;
29
26
  animatedValue: AnimatedCompatValue;
30
27
  heightHeader: number;
31
- headerRightWidth: number;
28
+ headerRightWidth?: number;
32
29
  inputSearchProps?: SearchHeaderProps;
33
30
  inputSearchRef?: Ref<InputRef>;
34
31
  navigation?: Navigation;
@@ -39,7 +36,7 @@ const HeaderExtendHeader: React.FC<{
39
36
  headerType = 'default',
40
37
  animatedValue,
41
38
  heightHeader,
42
- headerRightWidth = 73,
39
+ headerRightWidth: customHeaderRightWidth,
43
40
  inputSearchProps,
44
41
  inputSearchRef,
45
42
  useShadowHeader: useShadowHeaderProp = true,
@@ -51,7 +48,19 @@ const HeaderExtendHeader: React.FC<{
51
48
  const sharedValue = useNormalizedSharedValue(animatedValue);
52
49
  const gradientColor = customGradientColor ?? theme.colors.gradient;
53
50
  const headerBackground = customBackground ?? theme.assets?.headerBackground;
54
- const leftPosition = inputSearchProps?.leftPosition || BACK_WIDTH + 20;
51
+ const layout = useScreenLayout();
52
+
53
+ const leftPosition =
54
+ inputSearchProps?.leftPosition ||
55
+ (layout.sideBar ? SCREEN_PADDING : BACK_WIDTH + 20);
56
+ const headerRightWidth =
57
+ customHeaderRightWidth ?? (layout.sideBar ? 0 : TOOLKIT_WIDTH);
58
+ const contentLeft = layout.insetLeft + SCREEN_PADDING;
59
+ const contentRight = layout.insetLeft + layout.contentWidth;
60
+ const collapsedLeft = layout.insetLeft + leftPosition;
61
+ const searchWidth = layout.contentWidth - SCREEN_PADDING * 2;
62
+ const collapsedSearchWidth =
63
+ contentRight - collapsedLeft - SCREEN_PADDING - headerRightWidth;
55
64
 
56
65
  let useShadowHeader = useShadowHeaderProp;
57
66
  if (inputSearchProps && Platform.OS === 'android') {
@@ -70,7 +79,12 @@ const HeaderExtendHeader: React.FC<{
70
79
  }));
71
80
 
72
81
  const gradientOpacityStyle = useAnimatedStyle(() => ({
73
- opacity: interpolate(sharedValue.value, [0, 52], [1, 0], Extrapolation.CLAMP),
82
+ opacity: interpolate(
83
+ sharedValue.value,
84
+ [0, 52],
85
+ [1, 0],
86
+ Extrapolation.CLAMP,
87
+ ),
74
88
  }));
75
89
 
76
90
  const searchTranslateStyle = useAnimatedStyle(() => ({
@@ -79,7 +93,7 @@ const HeaderExtendHeader: React.FC<{
79
93
  translateX: interpolate(
80
94
  sharedValue.value,
81
95
  [0, 100],
82
- [SCREEN_PADDING, leftPosition],
96
+ [contentLeft, collapsedLeft],
83
97
  Extrapolation.CLAMP,
84
98
  ),
85
99
  },
@@ -87,19 +101,19 @@ const HeaderExtendHeader: React.FC<{
87
101
  width: interpolate(
88
102
  sharedValue.value,
89
103
  [0, 100],
90
- [
91
- screenWidth - SCREEN_PADDING * 2,
92
- screenWidth - leftPosition - 12 - headerRightWidth,
93
- ],
104
+ [searchWidth, collapsedSearchWidth],
94
105
  Extrapolation.CLAMP,
95
106
  ),
96
107
  }));
97
108
 
98
109
  const searchBackgroundStyle = useAnimatedStyle(() => {
99
110
  const t = Math.min(Math.max(sharedValue.value / 100, 0), 1);
100
- return { backgroundColor: t === 0
101
- ? theme.colors.background.surface
102
- : theme.colors.background.default };
111
+ return {
112
+ backgroundColor:
113
+ t === 0
114
+ ? theme.colors.background.surface
115
+ : theme.colors.background.default,
116
+ };
103
117
  });
104
118
 
105
119
  const extendedHeightStyle = useAnimatedStyle(() => ({
@@ -124,9 +138,7 @@ const HeaderExtendHeader: React.FC<{
124
138
  <Animated.View
125
139
  style={[
126
140
  styles.headerBox,
127
- headerType === 'extended'
128
- ? heightStyle
129
- : { height: heightHeader },
141
+ headerType === 'extended' ? heightStyle : { height: heightHeader },
130
142
  ]}
131
143
  >
132
144
  {!!gradientColor && (
@@ -162,10 +174,7 @@ const HeaderExtendHeader: React.FC<{
162
174
  style={[{ marginVertical: Spacing.S }, searchTranslateStyle]}
163
175
  >
164
176
  <Animated.View
165
- style={[
166
- { borderRadius: Radius.XL },
167
- searchBackgroundStyle,
168
- ]}
177
+ style={[{ borderRadius: Radius.XL }, searchBackgroundStyle]}
169
178
  >
170
179
  <InputSearch
171
180
  {...inputSearchProps}
@@ -191,7 +200,11 @@ const HeaderExtendHeader: React.FC<{
191
200
  />
192
201
  {!!gradientColor && (
193
202
  <Animated.View
194
- style={[styles.extendedHeader, gradientOpacityStyle, extendedHeightStyle]}
203
+ style={[
204
+ styles.extendedHeader,
205
+ gradientOpacityStyle,
206
+ extendedHeightStyle,
207
+ ]}
195
208
  >
196
209
  <LinearGradient
197
210
  colors={[gradientColor, gradientColor + '00']}
@@ -4,6 +4,8 @@ import React, { useCallback, useContext, useEffect } from 'react';
4
4
  import { ApplicationContext, MiniAppContext } from '../../Context';
5
5
  import { PopupNotify } from '../../Popup';
6
6
  import { NavigationButton } from './NavigationButton';
7
+ import { SideBarButton } from './SideBarButton';
8
+ import { useSideBarItemStyle } from '../../Layout/utils';
7
9
 
8
10
  /**
9
11
  * default header left used for nav
@@ -13,9 +15,11 @@ const HeaderLeft: React.FC<HeaderBackProps> = ({
13
15
  preventBack,
14
16
  onPressLeftHeader,
15
17
  onBackHandler,
18
+ floating = false,
16
19
  }) => {
17
20
  const context = useContext<any>(MiniAppContext);
18
21
  const { navigator } = useContext(ApplicationContext);
22
+ const sideBarStyle = useSideBarItemStyle('left', 0);
19
23
 
20
24
  const goBack = useCallback(() => {
21
25
  const canGoBack = navigator?.ref?.current?.canGoBack?.();
@@ -72,6 +76,19 @@ const HeaderLeft: React.FC<HeaderBackProps> = ({
72
76
  return () => backHandler.remove();
73
77
  }, [goBackSafe]);
74
78
 
79
+ if (floating && sideBarStyle) {
80
+ return (
81
+ <View style={sideBarStyle} pointerEvents={'box-none'}>
82
+ <SideBarButton
83
+ accessibilityLabel="btn_navigation_back"
84
+ icon="arrow-back"
85
+ tintColor={tintColor}
86
+ onPress={goBackSafe}
87
+ />
88
+ </View>
89
+ );
90
+ }
91
+
75
92
  return (
76
93
  <View style={styles.headerLeft}>
77
94
  <NavigationButton
@@ -13,6 +13,8 @@ import { PopupNotify } from '../../Popup';
13
13
  import { Tool, ToolGroup } from '../types';
14
14
  import { Icon } from '../../Icon';
15
15
  import { Text } from '../../Text';
16
+ import { useSideBarItemStyle } from '../../Layout/utils';
17
+ import { SideBarButton, SideBarGroup, SideBarGroupItem } from './SideBarButton';
16
18
 
17
19
  const DID_SYNC_NEW_HOME = 'did_sync_new_home';
18
20
 
@@ -21,8 +23,9 @@ const DID_SYNC_NEW_HOME = 'did_sync_new_home';
21
23
  */
22
24
  const HeaderRight: React.FC<any> = props => {
23
25
  const { translate } = useContext(ApplicationContext);
24
- const { headerRight = {} } = props;
26
+ const { headerRight = {}, floating = false } = props;
25
27
  const { useOnBoarding = false, buttonOnBoarding, onPress } = headerRight;
28
+ const sideBarStyle = useSideBarItemStyle('right', 1);
26
29
 
27
30
  if (typeof props.headerRight === 'function') {
28
31
  return props.headerRight(props);
@@ -38,6 +41,18 @@ const HeaderRight: React.FC<any> = props => {
38
41
  );
39
42
  }
40
43
 
44
+ if (floating && sideBarStyle) {
45
+ return (
46
+ <View style={sideBarStyle} pointerEvents={'box-none'}>
47
+ <HeaderToolkitAction
48
+ {...props.headerRight}
49
+ tintColor={props.tintColor}
50
+ vertical
51
+ />
52
+ </View>
53
+ );
54
+ }
55
+
41
56
  return (
42
57
  <View style={styles.headerRightButton}>
43
58
  <HeaderToolkitAction {...props.headerRight} tintColor={props.tintColor} />
@@ -56,6 +71,7 @@ const HeaderToolkitAction: React.FC<any> = ({
56
71
  useMore = false,
57
72
  tools = [],
58
73
  useCloseIcon = false,
74
+ vertical = false,
59
75
  }) => {
60
76
  const { navigator } = useContext(ApplicationContext);
61
77
  const context = useContext<any>(MiniAppContext);
@@ -260,6 +276,43 @@ const HeaderToolkitAction: React.FC<any> = ({
260
276
  group?.items?.some?.(tool => tool?.showBadge),
261
277
  );
262
278
 
279
+ const useHelpCenter = context.appId !== 'vn.momo.helpcenter';
280
+ const closeIcon = useCloseIcon
281
+ ? '16_navigation_close_circle'
282
+ : '16_basic_home';
283
+
284
+ if (vertical) {
285
+ return (
286
+ <View style={styles.sideBarColumn}>
287
+ {useShortcut && (
288
+ <SideBarButton
289
+ disabled={isLoading}
290
+ icon={iconShortcut}
291
+ onPress={shortcutOnPress}
292
+ tintColor={tintColor}
293
+ showBadge={showBadge}
294
+ />
295
+ )}
296
+ <SideBarGroup tintColor={tintColor}>
297
+ {useHelpCenter && (
298
+ <SideBarGroupItem
299
+ accessibilityLabel={'btn_navigation_help_center'}
300
+ icon={'help_center'}
301
+ tintColor={tintColor}
302
+ onPress={onPressHelpCenter}
303
+ />
304
+ )}
305
+ <SideBarGroupItem
306
+ accessibilityLabel={'btn_navigation_close'}
307
+ icon={closeIcon}
308
+ tintColor={tintColor}
309
+ onPress={onClose}
310
+ />
311
+ </SideBarGroup>
312
+ </View>
313
+ );
314
+ }
315
+
263
316
  return (
264
317
  <View style={Styles.row}>
265
318
  {useShortcut && (
@@ -280,7 +333,7 @@ const HeaderToolkitAction: React.FC<any> = ({
280
333
  },
281
334
  ]}
282
335
  >
283
- {context.appId !== 'vn.momo.helpcenter' && (
336
+ {useHelpCenter && (
284
337
  <>
285
338
  <TouchableOpacity
286
339
  accessibilityLabel={'btn_navigation_help_center'}
@@ -299,13 +352,7 @@ const HeaderToolkitAction: React.FC<any> = ({
299
352
  style={styles.toolkitButton}
300
353
  hitSlop={{ top: 7, bottom: 7, left: 0, right: 7 }}
301
354
  >
302
- <Icon
303
- color={tintColor}
304
- source={
305
- useCloseIcon ? '16_navigation_close_circle' : '16_basic_home'
306
- }
307
- size={20}
308
- />
355
+ <Icon color={tintColor} source={closeIcon} size={20} />
309
356
  </TouchableOpacity>
310
357
  </View>
311
358
  </View>
@@ -376,6 +423,9 @@ const styles = StyleSheet.create({
376
423
  width: 0.5,
377
424
  height: 12,
378
425
  },
426
+ sideBarColumn: {
427
+ gap: Spacing.M,
428
+ },
379
429
  headerLeft: {
380
430
  marginLeft: 12,
381
431
  },