Skip to content

Commit

Permalink
fix tooltipis on bottom tab bar
Browse files Browse the repository at this point in the history
  • Loading branch information
adamgrzybowski committed Jan 16, 2025
1 parent 52ce458 commit 667a052
Show file tree
Hide file tree
Showing 6 changed files with 93 additions and 51 deletions.
8 changes: 4 additions & 4 deletions src/components/Navigation/BottomTabBar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import type {SearchQueryString} from '@components/Search/types';
import Text from '@components/Text';
import EducationalTooltip from '@components/Tooltip/EducationalTooltip';
import useActiveWorkspace from '@hooks/useActiveWorkspace';
import useBottomTabIsFocused from '@hooks/useBottomTabIsFocused';
import useCurrentReportID from '@hooks/useCurrentReportID';
import useLocalize from '@hooks/useLocalize';
import useResponsiveLayout from '@hooks/useResponsiveLayout';
Expand Down Expand Up @@ -42,6 +41,7 @@ type BottomTabName = ValueOf<typeof BOTTOM_TABS>;

type BottomTabBarProps = {
selectedTab: BottomTabName;
shouldShowTooltip: boolean | undefined;
};

/**
Expand Down Expand Up @@ -72,7 +72,7 @@ function handleQueryWithPolicyID(query: SearchQueryString, activePolicyID?: stri
return SearchQueryUtils.buildSearchQueryString(queryJSON);
}

function BottomTabBar({selectedTab}: BottomTabBarProps) {
function BottomTabBar({selectedTab, shouldShowTooltip = false}: BottomTabBarProps) {
const theme = useTheme();
const styles = useThemeStyles();
const {translate} = useLocalize();
Expand All @@ -89,12 +89,12 @@ function BottomTabBar({selectedTab}: BottomTabBarProps) {
const [chatTabBrickRoad, setChatTabBrickRoad] = useState<BrickRoad>(() =>
getChatTabBrickRoad(activeWorkspaceID, currentReportID, reports, betas, policies, priorityMode, transactionViolations),
);
const isFocused = useBottomTabIsFocused();

const platform = getPlatform();
const isWebOrDesktop = platform === CONST.PLATFORM.WEB || platform === CONST.PLATFORM.DESKTOP;
const {renderProductTrainingTooltip, shouldShowProductTrainingTooltip, hideProductTrainingTooltip} = useProductTrainingContext(
CONST.PRODUCT_TRAINING_TOOLTIP_NAMES.BOTTOM_NAV_INBOX_TOOLTIP,
selectedTab !== BOTTOM_TABS.HOME && isFocused,
shouldShowTooltip,
);
useEffect(() => {
setChatTabBrickRoad(getChatTabBrickRoad(activeWorkspaceID, currentReportID, reports, betas, policies, priorityMode, transactionViolations));
Expand Down
75 changes: 75 additions & 0 deletions src/components/Navigation/TopLevelBottomTabBar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import {findFocusedRoute, useNavigationState} from '@react-navigation/native';
import React, {useEffect, useRef, useState} from 'react';
import {InteractionManager, View} from 'react-native';
import useResponsiveLayout from '@hooks/useResponsiveLayout';
import useStyledSafeAreaInsets from '@hooks/useStyledSafeAreaInsets';
import useThemeStyles from '@hooks/useThemeStyles';
import {isFullScreenName, isSplitNavigatorName} from '@libs/Navigation/helpers/isNavigatorName';
import {FULLSCREEN_TO_TAB, SIDEBAR_TO_SPLIT} from '@libs/Navigation/linkingConfig/RELATIONS';
import type {FullScreenName} from '@libs/Navigation/types';
import NAVIGATORS from '@src/NAVIGATORS';
import SCREENS from '@src/SCREENS';
import BottomTabBar, {BOTTOM_TABS} from './BottomTabBar';

const SCREENS_WITH_BOTTOM_TAB_BAR = [...Object.keys(SIDEBAR_TO_SPLIT), SCREENS.SEARCH.ROOT, SCREENS.SETTINGS.WORKSPACES];

/**
* TopLevelBottomTabBar is displayed when the user can interact with the bottom tab bar.
* We hide it when:
* 1. The bottom tab bar is not visible.
* 2. There is transition between screens with and without the bottom tab bar.
* 3. The bottom tab bar is under the overlay.
* For cases 2 and 3, local bottom tab bar mounted on the screen will be displayed.
*/

function TopLevelBottomTabBar() {
const styles = useThemeStyles();
const {shouldUseNarrowLayout} = useResponsiveLayout();
const {paddingBottom} = useStyledSafeAreaInsets();
const [isAfterClosingTransition, setIsAfterClosingTransition] = useState(false);
const cancelAfterInteractions = useRef<ReturnType<typeof InteractionManager.runAfterInteractions> | undefined>();

const selectedTab = useNavigationState((state) => {
const topmostFullScreenRoute = state?.routes.findLast((route) => isFullScreenName(route.name));
return FULLSCREEN_TO_TAB[(topmostFullScreenRoute?.name as FullScreenName) ?? NAVIGATORS.REPORTS_SPLIT_NAVIGATOR];
});

// There always should be a focused screen.
const isScreenWithBottomTabFocused = useNavigationState((state) => {
const focusedRoute = findFocusedRoute(state);

// We are checking if the focused route is a split navigator because there may be a brief moment where the navigator don't have state yet.
// That mens we don't have screen with bottom tab focused. This caused glitching.
return SCREENS_WITH_BOTTOM_TAB_BAR.includes(focusedRoute?.name ?? '') || isSplitNavigatorName(focusedRoute?.name);
});

// Visible directly means not through the overlay.
const isScreenWithBottomTabVisibleDirectly = useNavigationState((state) => isFullScreenName(state.routes.at(-1)?.name));

const shouldDisplayTopLevelBottomTabBar = (shouldUseNarrowLayout ? isScreenWithBottomTabFocused : isScreenWithBottomTabVisibleDirectly) && selectedTab !== BOTTOM_TABS.HOME;

useEffect(() => {
cancelAfterInteractions.current?.cancel();

if (!shouldDisplayTopLevelBottomTabBar) {
// If the bottom tab is not visible, that means there is a screen covering it.
// In that case we need to set the flag to true because there will be a transition for which we need to wait.
setIsAfterClosingTransition(false);
} else {
// If the bottom tab should be visible, we want to wait for transition to finish.
cancelAfterInteractions.current = InteractionManager.runAfterInteractions(() => {
setIsAfterClosingTransition(true);
});
}
}, [shouldDisplayTopLevelBottomTabBar]);

return (
<View style={styles.topLevelBottomTabBar(shouldDisplayTopLevelBottomTabBar && isAfterClosingTransition, shouldUseNarrowLayout, paddingBottom)}>
<BottomTabBar
selectedTab={selectedTab}
shouldShowTooltip={shouldDisplayTopLevelBottomTabBar}
/>
</View>
);
}
export default TopLevelBottomTabBar;

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import {createNavigatorFactory} from '@react-navigation/native';
import type {ParamListBase} from '@react-navigation/native';
import TopLevelBottomTabBar from '@components/Navigation/TopLevelBottomTabBar';
import useNavigationResetOnLayoutChange from '@libs/Navigation/AppNavigator/useNavigationResetOnLayoutChange';
import {isFullScreenName} from '@libs/Navigation/helpers/isNavigatorName';
import createPlatformStackNavigatorComponent from '@libs/Navigation/PlatformStackNavigation/createPlatformStackNavigatorComponent';
import defaultPlatformStackScreenOptions from '@libs/Navigation/PlatformStackNavigation/defaultPlatformStackScreenOptions';
import type {CustomStateHookProps, PlatformStackNavigationEventMap, PlatformStackNavigationOptions, PlatformStackNavigationState} from '@libs/Navigation/PlatformStackNavigation/types';
import RootStackRouter from './RootStackRouter';
import TopLevelBottomTabBar from './TopLevelBottomTabBar';

// This is an optimization to keep mounted only last few screens in the stack.
function useCustomRootStackNavigatorState({state}: CustomStateHookProps) {
Expand Down
9 changes: 7 additions & 2 deletions src/libs/Navigation/helpers/isNavigatorName.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {SIDEBAR_TO_SPLIT, SPLIT_TO_SIDEBAR} from '@libs/Navigation/linkingConfig/RELATIONS';
import type {FullScreenName, OnboardingFlowName, SplitNavigatorSidebarScreen} from '@libs/Navigation/types';
import type {FullScreenName, OnboardingFlowName, SplitNavigatorName, SplitNavigatorSidebarScreen} from '@libs/Navigation/types';
import SCREENS from '@src/SCREENS';

const ONBOARDING_SCREENS = [
Expand All @@ -15,6 +15,7 @@ const ONBOARDING_SCREENS = [
const FULL_SCREENS_SET = new Set([...Object.values(SIDEBAR_TO_SPLIT), SCREENS.SEARCH.ROOT]);
const SIDEBARS_SET = new Set(Object.values(SPLIT_TO_SIDEBAR));
const ONBOARDING_SCREENS_SET = new Set(ONBOARDING_SCREENS);
const SPLIT_NAVIGATORS_SET = new Set(Object.values(SIDEBAR_TO_SPLIT));

/**
* Functions defined below are used to check whether a screen belongs to a specific group.
Expand All @@ -32,6 +33,10 @@ function isOnboardingFlowName(screen: string | undefined) {
return checkIfScreenHasMatchingNameToSetValues<OnboardingFlowName>(screen, ONBOARDING_SCREENS_SET);
}

function isSplitNavigatorName(screen: string | undefined) {
return checkIfScreenHasMatchingNameToSetValues<SplitNavigatorName>(screen, SPLIT_NAVIGATORS_SET);
}

function isFullScreenName(screen: string | undefined) {
return checkIfScreenHasMatchingNameToSetValues<FullScreenName>(screen, FULL_SCREENS_SET);
}
Expand All @@ -40,4 +45,4 @@ function isSidebarScreenName(screen: string | undefined) {
return checkIfScreenHasMatchingNameToSetValues<SplitNavigatorSidebarScreen>(screen, SIDEBARS_SET);
}

export {isFullScreenName, isOnboardingFlowName, isSidebarScreenName};
export {isFullScreenName, isOnboardingFlowName, isSidebarScreenName, isSplitNavigatorName};
8 changes: 6 additions & 2 deletions src/styles/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -562,11 +562,15 @@ const styles = (theme: ThemeColors) =>
borderRadius: variables.componentBorderRadiusLarge,
},

topLevelBottomTabBar: (shouldDisplayTopLevelBottomTabBar: boolean, bottomSafeAreaOffset: number) => ({
topLevelBottomTabBar: (shouldDisplayTopLevelBottomTabBar: boolean, shouldUseNarrowLayout: boolean, bottomSafeAreaOffset: number) => ({
position: 'absolute',
width: '100%',
width: shouldUseNarrowLayout ? '100%' : variables.sideBarWidth,
transform: [{translateX: shouldUseNarrowLayout ? 0 : -variables.sideBarWidth}],
paddingBottom: bottomSafeAreaOffset,
bottom: shouldDisplayTopLevelBottomTabBar ? 0 : -(bottomSafeAreaOffset + variables.bottomTabHeight),
borderRightWidth: shouldUseNarrowLayout ? 0 : 1,
borderColor: theme.border,
backgroundColor: 'red',
}),

bottomTabBarContainer: {
Expand Down

0 comments on commit 667a052

Please sign in to comment.