Skip to content

Commit

Permalink
Merge pull request #38380 from bernhardoj/fix/38369-avatar-bottom-tab…
Browse files Browse the repository at this point in the history
…-bar-pressable-area

Fix area around bottom tab avatar isn't clickable
  • Loading branch information
mountiny authored Mar 18, 2024
2 parents 0af974d + 19a772d commit 59b3919
Show file tree
Hide file tree
Showing 6 changed files with 135 additions and 161 deletions.
69 changes: 29 additions & 40 deletions src/components/FloatingActionButton.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,20 @@
import type {ForwardedRef} from 'react';
import React, {forwardRef, useEffect, useRef} from 'react';
// eslint-disable-next-line no-restricted-imports
import type {GestureResponderEvent, Role, Text} from 'react-native';
import {Platform, View} from 'react-native';
import type {GestureResponderEvent, Role, Text, View} from 'react-native';
import {Platform} from 'react-native';
import Animated, {createAnimatedPropAdapter, Easing, interpolateColor, processColor, useAnimatedProps, useAnimatedStyle, useSharedValue, withTiming} from 'react-native-reanimated';
import Svg, {Path} from 'react-native-svg';
import useLocalize from '@hooks/useLocalize';
import useTheme from '@hooks/useTheme';
import useThemeStyles from '@hooks/useThemeStyles';
import variables from '@styles/variables';
import {PressableWithoutFeedback} from './Pressable';
import PressableWithFeedback from './Pressable/PressableWithFeedback';
import Tooltip from './Tooltip/PopoverAnchorTooltip';

const AnimatedPath = Animated.createAnimatedComponent(Path);
AnimatedPath.displayName = 'AnimatedPath';

const AnimatedPressable = Animated.createAnimatedComponent(PressableWithFeedback);
AnimatedPressable.displayName = 'AnimatedPressable';

type AdapterPropsRecord = {
type: number;
payload?: number | null;
Expand Down Expand Up @@ -104,41 +100,34 @@ function FloatingActionButton({onPress, isActive, accessibilityLabel, role}: Flo
};

return (
<PressableWithoutFeedback
style={styles.h100}
accessibilityLabel={accessibilityLabel}
onPress={toggleFabAction}
>
<View style={styles.bottomTabBarItem}>
<Tooltip text={translate('common.create')}>
<AnimatedPressable
ref={(el) => {
fabPressable.current = el ?? null;
if (buttonRef && 'current' in buttonRef) {
buttonRef.current = el ?? null;
}
}}
accessibilityLabel={accessibilityLabel}
role={role}
pressDimmingValue={1}
onPress={toggleFabAction}
onLongPress={() => {}}
shouldUseHapticsOnLongPress={false}
style={[styles.floatingActionButton, animatedStyle]}
<Tooltip text={translate('common.create')}>
<PressableWithoutFeedback
ref={(el) => {
fabPressable.current = el ?? null;
if (buttonRef && 'current' in buttonRef) {
buttonRef.current = el ?? null;
}
}}
style={[styles.h100, styles.bottomTabBarItem]}
accessibilityLabel={accessibilityLabel}
onPress={toggleFabAction}
onLongPress={() => {}}
role={role}
shouldUseHapticsOnLongPress={false}
>
<Animated.View style={[styles.floatingActionButton, animatedStyle]}>
<Svg
width={variables.iconSizeNormal}
height={variables.iconSizeNormal}
>
<Svg
width={variables.iconSizeNormal}
height={variables.iconSizeNormal}
>
<AnimatedPath
d="M12,3c0-1.1-0.9-2-2-2C8.9,1,8,1.9,8,3v5H3c-1.1,0-2,0.9-2,2c0,1.1,0.9,2,2,2h5v5c0,1.1,0.9,2,2,2c1.1,0,2-0.9,2-2v-5h5c1.1,0,2-0.9,2-2c0-1.1-0.9-2-2-2h-5V3z"
animatedProps={animatedProps}
/>
</Svg>
</AnimatedPressable>
</Tooltip>
</View>
</PressableWithoutFeedback>
<AnimatedPath
d="M12,3c0-1.1-0.9-2-2-2C8.9,1,8,1.9,8,3v5H3c-1.1,0-2,0.9-2,2c0,1.1,0.9,2,2,2h5v5c0,1.1,0.9,2,2,2c1.1,0,2-0.9,2-2v-5h5c1.1,0,2-0.9,2-2c0-1.1-0.9-2-2-2h-5V3z"
animatedProps={animatedProps}
/>
</Svg>
</Animated.View>
</PressableWithoutFeedback>
</Tooltip>
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,16 +61,16 @@ function BottomTabBar({isLoadingApp = false}: PurposeForUsingExpensifyModalProps

return (
<View style={styles.bottomTabBarContainer}>
<PressableWithFeedback
onPress={() => {
Navigation.navigate(ROUTES.HOME);
}}
role={CONST.ROLE.BUTTON}
accessibilityLabel={translate('common.chats')}
wrapperStyle={styles.flex1}
style={styles.bottomTabBarItem}
>
<Tooltip text={translate('common.chats')}>
<Tooltip text={translate('common.chats')}>
<PressableWithFeedback
onPress={() => {
Navigation.navigate(ROUTES.HOME);
}}
role={CONST.ROLE.BUTTON}
accessibilityLabel={translate('common.chats')}
wrapperStyle={styles.flex1}
style={styles.bottomTabBarItem}
>
<View>
<Icon
src={Expensicons.ChatBubble}
Expand All @@ -82,13 +82,11 @@ function BottomTabBar({isLoadingApp = false}: PurposeForUsingExpensifyModalProps
<View style={styles.bottomTabStatusIndicator(chatTabBrickRoad === CONST.BRICK_ROAD_INDICATOR_STATUS.INFO ? theme.iconSuccessFill : theme.danger)} />
)}
</View>
</Tooltip>
</PressableWithFeedback>
</PressableWithFeedback>
</Tooltip>

<BottomTabBarFloatingActionButton />
<View style={[styles.flex1, styles.justifyContentCenter, styles.alignItemsCenter]}>
<BottomTabAvatar isSelected={currentTabName === SCREENS.SETTINGS.ROOT} />
</View>
<BottomTabAvatar isSelected={currentTabName === SCREENS.SETTINGS.ROOT} />
</View>
);
}
Expand Down
26 changes: 5 additions & 21 deletions src/pages/home/sidebar/AvatarWithOptionalStatus.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,53 +2,37 @@
import PropTypes from 'prop-types';
import React from 'react';
import {View} from 'react-native';
import PressableWithoutFeedback from '@components/Pressable/PressableWithoutFeedback';
import Text from '@components/Text';
import useLocalize from '@hooks/useLocalize';
import useThemeStyles from '@hooks/useThemeStyles';
import CONST from '@src/CONST';
import PressableAvatarWithIndicator from './PressableAvatarWithIndicator';
import ProfileAvatarWithIndicator from './ProfileAvatarWithIndicator';

const propTypes = {
/** Emoji status */
emojiStatus: PropTypes.string,

/** Whether the avatar is selected */
isSelected: PropTypes.bool,

/** Callback called when the avatar or status icon is pressed */
onPress: PropTypes.func,
};

const defaultProps = {
emojiStatus: '',
isSelected: false,
onPress: () => {},
};

function AvatarWithOptionalStatus({emojiStatus, isSelected, onPress}) {
function AvatarWithOptionalStatus({emojiStatus, isSelected}) {
const styles = useThemeStyles();
const {translate} = useLocalize();

return (
<View style={styles.sidebarStatusAvatarContainer}>
<PressableAvatarWithIndicator
isSelected={isSelected}
onPress={onPress}
/>
<PressableWithoutFeedback
accessibilityLabel={translate('sidebarScreen.buttonMySettings')}
role={CONST.ROLE.BUTTON}
onPress={onPress}
style={[styles.sidebarStatusAvatar]}
>
<ProfileAvatarWithIndicator isSelected={isSelected} />
<View style={[styles.sidebarStatusAvatar]}>
<Text
style={styles.emojiStatusLHN}
numberOfLines={1}
>
{emojiStatus}
</Text>
</PressableWithoutFeedback>
</View>
</View>
);
}
Expand Down
32 changes: 25 additions & 7 deletions src/pages/home/sidebar/BottomTabAvatar.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
/* eslint-disable rulesdir/onyx-props-must-have-default */
import React, {useCallback} from 'react';
import {PressableWithFeedback} from '@components/Pressable';
import Tooltip from '@components/Tooltip';
import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails';
import useLocalize from '@hooks/useLocalize';
import useThemeStyles from '@hooks/useThemeStyles';
import interceptAnonymousUser from '@libs/interceptAnonymousUser';
import Navigation from '@libs/Navigation/Navigation';
import CONST from '@src/CONST';
import ROUTES from '@src/ROUTES';
import AvatarWithOptionalStatus from './AvatarWithOptionalStatus';
import PressableAvatarWithIndicator from './PressableAvatarWithIndicator';
import ProfileAvatarWithIndicator from './ProfileAvatarWithIndicator';

type BottomTabAvatarProps = {
/** Whether the create menu is open or not */
Expand All @@ -16,6 +21,8 @@ type BottomTabAvatarProps = {
};

function BottomTabAvatar({isCreateMenuOpen = false, isSelected = false}: BottomTabAvatarProps) {
const styles = useThemeStyles();
const {translate} = useLocalize();
const currentUserPersonalDetails = useCurrentUserPersonalDetails();
const emojiStatus = currentUserPersonalDetails?.status?.emojiCode ?? '';

Expand All @@ -28,20 +35,31 @@ function BottomTabAvatar({isCreateMenuOpen = false, isSelected = false}: BottomT
interceptAnonymousUser(() => Navigation.navigate(ROUTES.SETTINGS));
}, [isCreateMenuOpen]);

let children;

if (emojiStatus) {
return (
children = (
<AvatarWithOptionalStatus
emojiStatus={emojiStatus}
isSelected={isSelected}
onPress={showSettingsPage}
/>
);
} else {
children = <ProfileAvatarWithIndicator isSelected={isSelected} />;
}

return (
<PressableAvatarWithIndicator
isSelected={isSelected}
onPress={showSettingsPage}
/>
<Tooltip text={translate('profilePage.profile')}>
<PressableWithFeedback
onPress={showSettingsPage}
role={CONST.ROLE.BUTTON}
accessibilityLabel={translate('sidebarScreen.buttonMySettings')}
wrapperStyle={styles.flex1}
style={styles.bottomTabBarItem}
>
{children}
</PressableWithFeedback>
</Tooltip>
);
}

Expand Down
78 changes: 0 additions & 78 deletions src/pages/home/sidebar/PressableAvatarWithIndicator.js

This file was deleted.

Loading

0 comments on commit 59b3919

Please sign in to comment.