Skip to content

Commit e11a51a

Browse files
satya164Trancever
authored andcommitted
feat: add renderTouchable prop to BottomNavigation (#1901)
1 parent ce7ad22 commit e11a51a

File tree

2 files changed

+44
-24
lines changed

2 files changed

+44
-24
lines changed

src/components/BottomNavigation.tsx

Lines changed: 41 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
View,
66
Animated,
77
TouchableWithoutFeedback,
8+
TouchableWithoutFeedbackProps,
89
StyleSheet,
910
StyleProp,
1011
Platform,
@@ -44,6 +45,14 @@ type TabPressEvent = {
4445
preventDefault(): void;
4546
};
4647

48+
type TouchableProps = TouchableWithoutFeedbackProps & {
49+
key: string;
50+
children: React.ReactNode;
51+
borderless?: boolean;
52+
centered?: boolean;
53+
rippleColor?: string;
54+
};
55+
4756
type Props = {
4857
/**
4958
* Whether the shifting style is used, the active tab appears wider and the inactive tabs won't have a label.
@@ -147,6 +156,11 @@ type Props = {
147156
focused: boolean;
148157
color: string;
149158
}) => React.ReactNode;
159+
/**
160+
* Callback which returns a React element to be used as the touchable for the tab item.
161+
* Renders a `TouchableRipple` on Android and `TouchableWithoutFeedback` with `View` on iOS.
162+
*/
163+
renderTouchable?: (props: TouchableProps) => React.ReactNode;
150164
/**
151165
* Get label text for the tab, uses `route.title` by default. Use `renderLabel` to replace label component.
152166
*/
@@ -263,11 +277,16 @@ const MAX_TAB_WIDTH = 168;
263277
const BAR_HEIGHT = 56;
264278
const FAR_FAR_AWAY = 9999;
265279

266-
// @ts-ignore
267280
const Touchable = TouchableRipple.supported
268281
? TouchableRipple
269-
: // eslint-disable-next-line @typescript-eslint/no-unused-vars
270-
({ style, children, borderless, centered, rippleColor, ...rest }: any) => (
282+
: ({
283+
style,
284+
children,
285+
borderless: _0,
286+
centered: _1,
287+
rippleColor: _2,
288+
...rest
289+
}: TouchableProps) => (
271290
<TouchableWithoutFeedback {...rest}>
272291
<View style={style}>{children}</View>
273292
</TouchableWithoutFeedback>
@@ -594,6 +613,7 @@ class BottomNavigation extends React.Component<Props, State> {
594613
renderScene,
595614
renderIcon,
596615
renderLabel,
616+
renderTouchable = (props: TouchableProps) => <Touchable {...props} />,
597617
getLabelText = ({ route }: { route: Route }) => route.title,
598618
getBadge = ({ route }: { route: Route }) => route.badge,
599619
getColor = ({ route }: { route: Route }) => route.color,
@@ -820,23 +840,22 @@ class BottomNavigation extends React.Component<Props, State> {
820840

821841
const badge = getBadge({ route });
822842

823-
return (
824-
<Touchable
825-
key={route.key}
826-
borderless
827-
centered
828-
rippleColor={touchColor}
829-
onPress={() => this.handleTabPress(index)}
830-
testID={getTestID({ route })}
831-
accessibilityLabel={getAccessibilityLabel({ route })}
832-
accessibilityTraits={
833-
focused ? ['button', 'selected'] : 'button'
834-
}
835-
accessibilityComponentType="button"
836-
accessibilityRole="button"
837-
accessibilityStates={['selected']}
838-
style={styles.item}
839-
>
843+
return renderTouchable({
844+
key: route.key,
845+
borderless: true,
846+
centered: true,
847+
rippleColor: touchColor,
848+
onPress: () => this.handleTabPress(index),
849+
testID: getTestID({ route }),
850+
accessibilityLabel: getAccessibilityLabel({ route }),
851+
accessibilityTraits: focused
852+
? ['button', 'selected']
853+
: 'button',
854+
accessibilityComponentType: 'button',
855+
accessibilityRole: 'button',
856+
accessibilityStates: ['selected'],
857+
style: styles.item,
858+
children: (
840859
<View pointerEvents="none">
841860
<Animated.View
842861
style={[
@@ -964,8 +983,8 @@ class BottomNavigation extends React.Component<Props, State> {
964983
<View style={styles.labelContainer} />
965984
)}
966985
</View>
967-
</Touchable>
968-
);
986+
),
987+
});
969988
})}
970989
</SafeAreaView>
971990
</Animated.View>

src/components/TouchableRipple/index.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
ViewStyle,
66
StyleSheet,
77
StyleProp,
8+
GestureResponderEvent,
89
} from 'react-native';
910
import color from 'color';
1011
import { withTheme } from '../../core/theming';
@@ -31,11 +32,11 @@ type Props = React.ComponentPropsWithRef<typeof TouchableWithoutFeedback> & {
3132
/**
3233
* Function to execute on press. If not set, will cause the touchable to be disabled.
3334
*/
34-
onPress?: () => void | null;
35+
onPress?: (e: GestureResponderEvent) => void;
3536
/**
3637
* Function to execute on long press.
3738
*/
38-
onLongPress?: () => void;
39+
onLongPress?: (e: GestureResponderEvent) => void;
3940
/**
4041
* Color of the ripple effect (Android >= 5.0 and Web).
4142
*/

0 commit comments

Comments
 (0)