diff --git a/src/components/BlockingViews/BlockingView.tsx b/src/components/BlockingViews/BlockingView.tsx
index ee800c400a93..feeb64856a8c 100644
--- a/src/components/BlockingViews/BlockingView.tsx
+++ b/src/components/BlockingViews/BlockingView.tsx
@@ -109,8 +109,8 @@ function BlockingView({
CustomSubtitle,
contentFitImage,
containerStyle: containerStyleProp,
- addBottomSafeAreaPadding = false,
- addOfflineIndicatorBottomSafeAreaPadding = addBottomSafeAreaPadding,
+ addBottomSafeAreaPadding,
+ addOfflineIndicatorBottomSafeAreaPadding,
testID,
}: BlockingViewProps) {
const styles = useThemeStyles();
diff --git a/src/components/CategorySelector/CategorySelectorModal.tsx b/src/components/CategorySelector/CategorySelectorModal.tsx
index 4bcfb9e1f9b6..6f2637eeb8e9 100644
--- a/src/components/CategorySelector/CategorySelectorModal.tsx
+++ b/src/components/CategorySelector/CategorySelectorModal.tsx
@@ -56,7 +56,6 @@ function CategorySelectorModal({policyID, isVisible, currentCategory, onCategory
policyID={policyID}
selectedCategory={currentCategory}
onSubmit={onCategorySelected}
- contentContainerStyle={styles.pb5}
addBottomSafeAreaPadding
/>
diff --git a/src/components/FixedFooter.tsx b/src/components/FixedFooter.tsx
index 2a17997324f3..c5910647c705 100644
--- a/src/components/FixedFooter.tsx
+++ b/src/components/FixedFooter.tsx
@@ -22,13 +22,7 @@ type FixedFooterProps = {
shouldStickToBottom?: boolean;
};
-function FixedFooter({
- style,
- children,
- addBottomSafeAreaPadding = false,
- addOfflineIndicatorBottomSafeAreaPadding = addBottomSafeAreaPadding,
- shouldStickToBottom = false,
-}: FixedFooterProps) {
+function FixedFooter({style, children, addBottomSafeAreaPadding, addOfflineIndicatorBottomSafeAreaPadding, shouldStickToBottom = false}: FixedFooterProps) {
const styles = useThemeStyles();
const bottomSafeAreaPaddingStyle = useBottomSafeSafeAreaPaddingStyle({
diff --git a/src/components/Form/FormWrapper.tsx b/src/components/Form/FormWrapper.tsx
index 3120c5a3fffb..c2730c1e5ea7 100644
--- a/src/components/Form/FormWrapper.tsx
+++ b/src/components/Form/FormWrapper.tsx
@@ -83,7 +83,7 @@ function FormWrapper({
isLoading = false,
shouldScrollToEnd = false,
addBottomSafeAreaPadding,
- addOfflineIndicatorBottomSafeAreaPadding: addOfflineIndicatorBottomSafeAreaPaddingProp,
+ addOfflineIndicatorBottomSafeAreaPadding,
shouldSubmitButtonStickToBottom: shouldSubmitButtonStickToBottomProp,
shouldSubmitButtonBlendOpacity = false,
}: FormWrapperProps) {
@@ -137,13 +137,13 @@ function FormWrapper({
// If the paddingBottom is 0, it has already been applied to a parent component and we don't want to apply the padding again.
const isLegacyBottomSafeAreaPaddingAlreadyApplied = paddingBottom === 0;
const shouldApplyBottomSafeAreaPadding = addBottomSafeAreaPadding ?? !isLegacyBottomSafeAreaPaddingAlreadyApplied;
- const addOfflineIndicatorBottomSafeAreaPadding = addOfflineIndicatorBottomSafeAreaPaddingProp ?? addBottomSafeAreaPadding === true;
// We need to add bottom safe area padding to the submit button when we don't use a scroll view or
// when the submit button is sticking to the bottom.
const addSubmitButtonBottomSafeAreaPadding = addBottomSafeAreaPadding && (!shouldUseScrollView || shouldSubmitButtonStickToBottom);
const submitButtonStylesWithBottomSafeAreaPadding = useBottomSafeSafeAreaPaddingStyle({
addBottomSafeAreaPadding: addSubmitButtonBottomSafeAreaPadding,
+ addOfflineIndicatorBottomSafeAreaPadding,
styleProperty: shouldSubmitButtonStickToBottom ? 'bottom' : 'paddingBottom',
additionalPaddingBottom: shouldSubmitButtonStickToBottom ? styles.pb5.paddingBottom : 0,
style: submitButtonStyles,
diff --git a/src/components/Modal/BaseModal.tsx b/src/components/Modal/BaseModal.tsx
index fd44f593f189..b65040864272 100644
--- a/src/components/Modal/BaseModal.tsx
+++ b/src/components/Modal/BaseModal.tsx
@@ -1,4 +1,4 @@
-import React, {forwardRef, useCallback, useEffect, useMemo, useRef} from 'react';
+import React, {forwardRef, useCallback, useContext, useEffect, useMemo, useRef} from 'react';
import {View} from 'react-native';
import type {ModalProps as ReactNativeModalProps} from 'react-native-modal';
import ReactNativeModal from 'react-native-modal';
@@ -6,6 +6,7 @@ import type {ValueOf} from 'type-fest';
import ColorSchemeWrapper from '@components/ColorSchemeWrapper';
import FocusTrapForModal from '@components/FocusTrap/FocusTrapForModal';
import NavigationBar from '@components/NavigationBar';
+import ScreenWrapperOfflineIndicatorContext from '@components/ScreenWrapper/ScreenWrapperOfflineIndicatorContext';
import useKeyboardState from '@hooks/useKeyboardState';
import usePrevious from '@hooks/usePrevious';
import useResponsiveLayout from '@hooks/useResponsiveLayout';
@@ -16,6 +17,7 @@ import useTheme from '@hooks/useTheme';
import useThemeStyles from '@hooks/useThemeStyles';
import useWindowDimensions from '@hooks/useWindowDimensions';
import ComposerFocusManager from '@libs/ComposerFocusManager';
+import NarrowPaneContext from '@libs/Navigation/AppNavigator/Navigators/NarrowPaneContext';
import Overlay from '@libs/Navigation/AppNavigator/Navigators/Overlay';
import Navigation from '@libs/Navigation/Navigation';
import variables from '@styles/variables';
@@ -249,76 +251,84 @@ function BaseModal(
[isVisible, type],
);
+ // In Modals we need to reset the ScreenWrapperOfflineIndicatorContext to allow nested ScreenWrapper components to render offline indicators,
+ // except if we are in a narrow pane navigator. In this case, we use the narrow pane's original values.
+ const {isInNarrowPane} = useContext(NarrowPaneContext);
+ const {originalValues} = useContext(ScreenWrapperOfflineIndicatorContext);
+ const offlineIndicatorContextValue = useMemo(() => (isInNarrowPane ? originalValues ?? {} : {}), [isInNarrowPane, originalValues]);
+
return (
-
- e.stopPropagation()}
- onBackdropPress={handleBackdropPress}
- // Note: Escape key on web/desktop will trigger onBackButtonPress callback
- // eslint-disable-next-line react/jsx-props-no-multi-spaces
- onBackButtonPress={closeTop}
- onModalShow={handleShowModal}
- propagateSwipe={propagateSwipe}
- onModalHide={hideModal}
- onModalWillShow={saveFocusState}
- onDismiss={handleDismissModal}
- onSwipeComplete={() => onClose?.()}
- swipeDirection={swipeDirection}
- swipeThreshold={swipeThreshold}
- isVisible={isVisible}
- backdropColor={theme.overlay}
- backdropOpacity={!shouldUseCustomBackdrop && hideBackdrop ? 0 : variables.overlayOpacity}
- backdropTransitionOutTiming={0}
- hasBackdrop={fullscreen}
- coverScreen={fullscreen}
- style={[modalStyle, sidePanelStyle]}
- deviceHeight={windowHeight}
- deviceWidth={windowWidth}
- animationIn={animationIn ?? modalStyleAnimationIn}
- animationInDelay={animationInDelay}
- animationOut={animationOut ?? modalStyleAnimationOut}
- useNativeDriver={useNativeDriver}
- useNativeDriverForBackdrop={useNativeDriverForBackdrop}
- hideModalContentWhileAnimating={hideModalContentWhileAnimating}
- animationInTiming={animationInTiming}
- animationOutTiming={animationOutTiming}
- statusBarTranslucent={statusBarTranslucent}
- navigationBarTranslucent={navigationBarTranslucent}
- onLayout={onLayout}
- avoidKeyboard={avoidKeyboard}
- customBackdrop={shouldUseCustomBackdrop ? : undefined}
- type={type}
- shouldUseNewModal={shouldUseNewModal}
+
+
- e.stopPropagation()}
+ onBackdropPress={handleBackdropPress}
+ // Note: Escape key on web/desktop will trigger onBackButtonPress callback
+ // eslint-disable-next-line react/jsx-props-no-multi-spaces
+ onBackButtonPress={closeTop}
+ onModalShow={handleShowModal}
+ propagateSwipe={propagateSwipe}
+ onModalHide={hideModal}
onModalWillShow={saveFocusState}
onDismiss={handleDismissModal}
+ onSwipeComplete={() => onClose?.()}
+ swipeDirection={swipeDirection}
+ swipeThreshold={swipeThreshold}
+ isVisible={isVisible}
+ backdropColor={theme.overlay}
+ backdropOpacity={!shouldUseCustomBackdrop && hideBackdrop ? 0 : variables.overlayOpacity}
+ backdropTransitionOutTiming={0}
+ hasBackdrop={fullscreen}
+ coverScreen={fullscreen}
+ style={[modalStyle, sidePanelStyle]}
+ deviceHeight={windowHeight}
+ deviceWidth={windowWidth}
+ animationIn={animationIn ?? modalStyleAnimationIn}
+ animationInDelay={animationInDelay}
+ animationOut={animationOut ?? modalStyleAnimationOut}
+ useNativeDriver={useNativeDriver}
+ useNativeDriverForBackdrop={useNativeDriverForBackdrop}
+ hideModalContentWhileAnimating={hideModalContentWhileAnimating}
+ animationInTiming={animationInTiming}
+ animationOutTiming={animationOutTiming}
+ statusBarTranslucent={statusBarTranslucent}
+ navigationBarTranslucent={navigationBarTranslucent}
+ onLayout={onLayout}
+ avoidKeyboard={avoidKeyboard}
+ customBackdrop={shouldUseCustomBackdrop ? : undefined}
+ type={type}
+ shouldUseNewModal={shouldUseNewModal}
>
-
-
- {children}
-
-
-
- {!keyboardStateContextValue?.isKeyboardActive && }
-
-
+
+ {children}
+
+
+
+ {!keyboardStateContextValue?.isKeyboardActive && }
+
+
+
);
}
diff --git a/src/components/OfflineIndicator.tsx b/src/components/OfflineIndicator.tsx
index db5250ee8234..ea9f3aff1fac 100644
--- a/src/components/OfflineIndicator.tsx
+++ b/src/components/OfflineIndicator.tsx
@@ -31,6 +31,7 @@ function OfflineIndicator({style, containerStyles: containerStylesProp, addBotto
const fallbackStyle = useMemo(() => [styles.offlineIndicatorContainer, containerStylesProp], [styles.offlineIndicatorContainer, containerStylesProp]);
const containerStyles = useBottomSafeSafeAreaPaddingStyle({
addBottomSafeAreaPadding,
+ addOfflineIndicatorBottomSafeAreaPadding: false,
style: fallbackStyle,
});
diff --git a/src/components/ScreenWrapper/ScreenWrapperOfflineIndicatorContext.ts b/src/components/ScreenWrapper/ScreenWrapperOfflineIndicatorContext.ts
new file mode 100644
index 000000000000..15cdfa5e9e49
--- /dev/null
+++ b/src/components/ScreenWrapper/ScreenWrapperOfflineIndicatorContext.ts
@@ -0,0 +1,19 @@
+import {createContext} from 'react';
+
+type ScreenWrapperOfflineIndicatorBaseContext = {
+ showOnSmallScreens?: boolean;
+ showOnWideScreens?: boolean;
+ addSafeAreaPadding?: boolean;
+};
+
+type ScreenWrapperOfflineIndicatorContextType = {
+ showOnSmallScreens?: boolean;
+ showOnWideScreens?: boolean;
+ addSafeAreaPadding?: boolean;
+ originalValues?: ScreenWrapperOfflineIndicatorBaseContext;
+};
+
+const ScreenWrapperOfflineIndicatorContext = createContext({});
+
+export default ScreenWrapperOfflineIndicatorContext;
+export type {ScreenWrapperOfflineIndicatorContextType};
diff --git a/src/components/ScreenWrapper.tsx b/src/components/ScreenWrapper/index.tsx
similarity index 72%
rename from src/components/ScreenWrapper.tsx
rename to src/components/ScreenWrapper/index.tsx
index 03b3489048f8..a2ec206b2e1f 100644
--- a/src/components/ScreenWrapper.tsx
+++ b/src/components/ScreenWrapper/index.tsx
@@ -7,6 +7,18 @@ import {Keyboard, PanResponder, View} from 'react-native';
import {useOnyx} from 'react-native-onyx';
import {PickerAvoidingView} from 'react-native-picker-select';
import type {EdgeInsets} from 'react-native-safe-area-context';
+import CustomDevMenu from '@components/CustomDevMenu';
+import CustomStatusBarAndBackgroundContext from '@components/CustomStatusBarAndBackground/CustomStatusBarAndBackgroundContext';
+import FocusTrapForScreens from '@components/FocusTrap/FocusTrapForScreen';
+import type FocusTrapForScreenProps from '@components/FocusTrap/FocusTrapForScreen/FocusTrapProps';
+import HeaderGap from '@components/HeaderGap';
+import ImportedStateIndicator from '@components/ImportedStateIndicator';
+import {InitialURLContext} from '@components/InitialURLContextProvider';
+import {useInputBlurContext} from '@components/InputBlurContext';
+import KeyboardAvoidingView from '@components/KeyboardAvoidingView';
+import ModalContext from '@components/Modal/ModalContext';
+import OfflineIndicator from '@components/OfflineIndicator';
+import withNavigationFallback from '@components/withNavigationFallback';
import useBottomSafeSafeAreaPaddingStyle from '@hooks/useBottomSafeSafeAreaPaddingStyle';
import useEnvironment from '@hooks/useEnvironment';
import useInitialDimensions from '@hooks/useInitialWindowDimensions';
@@ -18,6 +30,7 @@ import useTackInputFocus from '@hooks/useTackInputFocus';
import useThemeStyles from '@hooks/useThemeStyles';
import useWindowDimensions from '@hooks/useWindowDimensions';
import {isMobile, isMobileWebKit, isSafari} from '@libs/Browser';
+import NarrowPaneContext from '@libs/Navigation/AppNavigator/Navigators/NarrowPaneContext';
import Navigation from '@libs/Navigation/Navigation';
import type {PlatformStackNavigationProp} from '@libs/Navigation/PlatformStackNavigation/types';
import type {ReportsSplitNavigatorParamList, RootNavigatorParamList} from '@libs/Navigation/types';
@@ -26,18 +39,7 @@ import toggleTestToolsModal from '@userActions/TestTool';
import CONFIG from '@src/CONFIG';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
-import CustomDevMenu from './CustomDevMenu';
-import CustomStatusBarAndBackgroundContext from './CustomStatusBarAndBackground/CustomStatusBarAndBackgroundContext';
-import FocusTrapForScreens from './FocusTrap/FocusTrapForScreen';
-import type FocusTrapForScreenProps from './FocusTrap/FocusTrapForScreen/FocusTrapProps';
-import HeaderGap from './HeaderGap';
-import ImportedStateIndicator from './ImportedStateIndicator';
-import {InitialURLContext} from './InitialURLContextProvider';
-import {useInputBlurContext} from './InputBlurContext';
-import KeyboardAvoidingView from './KeyboardAvoidingView';
-import ModalContext from './Modal/ModalContext';
-import OfflineIndicator from './OfflineIndicator';
-import withNavigationFallback from './withNavigationFallback';
+import ScreenWrapperOfflineIndicatorContext from './ScreenWrapperOfflineIndicatorContext';
type ScreenWrapperChildrenProps = {
insets: EdgeInsets;
@@ -98,9 +100,15 @@ type ScreenWrapperProps = {
/** Whether to use the minHeight. Use true for screens where the window height are changing because of Virtual Keyboard */
shouldEnableMinHeight?: boolean;
- /** Whether to show offline indicator */
+ /** Whether to disable the safe area padding for (nested) offline indicators */
+ disableOfflineIndicatorSafeAreaPadding?: boolean;
+
+ /** Whether to show offline indicator on small screens */
shouldShowOfflineIndicator?: boolean;
+ /** Whether to show offline indicator on wide screens */
+ shouldShowOfflineIndicatorInWideScreen?: boolean;
+
/** Whether to avoid scroll on virtual viewport */
shouldAvoidScrollOnVirtualViewport?: boolean;
@@ -115,9 +123,6 @@ type ScreenWrapperProps = {
*/
navigation?: PlatformStackNavigationProp | PlatformStackNavigationProp;
- /** Whether to show offline indicator on wide screens */
- shouldShowOfflineIndicatorInWideScreen?: boolean;
-
/** Overrides the focus trap default settings */
focusTrapSettings?: FocusTrapForScreenProps['focusTrapSettings'];
@@ -161,7 +166,9 @@ function ScreenWrapper(
shouldEnablePickerAvoiding = true,
headerGapStyles,
children,
- shouldShowOfflineIndicator = true,
+ disableOfflineIndicatorSafeAreaPadding,
+ shouldShowOfflineIndicatorInWideScreen,
+ shouldShowOfflineIndicator,
offlineIndicatorStyle,
style,
shouldDismissKeyboardBeforeClose = true,
@@ -169,7 +176,6 @@ function ScreenWrapper(
testID,
navigation: navigationProp,
shouldAvoidScrollOnVirtualViewport = true,
- shouldShowOfflineIndicatorInWideScreen = false,
shouldUseCachedViewportHeight = false,
focusTrapSettings,
bottomContent,
@@ -333,7 +339,7 @@ function ScreenWrapper(
}, [isUsingEdgeToEdgeMode, ignoreInsetsConsumption, includePaddingTop, paddingTop, unmodifiedPaddings.top]);
const showBottomContent = isUsingEdgeToEdgeMode ? !!bottomContent : true;
- const edgeToEdgeBottomContentStyle = useBottomSafeSafeAreaPaddingStyle({addBottomSafeAreaPadding: true});
+ const edgeToEdgeBottomContentStyle = useBottomSafeSafeAreaPaddingStyle({addBottomSafeAreaPadding: true, addOfflineIndicatorBottomSafeAreaPadding: false});
const legacyBottomContentStyle: StyleProp = useMemo(() => {
const shouldUseUnmodifiedPaddings = includeSafeAreaPaddingBottom && ignoreInsetsConsumption;
if (shouldUseUnmodifiedPaddings) {
@@ -360,7 +366,7 @@ function ScreenWrapper(
* By default, the background color of the mobile offline indicator is opaque.
* If `isOfflineIndicatorTranslucent` is set to true, a translucent background color is applied.
*/
- const mobileOfflineIndicatorBackgroundStyle = useMemo(() => {
+ const smallScreenOfflineIndicatorBackgroundStyle = useMemo(() => {
const showOfflineIndicatorBackground = !bottomContent && isOffline;
if (!showOfflineIndicatorBackground) {
return undefined;
@@ -369,7 +375,7 @@ function ScreenWrapper(
}, [bottomContent, isOffline, isOfflineIndicatorTranslucent, styles.appBG, styles.translucentNavigationBarBG]);
/** In edge-to-edge mode, we always want to apply the bottom safe area padding to the mobile offline indicator. */
- const hasMobileOfflineIndicatorBottomSafeAreaPadding = isUsingEdgeToEdgeMode ? enableEdgeToEdgeBottomSafeAreaPadding : !includeSafeAreaPaddingBottom;
+ const hasSmallScreenOfflineIndicatorBottomSafeAreaPadding = isUsingEdgeToEdgeMode ? enableEdgeToEdgeBottomSafeAreaPadding : !includeSafeAreaPaddingBottom;
/**
* This style includes the bottom safe area padding for the mobile offline indicator.
@@ -379,42 +385,73 @@ function ScreenWrapper(
* two overlapping layers of translucent background.
* If the device does not have soft keys, the bottom safe area padding is applied as `paddingBottom`.
*/
- const mobileOfflineIndicatorBottomSafeAreaStyle = useBottomSafeSafeAreaPaddingStyle({
- addBottomSafeAreaPadding: hasMobileOfflineIndicatorBottomSafeAreaPadding,
+ const smallScreenOfflineIndicatorBottomSafeAreaStyle = useBottomSafeSafeAreaPaddingStyle({
+ addBottomSafeAreaPadding: hasSmallScreenOfflineIndicatorBottomSafeAreaPadding,
+ addOfflineIndicatorBottomSafeAreaPadding: false,
styleProperty: isSoftKeyNavigation ? 'bottom' : 'paddingBottom',
});
/** If there is no bottom content, the mobile offline indicator will stick to the bottom of the screen by default. */
- const displayStickyMobileOfflineIndicator = shouldMobileOfflineIndicatorStickToBottom && !bottomContent;
+ const displayStickySmallScreenOfflineIndicator = shouldMobileOfflineIndicatorStickToBottom && !bottomContent;
/**
- * This style includes all styles applied to the container of the mobile offline indicator.
+ * This style includes all styles applied to the container of the offline indicator on small screens.
* It always applies the bottom safe area padding as well as the background style, if the device has soft keys.
* In this case, we want the whole container (including the bottom safe area padding) to have translucent/opaque background.
*/
- const mobileOfflineIndicatorContainerStyle = useMemo(
- () => [mobileOfflineIndicatorBottomSafeAreaStyle, displayStickyMobileOfflineIndicator && styles.stickToBottom, !isSoftKeyNavigation && mobileOfflineIndicatorBackgroundStyle],
- [mobileOfflineIndicatorBottomSafeAreaStyle, displayStickyMobileOfflineIndicator, styles.stickToBottom, isSoftKeyNavigation, mobileOfflineIndicatorBackgroundStyle],
+ const smallScreenOfflineIndicatorContainerStyle = useMemo(
+ () => [
+ smallScreenOfflineIndicatorBottomSafeAreaStyle,
+ displayStickySmallScreenOfflineIndicator && styles.stickToBottom,
+ !isSoftKeyNavigation && smallScreenOfflineIndicatorBackgroundStyle,
+ ],
+ [smallScreenOfflineIndicatorBottomSafeAreaStyle, displayStickySmallScreenOfflineIndicator, styles.stickToBottom, isSoftKeyNavigation, smallScreenOfflineIndicatorBackgroundStyle],
);
/**
- * This style includes the styles applied to the mobile offline indicator component.
- * If the device has soft keys, we only want to apply the background style to the mobile offline indicator component,
+ * This style includes the styles applied to the offline indicator component on small screens.
+ * If the device has soft keys, we only want to apply the background style to the offline indicator component,
* rather than the whole container, because otherwise the navigation bar would be extra opaque, since it already has a translucent background.
*/
- const mobileOfflineIndicatorStyle = useMemo(
- () => [styles.pl5, isSoftKeyNavigation && mobileOfflineIndicatorBackgroundStyle, offlineIndicatorStyle],
- [isSoftKeyNavigation, mobileOfflineIndicatorBackgroundStyle, offlineIndicatorStyle, styles.pl5],
+ const smallScreenOfflineIndicatorStyle = useMemo(
+ () => [styles.pl5, isSoftKeyNavigation && smallScreenOfflineIndicatorBackgroundStyle, offlineIndicatorStyle],
+ [isSoftKeyNavigation, smallScreenOfflineIndicatorBackgroundStyle, offlineIndicatorStyle, styles.pl5],
);
- const displayMobileOfflineIndicator = isSmallScreenWidth && shouldShowOfflineIndicator;
- const displayWidescreenOfflineIndicator = !shouldUseNarrowLayout && shouldShowOfflineIndicatorInWideScreen;
+ // This context allows us to disable the safe area padding offseting the offline indicator in scrollable components like 'ScrollView', 'SelectionList' or 'FormProvider'.
+ // This is useful e.g. for the RightModalNavigator, where we want to avoid the safe area padding offseting the offline indicator because we only show the offline indicator on small screens.
+ const {isInNarrowPane} = useContext(NarrowPaneContext);
+ const {addSafeAreaPadding, showOnSmallScreens, showOnWideScreens, originalValues} = useContext(ScreenWrapperOfflineIndicatorContext);
+ const offlineIndicatorContextValue = useMemo(() => {
+ const newAddSafeAreaPadding = isInNarrowPane ? isSmallScreenWidth : addSafeAreaPadding;
+
+ const newOriginalValues = originalValues ?? {
+ addSafeAreaPadding: newAddSafeAreaPadding,
+ showOnSmallScreens,
+ showOnWideScreens,
+ };
+
+ return {
+ // Allows for individual screens to disable the offline indicator safe area padding for the screen and all nested ScreenWrapper components.
+ addSafeAreaPadding: disableOfflineIndicatorSafeAreaPadding === undefined ? newAddSafeAreaPadding ?? true : !disableOfflineIndicatorSafeAreaPadding,
+ // Prevent any nested ScreenWrapper components from rendering another offline indicator.
+ showOnSmallScreens: false,
+ showOnWideScreens: false,
+ // Pass down the original values by the outermost ScreenWrapperOfflineIndicatorContext.Provider,
+ // to allow nested ScreenWrapperOfflineIndicatorContext.Provider to access these values. (e.g. in Modals)
+ originalValues: newOriginalValues,
+ };
+ }, [addSafeAreaPadding, disableOfflineIndicatorSafeAreaPadding, isInNarrowPane, isSmallScreenWidth, originalValues, showOnSmallScreens, showOnWideScreens]);
+
+ const displaySmallScreenOfflineIndicator = isSmallScreenWidth && (shouldShowOfflineIndicator ?? showOnSmallScreens ?? true);
+ const displayWidescreenOfflineIndicator = !shouldUseNarrowLayout && (shouldShowOfflineIndicatorInWideScreen ?? showOnWideScreens ?? false);
/** If we currently show the offline indicator and it has bottom safe area padding, we need to offset the bottom safe area padding in the KeyboardAvoidingView. */
- const shouldOffsetMobileOfflineIndicator = displayMobileOfflineIndicator && hasMobileOfflineIndicatorBottomSafeAreaPadding && isOffline;
+ const shouldOffsetMobileOfflineIndicator = displaySmallScreenOfflineIndicator && hasSmallScreenOfflineIndicatorBottomSafeAreaPadding && isOffline;
const isAvoidingViewportScroll = useTackInputFocus(isFocused && shouldEnableMaxHeight && shouldAvoidScrollOnVirtualViewport && isMobileWebKit());
- const contextValue = useMemo(
+
+ const statusContextValue = useMemo(
() => ({didScreenTransitionEnd, isSafeAreaTopPaddingApplied, isSafeAreaBottomPaddingApplied: includeSafeAreaPaddingBottom}),
[didScreenTransitionEnd, includeSafeAreaPaddingBottom, isSafeAreaTopPaddingApplied],
);
@@ -449,38 +486,40 @@ function ScreenWrapper(
>
{isDevelopment && }
-
- {
- // If props.children is a function, call it to provide the insets to the children.
- typeof children === 'function'
- ? children({
- insets,
- safeAreaPaddingBottomStyle,
- didScreenTransitionEnd,
- })
- : children
- }
- {displayMobileOfflineIndicator && (
- <>
- {isOffline && (
-
-
- {/* Since import state is tightly coupled to the offline state, it is safe to display it when showing offline indicator */}
-
- )}
-
- >
- )}
- {displayWidescreenOfflineIndicator && (
- <>
-
- {/* Since import state is tightly coupled to the offline state, it is safe to display it when showing offline indicator */}
-
- >
- )}
+
+
+ {
+ // If props.children is a function, call it to provide the insets to the children.
+ typeof children === 'function'
+ ? children({
+ insets,
+ safeAreaPaddingBottomStyle,
+ didScreenTransitionEnd,
+ })
+ : children
+ }
+ {displaySmallScreenOfflineIndicator && (
+ <>
+ {isOffline && (
+
+
+ {/* Since import state is tightly coupled to the offline state, it is safe to display it when showing offline indicator */}
+
+ )}
+
+ >
+ )}
+ {displayWidescreenOfflineIndicator && (
+ <>
+
+ {/* Since import state is tightly coupled to the offline state, it is safe to display it when showing offline indicator */}
+
+ >
+ )}
+
diff --git a/src/components/ScrollView.tsx b/src/components/ScrollView.tsx
index 660f43114ca6..16fd2dd167ea 100644
--- a/src/components/ScrollView.tsx
+++ b/src/components/ScrollView.tsx
@@ -14,14 +14,7 @@ type ScrollViewProps = RNScrollViewProps & {
};
function ScrollView(
- {
- children,
- scrollIndicatorInsets,
- contentContainerStyle: contentContainerStyleProp,
- addBottomSafeAreaPadding = false,
- addOfflineIndicatorBottomSafeAreaPadding = addBottomSafeAreaPadding,
- ...props
- }: ScrollViewProps,
+ {children, scrollIndicatorInsets, contentContainerStyle: contentContainerStyleProp, addBottomSafeAreaPadding, addOfflineIndicatorBottomSafeAreaPadding, ...props}: ScrollViewProps,
ref: ForwardedRef,
) {
const contentContainerStyle = useBottomSafeSafeAreaPaddingStyle({
diff --git a/src/components/SectionList/BaseSectionList.tsx b/src/components/SectionList/BaseSectionList.tsx
index 18a915d1a58b..eb39de8bd541 100644
--- a/src/components/SectionList/BaseSectionList.tsx
+++ b/src/components/SectionList/BaseSectionList.tsx
@@ -4,12 +4,7 @@ import AnimatedSectionList from './AnimatedSectionList';
import type {SectionListProps, SectionListRef} from './types';
function BaseSectionList(
- {
- addBottomSafeAreaPadding = false,
- addOfflineIndicatorBottomSafeAreaPadding = addBottomSafeAreaPadding,
- contentContainerStyle: contentContainerStyleProp,
- ...restProps
- }: SectionListProps,
+ {addBottomSafeAreaPadding, addOfflineIndicatorBottomSafeAreaPadding, contentContainerStyle: contentContainerStyleProp, ...restProps}: SectionListProps,
ref: SectionListRef,
) {
const contentContainerStyle = useBottomSafeSafeAreaPaddingStyle({addBottomSafeAreaPadding, addOfflineIndicatorBottomSafeAreaPadding, style: contentContainerStyleProp});
diff --git a/src/components/SelectionList/BaseSelectionList.tsx b/src/components/SelectionList/BaseSelectionList.tsx
index c516762fc044..60e22bfc6022 100644
--- a/src/components/SelectionList/BaseSelectionList.tsx
+++ b/src/components/SelectionList/BaseSelectionList.tsx
@@ -135,8 +135,8 @@ function BaseSelectionList(
listItemTitleContainerStyles,
isScreenFocused = false,
shouldSubscribeToArrowKeyEvents = true,
- addBottomSafeAreaPadding = false,
- addOfflineIndicatorBottomSafeAreaPadding = addBottomSafeAreaPadding,
+ addBottomSafeAreaPadding,
+ addOfflineIndicatorBottomSafeAreaPadding,
fixedNumItemsForLoader,
loaderSpeed,
errorText,
diff --git a/src/components/ValuePicker/ValueSelectionList.tsx b/src/components/ValuePicker/ValueSelectionList.tsx
index 9ba6ea564baa..cad4dda3e36b 100644
--- a/src/components/ValuePicker/ValueSelectionList.tsx
+++ b/src/components/ValuePicker/ValueSelectionList.tsx
@@ -18,6 +18,7 @@ function ValueSelectionList({items = [], selectedItem, onItemSelected, shouldSho
shouldShowTooltips={shouldShowTooltips}
shouldUpdateFocusedIndex
ListItem={RadioListItem}
+ addBottomSafeAreaPadding
/>
);
}
diff --git a/src/components/ValuePicker/ValueSelectorModal.tsx b/src/components/ValuePicker/ValueSelectorModal.tsx
index fdbb8b322aef..9e08ce7e4b34 100644
--- a/src/components/ValuePicker/ValueSelectorModal.tsx
+++ b/src/components/ValuePicker/ValueSelectorModal.tsx
@@ -2,7 +2,6 @@ import React from 'react';
import HeaderWithBackButton from '@components/HeaderWithBackButton';
import Modal from '@components/Modal';
import ScreenWrapper from '@components/ScreenWrapper';
-import useThemeStyles from '@hooks/useThemeStyles';
import CONST from '@src/CONST';
import type {ValueSelectorModalProps} from './types';
import ValueSelectionList from './ValueSelectionList';
@@ -18,8 +17,6 @@ function ValueSelectorModal({
onBackdropPress,
shouldEnableKeyboardAvoidingView = true,
}: ValueSelectorModalProps) {
- const styles = useThemeStyles();
-
return (
diff --git a/src/hooks/useBottomSafeSafeAreaPaddingStyle.ts b/src/hooks/useBottomSafeSafeAreaPaddingStyle.ts
index e680af8a73bd..0b2912ab5470 100644
--- a/src/hooks/useBottomSafeSafeAreaPaddingStyle.ts
+++ b/src/hooks/useBottomSafeSafeAreaPaddingStyle.ts
@@ -1,6 +1,7 @@
-import {useMemo} from 'react';
+import {useContext, useMemo} from 'react';
import {StyleSheet} from 'react-native';
import type {StyleProp, ViewStyle} from 'react-native';
+import ScreenWrapperOfflineIndicatorContext from '@components/ScreenWrapper/ScreenWrapperOfflineIndicatorContext';
import CONST from '@src/CONST';
import useNetwork from './useNetwork';
import useSafeAreaPaddings from './useSafeAreaPaddings';
@@ -29,11 +30,16 @@ type UseBottomSafeAreaPaddingStyleParams = {
* @param params - The parameters for the hook.
* @returns The style with bottom safe area padding applied.
*/
-function useBottomSafeSafeAreaPaddingStyle(params?: UseBottomSafeAreaPaddingStyleParams) {
+function useBottomSafeSafeAreaPaddingStyle({
+ addBottomSafeAreaPadding = false,
+ addOfflineIndicatorBottomSafeAreaPadding = addBottomSafeAreaPadding,
+ style,
+ styleProperty = 'paddingBottom',
+ additionalPaddingBottom = 0,
+}: UseBottomSafeAreaPaddingStyleParams = {}) {
const {paddingBottom: safeAreaPaddingBottom} = useSafeAreaPaddings(true);
const {isOffline} = useNetwork();
-
- const {addBottomSafeAreaPadding, addOfflineIndicatorBottomSafeAreaPadding, style, styleProperty = 'paddingBottom', additionalPaddingBottom = 0} = params ?? {};
+ const {addSafeAreaPadding: isOfflineIndicatorSafeAreaPaddingEnabled} = useContext(ScreenWrapperOfflineIndicatorContext);
return useMemo>(() => {
let totalPaddingBottom: number | string = additionalPaddingBottom;
@@ -43,7 +49,7 @@ function useBottomSafeSafeAreaPaddingStyle(params?: UseBottomSafeAreaPaddingStyl
totalPaddingBottom += safeAreaPaddingBottom;
}
- if (addOfflineIndicatorBottomSafeAreaPadding && isOffline) {
+ if (addOfflineIndicatorBottomSafeAreaPadding && isOffline && isOfflineIndicatorSafeAreaPaddingEnabled) {
totalPaddingBottom += CONST.OFFLINE_INDICATOR_HEIGHT;
}
@@ -71,7 +77,16 @@ function useBottomSafeSafeAreaPaddingStyle(params?: UseBottomSafeAreaPaddingStyl
// If no style is provided, return the padding as an object
return {paddingBottom: totalPaddingBottom};
- }, [additionalPaddingBottom, addBottomSafeAreaPadding, addOfflineIndicatorBottomSafeAreaPadding, isOffline, style, safeAreaPaddingBottom, styleProperty]);
+ }, [
+ additionalPaddingBottom,
+ addBottomSafeAreaPadding,
+ addOfflineIndicatorBottomSafeAreaPadding,
+ isOffline,
+ isOfflineIndicatorSafeAreaPaddingEnabled,
+ style,
+ safeAreaPaddingBottom,
+ styleProperty,
+ ]);
}
export default useBottomSafeSafeAreaPaddingStyle;
diff --git a/src/hooks/useScreenWrapperTransitionStatus.ts b/src/hooks/useScreenWrapperTransitionStatus.ts
index 0d58bf3120c8..de94c9708797 100644
--- a/src/hooks/useScreenWrapperTransitionStatus.ts
+++ b/src/hooks/useScreenWrapperTransitionStatus.ts
@@ -7,11 +7,11 @@ import {ScreenWrapperStatusContext} from '@components/ScreenWrapper';
* @returns `didScreenTransitionEnd` flag to indicate if navigation transition ended.
*/
export default function useScreenWrapperTransitionStatus() {
- const value = useContext(ScreenWrapperStatusContext);
+ const context = useContext(ScreenWrapperStatusContext);
- if (value === undefined) {
+ if (context === undefined) {
throw new Error("Couldn't find values for screen ScreenWrapper transition status. Are you inside a screen in ScreenWrapper?");
}
- return value;
+ return {didScreenTransitionEnd: context.didScreenTransitionEnd};
}
diff --git a/src/libs/Navigation/AppNavigator/Navigators/LeftModalNavigator.tsx b/src/libs/Navigation/AppNavigator/Navigators/LeftModalNavigator.tsx
index aaf40a62f99e..1fb7c1ea44b3 100644
--- a/src/libs/Navigation/AppNavigator/Navigators/LeftModalNavigator.tsx
+++ b/src/libs/Navigation/AppNavigator/Navigators/LeftModalNavigator.tsx
@@ -10,6 +10,7 @@ import type {AuthScreensParamList, LeftModalNavigatorParamList} from '@libs/Navi
import NAVIGATORS from '@src/NAVIGATORS';
import SCREENS from '@src/SCREENS';
import type ReactComponentModule from '@src/types/utils/ReactComponentModule';
+import {NarrowPaneContextProvider} from './NarrowPaneContext';
import Overlay from './Overlay';
type LeftModalNavigatorProps = PlatformStackScreenProps;
@@ -24,25 +25,27 @@ function LeftModalNavigator({navigation}: LeftModalNavigatorProps) {
const screenOptions = useSideModalStackScreenOptions('horizontal-inverted');
return (
-
- {!shouldUseNarrowLayout && (
-
- )}
-
-
-
+
+ {!shouldUseNarrowLayout && (
+
-
-
-
+ )}
+
+
+
+
+
+
+
);
}
diff --git a/src/libs/Navigation/AppNavigator/Navigators/NarrowPaneContext.tsx b/src/libs/Navigation/AppNavigator/Navigators/NarrowPaneContext.tsx
new file mode 100644
index 000000000000..e08164ece8a6
--- /dev/null
+++ b/src/libs/Navigation/AppNavigator/Navigators/NarrowPaneContext.tsx
@@ -0,0 +1,19 @@
+import React, {createContext} from 'react';
+
+type NarrowPaneContextType = {
+ // Whether the screen/component accessing the context is in narrow pane navigator (RHP/LHP)
+ isInNarrowPane: boolean;
+};
+
+const NarrowPaneContext = createContext({isInNarrowPane: false});
+
+const IS_IN_NARROW_PANE_CONTEXT_VALUE: NarrowPaneContextType = {
+ isInNarrowPane: true,
+};
+
+function NarrowPaneContextProvider({children}: {children: React.ReactNode}) {
+ return {children};
+}
+
+export default NarrowPaneContext;
+export {NarrowPaneContextProvider};
diff --git a/src/libs/Navigation/AppNavigator/Navigators/PublicRightModalNavigator.tsx b/src/libs/Navigation/AppNavigator/Navigators/PublicRightModalNavigator.tsx
index dccf2e10fc75..7e17a4f74781 100644
--- a/src/libs/Navigation/AppNavigator/Navigators/PublicRightModalNavigator.tsx
+++ b/src/libs/Navigation/AppNavigator/Navigators/PublicRightModalNavigator.tsx
@@ -10,6 +10,7 @@ import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavig
import type {ConsoleNavigatorParamList, PublicScreensParamList} from '@libs/Navigation/types';
import NAVIGATORS from '@src/NAVIGATORS';
import SCREENS from '@src/SCREENS';
+import {NarrowPaneContextProvider} from './NarrowPaneContext';
import Overlay from './Overlay';
type PublicRightModalNavigatorComponentProps = PlatformStackScreenProps;
@@ -23,20 +24,22 @@ function PublicRightModalNavigatorComponent({navigation}: PublicRightModalNaviga
const screenOptions = useCustomScreenOptions();
return (
-
- {!shouldUseNarrowLayout && }
-
-
-
-
-
-
+
+
+ {!shouldUseNarrowLayout && }
+
+
+
+
+
+
+
);
}
diff --git a/src/libs/Navigation/AppNavigator/Navigators/RightModalNavigator.tsx b/src/libs/Navigation/AppNavigator/Navigators/RightModalNavigator.tsx
index cd90a58bfed5..366131799dfa 100644
--- a/src/libs/Navigation/AppNavigator/Navigators/RightModalNavigator.tsx
+++ b/src/libs/Navigation/AppNavigator/Navigators/RightModalNavigator.tsx
@@ -14,6 +14,7 @@ import type {AuthScreensParamList, RightModalNavigatorParamList} from '@navigati
import CONST from '@src/CONST';
import NAVIGATORS from '@src/NAVIGATORS';
import SCREENS from '@src/SCREENS';
+import {NarrowPaneContextProvider} from './NarrowPaneContext';
import Overlay from './Overlay';
type RightModalNavigatorProps = PlatformStackScreenProps;
@@ -28,208 +29,210 @@ function RightModalNavigator({navigation, route}: RightModalNavigatorProps) {
const screenOptions = useCustomScreenOptions();
return (
-
- {!shouldUseNarrowLayout && (
- {
- if (isExecutingRef.current) {
- return;
- }
- isExecutingRef.current = true;
- navigation.goBack();
- setTimeout(() => {
- isExecutingRef.current = false;
- }, CONST.ANIMATED_TRANSITION);
- }}
- />
- )}
-
- {
- if (
- // @ts-expect-error There is something wrong with a types here and it's don't see the params list
- navigation.getState().routes.find((routes) => routes.name === NAVIGATORS.RIGHT_MODAL_NAVIGATOR)?.params?.screen ===
- SCREENS.RIGHT_MODAL.TRANSACTION_DUPLICATE ||
- route.params?.screen !== SCREENS.RIGHT_MODAL.TRANSACTION_DUPLICATE
- ) {
+
+
+ {!shouldUseNarrowLayout && (
+ {
+ if (isExecutingRef.current) {
return;
}
- // Delay clearing review duplicate data till the RHP is completely closed
- // to avoid not found showing briefly in confirmation page when RHP is closing
- InteractionManager.runAfterInteractions(() => {
- abandonReviewDuplicateTransactions();
- });
- },
- }}
- id={NAVIGATORS.RIGHT_MODAL_NAVIGATOR}
- >
- {
+ isExecutingRef.current = false;
+ }, CONST.ANIMATED_TRANSITION);
+ }}
/>
- {
- InteractionManager.runAfterInteractions(clearTwoFactorAuthData);
+ )}
+
+ {
+ if (
+ // @ts-expect-error There is something wrong with a types here and it's don't see the params list
+ navigation.getState().routes.find((routes) => routes.name === NAVIGATORS.RIGHT_MODAL_NAVIGATOR)?.params?.screen ===
+ SCREENS.RIGHT_MODAL.TRANSACTION_DUPLICATE ||
+ route.params?.screen !== SCREENS.RIGHT_MODAL.TRANSACTION_DUPLICATE
+ ) {
+ return;
+ }
+ // Delay clearing review duplicate data till the RHP is completely closed
+ // to avoid not found showing briefly in confirmation page when RHP is closing
+ InteractionManager.runAfterInteractions(() => {
+ abandonReviewDuplicateTransactions();
+ });
},
}}
- />
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ id={NAVIGATORS.RIGHT_MODAL_NAVIGATOR}
+ >
+
+ {
+ InteractionManager.runAfterInteractions(clearTwoFactorAuthData);
+ },
+ }}
+ />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
);
}
diff --git a/src/pages/NewChatPage.tsx b/src/pages/NewChatPage.tsx
index a3103885d9d1..1b3c92f379d6 100755
--- a/src/pages/NewChatPage.tsx
+++ b/src/pages/NewChatPage.tsx
@@ -44,11 +44,16 @@ import KeyboardUtils from '@src/utils/keyboard';
const excludedGroupEmails: string[] = CONST.EXPENSIFY_EMAILS.filter((value) => value !== CONST.EMAIL.CONCIERGE);
+type SelectedOption = ListItem &
+ Omit & {
+ reportID?: string;
+ };
+
function useOptions() {
const [searchTerm, debouncedSearchTerm, setSearchTerm] = useDebouncedState('');
- const [selectedOptions, setSelectedOptions] = useState>([]);
- const [betas] = useOnyx(ONYXKEYS.BETAS);
- const [newGroupDraft] = useOnyx(ONYXKEYS.NEW_GROUP_CHAT_DRAFT);
+ const [selectedOptions, setSelectedOptions] = useState([]);
+ const [betas] = useOnyx(ONYXKEYS.BETAS, {canBeMissing: true});
+ const [newGroupDraft] = useOnyx(ONYXKEYS.NEW_GROUP_CHAT_DRAFT, {canBeMissing: true});
const personalData = useCurrentUserPersonalDetails();
const {didScreenTransitionEnd} = useScreenWrapperTransitionStatus();
const {options: listOptions, areOptionsInitialized} = useOptionsList({
@@ -142,7 +147,7 @@ function NewChatPage() {
const styles = useThemeStyles();
const personalData = useCurrentUserPersonalDetails();
const {top} = useSafeAreaInsets();
- const [isSearchingForReports] = useOnyx(ONYXKEYS.IS_SEARCHING_FOR_REPORTS, {initWithStoredValues: false});
+ const [isSearchingForReports] = useOnyx(ONYXKEYS.IS_SEARCHING_FOR_REPORTS, {initWithStoredValues: false, canBeMissing: true});
const selectionListRef = useRef(null);
const {headerMessage, searchTerm, debouncedSearchTerm, setSearchTerm, selectedOptions, setSelectedOptions, recentReports, personalDetails, userToInvite, areOptionsInitialized} =
@@ -152,7 +157,7 @@ function NewChatPage() {
const sectionsList: Section[] = [];
let firstKey = '';
- const formatResults = formatSectionsFromSearchTerm(debouncedSearchTerm, selectedOptions, recentReports, personalDetails);
+ const formatResults = formatSectionsFromSearchTerm(debouncedSearchTerm, selectedOptions as OptionData[], recentReports, personalDetails);
sectionsList.push(formatResults.section);
if (!firstKey) {
@@ -198,12 +203,12 @@ function NewChatPage() {
(option: ListItem & Partial) => {
const isOptionInList = !!option.isSelected;
- let newSelectedOptions;
+ let newSelectedOptions: SelectedOption[];
if (isOptionInList) {
newSelectedOptions = reject(selectedOptions, (selectedOption) => selectedOption.login === option.login);
} else {
- newSelectedOptions = [...selectedOptions, {...option, isSelected: true, selected: true, reportID: option.reportID ?? `${CONST.DEFAULT_NUMBER_ID}`}];
+ newSelectedOptions = [...selectedOptions, {...option, isSelected: true, selected: true, reportID: option.reportID}];
selectionListRef?.current?.scrollToIndex(0, true);
}
@@ -296,7 +301,7 @@ function NewChatPage() {
if (!personalData || !personalData.login || !personalData.accountID) {
return;
}
- const selectedParticipants: SelectedParticipant[] = selectedOptions.map((option: OptionData) => ({
+ const selectedParticipants: SelectedParticipant[] = selectedOptions.map((option) => ({
login: option?.login,
accountID: option.accountID ?? CONST.DEFAULT_NUMBER_ID,
}));
@@ -309,7 +314,7 @@ function NewChatPage() {
const footerContent = useMemo(
() =>
- !isDismissed || selectedOptions.length ? (
+ (!isDismissed || selectedOptions.length > 0) && (
<>
)}
>
- ) : null,
+ ),
[createGroup, selectedOptions.length, styles.mb5, translate, isDismissed],
);
@@ -335,6 +340,8 @@ function NewChatPage() {
enableEdgeToEdgeBottomSafeAreaPadding
includePaddingTop={false}
shouldEnablePickerAvoiding={false}
+ disableOfflineIndicatorSafeAreaPadding
+ shouldShowOfflineIndicator={false}
keyboardVerticalOffset={variables.contentHeaderHeight + top + variables.tabSelectorButtonHeight + variables.tabSelectorButtonPadding}
// Disable the focus trap of this page to activate the parent focus trap in `NewChatSelectorPage`.
focusTrapSettings={{active: false}}
diff --git a/src/pages/workspace/WorkspaceNewRoomPage.tsx b/src/pages/workspace/WorkspaceNewRoomPage.tsx
index 5e823caf5541..acad336394e8 100644
--- a/src/pages/workspace/WorkspaceNewRoomPage.tsx
+++ b/src/pages/workspace/WorkspaceNewRoomPage.tsx
@@ -17,7 +17,6 @@ import useActiveWorkspace from '@hooks/useActiveWorkspace';
import useAutoFocusInput from '@hooks/useAutoFocusInput';
import useBottomSafeSafeAreaPaddingStyle from '@hooks/useBottomSafeSafeAreaPaddingStyle';
import useLocalize from '@hooks/useLocalize';
-import useResponsiveLayout from '@hooks/useResponsiveLayout';
import useSafeAreaInsets from '@hooks/useSafeAreaInsets';
import useThemeStyles from '@hooks/useThemeStyles';
import {addErrorMessage} from '@libs/ErrorUtils';
@@ -34,6 +33,33 @@ import ROUTES from '@src/ROUTES';
import INPUT_IDS from '@src/types/form/NewRoomForm';
import type * as OnyxCommon from '@src/types/onyx/OnyxCommon';
+function EmptyWorkspaceView() {
+ const styles = useThemeStyles();
+ const {translate} = useLocalize();
+ const bottomSafeAreaPaddingStyle = useBottomSafeSafeAreaPaddingStyle({addBottomSafeAreaPadding: true, additionalPaddingBottom: styles.mb5.marginBottom, styleProperty: 'marginBottom'});
+
+ return (
+ <>
+
+