index.tsx 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. import React from 'react';
  2. import { View, Text, Pressable, StyleProp, ViewStyle } from 'react-native';
  3. import { Tabs, MaterialTabBar } from 'react-native-collapsible-tab-view';
  4. import { styles } from './styles';
  5. import { Colors } from 'src/theme';
  6. import MarkToUpIcon from '../../../assets/icons/mark-to-up.svg';
  7. import BanIcon from 'assets/icons/messages/ban.svg';
  8. import MessagesDot from '../MessagesDot';
  9. interface Route {
  10. key: string;
  11. title?: string;
  12. icon?: string;
  13. }
  14. type Props = {
  15. index: number;
  16. setIndex: React.Dispatch<React.SetStateAction<number>>;
  17. routes: Route[];
  18. renderScene: (props: { route: any }) => React.ReactNode;
  19. withMark?: boolean;
  20. lazy?: boolean;
  21. withNotification?: number;
  22. maxTabHeight?: number;
  23. tabBarStyle?: StyleProp<ViewStyle>;
  24. sceneStyles?: StyleProp<ViewStyle>;
  25. };
  26. export const HorizontalTabView: React.FC<Props> = ({
  27. index,
  28. setIndex,
  29. routes,
  30. renderScene,
  31. withMark,
  32. lazy = false,
  33. withNotification = 0,
  34. maxTabHeight,
  35. tabBarStyle = {},
  36. sceneStyles = {}
  37. }) => {
  38. const TabItemComponent = ({ name, index: tabIndex, onPress, label, style, onLayout }: any) => {
  39. const fullRoute = routes.find((r) => r.key === name);
  40. return (
  41. <Pressable
  42. onPress={() => onPress(name)}
  43. onLayout={onLayout}
  44. style={[styles.tabLabelWrapper, style, withNotification > 0 ? { marginTop: 3 } : {}]}
  45. >
  46. <View
  47. style={[
  48. styles.tabLabelContainer,
  49. maxTabHeight ? { maxHeight: maxTabHeight } : {},
  50. tabIndex === index ? { backgroundColor: Colors.ORANGE, borderColor: Colors.ORANGE } : {}
  51. ]}
  52. >
  53. {fullRoute?.icon === 'ban' ? (
  54. <BanIcon
  55. width={15}
  56. height={15}
  57. fill={tabIndex === index ? Colors.WHITE : Colors.DARK_BLUE}
  58. />
  59. ) : (
  60. <Text style={[styles.label, tabIndex === index ? { color: Colors.WHITE } : {}]}>
  61. {fullRoute?.title ?? label}
  62. </Text>
  63. )}
  64. {withMark ? (
  65. <MarkToUpIcon height={16} width={16} style={styles.icon} stroke={undefined} />
  66. ) : null}
  67. </View>
  68. {withNotification > 0 && fullRoute?.key === 'received' ? (
  69. <View style={styles.notificationContainer}>
  70. <MessagesDot messagesCount={withNotification} />
  71. </View>
  72. ) : null}
  73. </Pressable>
  74. );
  75. };
  76. return (
  77. <Tabs.Container
  78. renderTabBar={(props) => (
  79. <MaterialTabBar
  80. {...props}
  81. scrollEnabled
  82. indicatorStyle={{ height: 0 }}
  83. activeColor={Colors.ORANGE}
  84. inactiveColor={Colors.DARK_BLUE}
  85. keepActiveTabCentered
  86. contentContainerStyle={{ paddingHorizontal: 0 }}
  87. style={[styles.tabBar, tabBarStyle]}
  88. tabStyle={[styles.tabStyle, maxTabHeight ? { maxHeight: maxTabHeight } : {}]}
  89. TabItemComponent={TabItemComponent}
  90. />
  91. )}
  92. onIndexChange={setIndex}
  93. initialTabName={routes[index]?.key}
  94. lazy={lazy}
  95. headerHeight={0}
  96. headerContainerStyle={styles.tabBar}
  97. containerStyle={[tabBarStyle]}
  98. tabBarHeight={40}
  99. >
  100. {routes.map((route) => (
  101. <Tabs.Tab key={route.key} name={route.key} label={route.title}>
  102. <View
  103. style={[
  104. { flex: 1, width: '100%', paddingTop: 40, paddingHorizontal: '4%' },
  105. sceneStyles
  106. ]}
  107. >
  108. {renderScene({ route })}
  109. </View>
  110. </Tabs.Tab>
  111. ))}
  112. </Tabs.Container>
  113. );
  114. };