For all presses I am using the component.

I have several components that come in the form of cards, and some of them have buttons on them. Most of them are optionally buttons themselves, but I already have my IconButton component taking care of the nesting through the use of event.stopPropagation() in the press functions.

I also have a wrapper component to flip the contained card and display extra information on the back, which again is pressable in and of itself, and has a button absolutely positioned into the corner.

My problem is that one of my cards is a numeric input card, which has increment and decrement IconButtons, but these buttons are not getting pressed when I wrap it with the flipper. Logging from the presses, I have determined that the press action is going to the CardFlipper's body Pressable, and while I have worked around the card press requirement by simply moving the press from the child to the flipper, I cannot do the same with my numeric input card.

Styling concerns: None of the pressables are being raised or lowered with the zIndex value, and only the flip buttons on the flip wrapper use 's hitSlop value as they are small buttons. Additionally, the flip wrapper uses react-native-reanimated to animate the flipping motion, but the body's pressable wraps the animated view, not the other way around.

IconButton render

return (
        <View style={[styles.container, style, {
            borderWidth: borderless ? 0 : StyleSheet.hairlineWidth,
            height: defaultedFontSize + 20
        }]}>
            <Pressable
                style={[styles.press, { padding: pressPadding }]}
                onPress={event => {
                    event.stopPropagation();
                    onPress();
                }}
                onLongPress={event => {
                    event.stopPropagation();
                    onLongPress && onLongPress();
                }}
                android_ripple={{
                    color: iconColor,
                    borderless: false
                }}
                disabled={disabled}
                hitSlop={hitSlop}
            >
                <MaterialCommunityIcons name={icon} size={defaultedFontSize} color={iconColor} />
                {name ? <ShowcardGothic.Text style={[styles.text, { fontSize: textFontSize }]}>{name}</ShowcardGothic.Text> : null}
            </Pressable>
        </View>
    );

TextInputCard render

return (
        <Pressable
            style={styles().container}
            onPress={onPress}
            onLongPress={onLongPress}
        >
            <View style={styles().header}>
                <ShowcardGothic.Text>{name}</ShowcardGothic.Text>
            </View>
            <View style={styles().contentContainer}>
                <IconWindow icons={getDigitalIcons()} squeeze />
                <Vertical width={5} />
                <View style={styles().description}>
                    <IconButton icon="minus-thick" onPress={() => decrement()} onLongPress={() => decrement(10)} />
                    <Horizontal width={20} />
                    <IconButton icon="plus-thick"  onPress={() => increment()} onLongPress={() => increment(10)} />
                </View>
            </View>
        </Pressable>
    );

CardFlipper render

return (
        <Pressable onPress={onPress} onLongPress={onLongPress}>
            <Animated.View style={[styles(defaultedScale).flipperFront, frontAnimatedStyle]}>
                {children}
                <IconButton
                    icon="arrow-u-left-bottom-bold"
                    style={{
                        position: 'absolute',
                        top: cardHeight * defaultedScale - 30,
                        left: cardWidth * defaultedScale - 30
                    }}
                    fontSize={14}
                    onPress={() => flip.value = (flip.value + 1) % 2}
                    borderless
                />
            </Animated.View>
            <Animated.View style={[styles(defaultedScale).flipperBack, backAnimatedStyle]}>
                {typeof back === 'string' ? (
                    <ShowcardGothic.Text adjustsFontSizeToFit>{back}</ShowcardGothic.Text>
                ) : back}
                <IconButton
                    icon="arrow-u-right-bottom-bold"
                    style={{
                        position: 'absolute',
                        top: cardHeight * defaultedScale - 30,
                        right: cardWidth * defaultedScale - 30
                    }}
                    fontSize={14}
                    onPress={() => flip.value = (flip.value + 1) % 2}
                    hitSlop={10}
                    borderless
                />
            </Animated.View>
        </Pressable>
    );

I have attempted to put event.stopPropagation() on all of the pressable onPresses and onLongPresses. Additionally, I have attempted putting pressables inside the animated views instead of outside both, but neither change has affected the output.

I have also tried replacing the flipper's pressable view with a fragment, to the same effect, but then there is no outer onPress to be called.

Before turning the flipping functionality into a wrapper component for reusability, I had it in one of my more basic card components, but I would rather have the flipper wrapper instead of manually animating every card I want to flip.

Other notes: ShowcardGothic is a Text wrapper providing the font of the same name React native version is 0.73.0, react at 18.2.0, reanimated at ^3.6.1; recently created project

1

There are 1 best solutions below

1
On

I have since discovered, after commenting out the button to flip on the back side of the animated card. Doing this showed that the root cause is actually that the back view is layered over the front view, and I have corrected it by adding zIndex parameters to my animated style to keep the front facing side on top