diff --git a/assets/images/new-expensify.svg b/assets/images/new-expensify.svg
index 38276ecd9385..dc7aec87c6fd 100644
--- a/assets/images/new-expensify.svg
+++ b/assets/images/new-expensify.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/src/components/Icon/Expensicons.ts b/src/components/Icon/Expensicons.ts
index 4d4d187b5510..164f0b6d2454 100644
--- a/src/components/Icon/Expensicons.ts
+++ b/src/components/Icon/Expensicons.ts
@@ -52,6 +52,7 @@ import EReceiptIcon from '@assets/images/eReceiptIcon.svg';
import Exclamation from '@assets/images/exclamation.svg';
import Exit from '@assets/images/exit.svg';
import Expand from '@assets/images/expand.svg';
+import ExpensifyAppIcon from '@assets/images/expensify-app-icon.svg';
import ExpensifyFooterLogoVertical from '@assets/images/expensify-footer-logo-vertical.svg';
import ExpensifyFooterLogo from '@assets/images/expensify-footer-logo.svg';
import ExpensifyWordmark from '@assets/images/expensify-wordmark.svg';
@@ -185,6 +186,7 @@ export {
EmptyStateAttachReceipt,
Exclamation,
Exit,
+ ExpensifyAppIcon,
ExpensifyCard,
ExpensifyWordmark,
ExpensifyFooterLogo,
diff --git a/src/components/Icon/index.tsx b/src/components/Icon/index.tsx
index 5f82421c0e8e..0ba7d444324b 100644
--- a/src/components/Icon/index.tsx
+++ b/src/components/Icon/index.tsx
@@ -100,4 +100,5 @@ function Icon({
Icon.displayName = 'Icon';
+export type {IconProps};
export default Icon;
diff --git a/src/components/IllustratedHeaderPageLayout.js b/src/components/IllustratedHeaderPageLayout.js
index dff3c52f4315..89e21c92c31e 100644
--- a/src/components/IllustratedHeaderPageLayout.js
+++ b/src/components/IllustratedHeaderPageLayout.js
@@ -1,8 +1,8 @@
import PropTypes from 'prop-types';
import React from 'react';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
import useWindowDimensions from '@hooks/useWindowDimensions';
-import useTheme from '../hooks/useTheme';
-import useThemeStyles from '../hooks/useThemeStyles';
import HeaderPageLayout from './HeaderPageLayout';
import headerWithBackButtonPropTypes from './HeaderWithBackButton/headerWithBackButtonPropTypes';
import Lottie from './Lottie';
diff --git a/src/components/MenuItem.js b/src/components/MenuItem.js
index b1f6b7f7319a..4c47f60a894d 100644
--- a/src/components/MenuItem.js
+++ b/src/components/MenuItem.js
@@ -84,6 +84,7 @@ const defaultProps = {
shouldShowRightComponent: false,
titleWithTooltips: [],
shouldCheckActionAllowedOnPress: true,
+ isPaneMenu: false,
};
const MenuItem = React.forwardRef((props, ref) => {
@@ -234,6 +235,7 @@ const MenuItem = React.forwardRef((props, ref) => {
StyleUtils.getIconFillColor(
getButtonState(props.focused || isHovered, pressed, props.success, props.disabled, props.interactive),
true,
+ props.isPaneMenu,
)
}
/>
@@ -266,7 +268,11 @@ const MenuItem = React.forwardRef((props, ref) => {
height={props.iconHeight}
fill={
props.secondaryIconFill ||
- StyleUtils.getIconFillColor(getButtonState(props.focused || isHovered, pressed, props.success, props.disabled, props.interactive), true)
+ StyleUtils.getIconFillColor(
+ getButtonState(props.focused || isHovered, pressed, props.success, props.disabled, props.interactive),
+ true,
+ props.isPaneMenu,
+ )
}
/>
diff --git a/src/components/SubscriptAvatar.tsx b/src/components/SubscriptAvatar.tsx
index 9a0aa934ff1b..05c0aa6138e6 100644
--- a/src/components/SubscriptAvatar.tsx
+++ b/src/components/SubscriptAvatar.tsx
@@ -8,8 +8,20 @@ import type {AvatarSource} from '@libs/UserUtils';
import CONST from '@src/CONST';
import {AvatarType} from '@src/types/onyx/OnyxCommon';
import Avatar from './Avatar';
+import Icon, {IconProps} from './Icon';
import UserDetailsTooltip from './UserDetailsTooltip';
+type SubIcon = {
+ /** Avatar source to display */
+ source: IconProps['src'];
+
+ /** Width of the icon */
+ width?: number;
+
+ /** Height of the icon */
+ height?: number;
+};
+
type SubAvatar = {
/** Avatar source to display */
source?: AvatarSource;
@@ -31,15 +43,18 @@ type SubscriptAvatarProps = {
/** Avatar URL or icon */
mainAvatar?: SubAvatar;
- /** Subscript avatar URL or icon */
- secondaryAvatar?: SubAvatar;
-
/** Set the size of avatars */
size?: ValueOf;
/** Background color used for subscript avatar border */
backgroundColor?: string;
+ /** Subscript avatar URL or icon */
+ secondaryAvatar?: SubAvatar;
+
+ /** Subscript icon type */
+ subscriptIcon?: SubIcon;
+
/** Removes margin from around the avatar, used for the chat view */
noMargin?: boolean;
@@ -47,7 +62,7 @@ type SubscriptAvatarProps = {
showTooltip?: boolean;
};
-function SubscriptAvatar({mainAvatar = {}, secondaryAvatar = {}, size = CONST.AVATAR_SIZE.DEFAULT, backgroundColor, noMargin = false, showTooltip = true}: SubscriptAvatarProps) {
+function SubscriptAvatar({mainAvatar = {}, secondaryAvatar, subscriptIcon, size = CONST.AVATAR_SIZE.DEFAULT, backgroundColor, noMargin = false, showTooltip = true}: SubscriptAvatarProps) {
const theme = useTheme();
const styles = useThemeStyles();
const StyleUtils = useStyleUtils();
@@ -73,31 +88,58 @@ function SubscriptAvatar({mainAvatar = {}, secondaryAvatar = {}, size = CONST.AV
/>
-
+ {secondaryAvatar && (
+
+
+
+
+
+ )}
+ {subscriptIcon && (
-
-
+ )}
);
}
diff --git a/src/components/WorkspaceSwitcherButton.tsx b/src/components/WorkspaceSwitcherButton.tsx
new file mode 100644
index 000000000000..30a10cc96da0
--- /dev/null
+++ b/src/components/WorkspaceSwitcherButton.tsx
@@ -0,0 +1,30 @@
+import React from 'react';
+import useLocalize from '@hooks/useLocalize';
+import CONST from '@src/CONST';
+import * as Expensicons from './Icon/Expensicons';
+import {PressableWithFeedback} from './Pressable';
+import SubscriptAvatar from './SubscriptAvatar';
+
+function WorkspaceSwitcherButton() {
+ const {translate} = useLocalize();
+
+ return (
+ {}}
+ >
+
+
+ );
+}
+
+WorkspaceSwitcherButton.displayName = 'WorkspaceSwitcherButton';
+
+export default WorkspaceSwitcherButton;
diff --git a/src/components/menuItemPropTypes.js b/src/components/menuItemPropTypes.js
index 4d2de3275e23..576fff6d78da 100644
--- a/src/components/menuItemPropTypes.js
+++ b/src/components/menuItemPropTypes.js
@@ -162,6 +162,9 @@ const propTypes = {
/** Should check anonymous user in onPress function */
shouldCheckActionAllowedOnPress: PropTypes.bool,
+
+ /** Is this menu item in the settings pane */
+ isPaneMenu: PropTypes.bool,
};
export default propTypes;
diff --git a/src/languages/en.ts b/src/languages/en.ts
index 563f111a9772..dfe9e02ab03a 100755
--- a/src/languages/en.ts
+++ b/src/languages/en.ts
@@ -1996,7 +1996,6 @@ export default {
transactionDate: 'Transaction date',
},
breadcrumbs: {
- // TODO-IDEAL: Verify translations in Spanish
chats: 'Chats',
},
referralProgram: {
diff --git a/src/libs/Navigation/AppNavigator/createCustomBottomTabNavigator/TopBar.js b/src/libs/Navigation/AppNavigator/createCustomBottomTabNavigator/TopBar.js
new file mode 100644
index 000000000000..fc92d8514b7c
--- /dev/null
+++ b/src/libs/Navigation/AppNavigator/createCustomBottomTabNavigator/TopBar.js
@@ -0,0 +1,61 @@
+import PropTypes from 'prop-types';
+import React, {useCallback} from 'react';
+import {View} from 'react-native';
+import * as Expensicons from '@components/Icon/Expensicons';
+import PressableWithFeedback from '@components/Pressable/PressableWithFeedback';
+import Search from '@components/Search';
+import SubscriptAvatar from '@components/SubscriptAvatar';
+import useLocalize from '@hooks/useLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
+import Navigation from '@libs/Navigation/Navigation';
+import SignInOrAvatarWithOptionalStatus from '@pages/home/sidebar/SignInOrAvatarWithOptionalStatus';
+import * as Session from '@userActions/Session';
+import CONST from '@src/CONST';
+import ROUTES from '@src/ROUTES';
+
+// TODO-IDEAL: isCreateMenuOpen wasn't used before
+function TopBar({isCreateMenuOpen = false}) {
+ const styles = useThemeStyles();
+ const {translate} = useLocalize();
+
+ const showSearchPage = useCallback(() => {
+ if (isCreateMenuOpen) {
+ // Prevent opening Search page when click Search icon quickly after clicking FAB icon
+ return;
+ }
+
+ Navigation.navigate(ROUTES.SEARCH);
+ }, [isCreateMenuOpen]);
+
+ return (
+
+
+
+
+
+
+
+ );
+}
+
+TopBar.displayName = 'TopBar';
+TopBar.propTypes = {
+ isCreateMenuOpen: PropTypes.bool,
+};
+TopBar.defaultProps = {
+ isCreateMenuOpen: false,
+};
+
+export default TopBar;
diff --git a/src/libs/Navigation/AppNavigator/createCustomBottomTabNavigator/index.tsx b/src/libs/Navigation/AppNavigator/createCustomBottomTabNavigator/index.tsx
index 24be4ce5a174..e6a34a428527 100644
--- a/src/libs/Navigation/AppNavigator/createCustomBottomTabNavigator/index.tsx
+++ b/src/libs/Navigation/AppNavigator/createCustomBottomTabNavigator/index.tsx
@@ -15,6 +15,7 @@ import {View} from 'react-native';
import {NavigationStateRoute} from '@libs/Navigation/types';
import SCREENS from '@src/SCREENS';
import BottomTabBar from './BottomTabBar';
+import TopBar from './TopBar';
type CustomNavigatorProps = DefaultNavigatorOptions, StackNavigationOptions, StackNavigationEventMap> & {
initialRouteName: string;
@@ -67,6 +68,7 @@ function CustomBottomTabNavigator({initialRouteName, children, screenOptions, ..
return (
+
{
- if (isCreateMenuOpen) {
- // Prevent opening Search page when click Search icon quickly after clicking FAB icon
- return;
- }
-
- Navigation.navigate(ROUTES.SEARCH);
- }, [isCreateMenuOpen]);
-
/**
* Show Report page with selected report id
*
@@ -152,33 +132,6 @@ function SidebarLinks({onLinkClick, insets, optionListItems, isLoading, priority
return (
-
-
- }
- role={CONST.ROLE.PRESENTATION}
- shouldShowEnvironmentBadge
- />
-
-
-
-
-
-
-
{
Link.openExternalLink(CONST.EXPENSIFY_INBOX_URL);
},
- shouldShowRightIcon: true,
- iconRight: Expensicons.NewWindow,
link: CONST.EXPENSIFY_INBOX_URL,
},
{
@@ -210,8 +208,6 @@ function InitialSettingsPage(props) {
action: () => {
Link.openExternalLink(CONST.NEWHELP_URL);
},
- shouldShowRightIcon: true,
- iconRight: Expensicons.NewWindow,
link: CONST.NEWHELP_URL,
},
{
@@ -273,6 +269,7 @@ function InitialSettingsPage(props) {
!_.isEmpty(item.link) ? (e) => ReportActionContextMenu.showContextMenu(CONTEXT_MENU_TYPES.LINK, e, item.link, popoverAnchor.current) : undefined
}
focused={activeRoute && activeRoute.startsWith(item.routeName, 1)}
+ isPaneMenu
/>
);
})}
@@ -355,14 +352,12 @@ function InitialSettingsPage(props) {
);
- const navigateBackTo = lodashGet(props.route, 'params.backTo', ROUTES.HOME);
-
return (
Navigation.navigate(navigateBackTo)}
+ onBackButtonPress={() => Navigation.closeFullScreen()}
backgroundColor={theme.PAGE_THEMES[SCREENS.SETTINGS.ROOT].backgroundColor}
childrenContainerStyles={[styles.m0, styles.p0]}
>
diff --git a/src/stories/SubscriptAvatar.stories.js b/src/stories/SubscriptAvatar.stories.js
index 9ca055aaa5d8..f2cf1c216052 100644
--- a/src/stories/SubscriptAvatar.stories.js
+++ b/src/stories/SubscriptAvatar.stories.js
@@ -1,6 +1,6 @@
import React from 'react';
import * as defaultAvatars from '@components/Icon/DefaultAvatars';
-import * as defaultWorkspaceAvatars from '@components/Icon/WorkspaceDefaultAvatars';
+import * as Expensicons from '@components/Icon/Expensicons';
import SubscriptAvatar from '@components/SubscriptAvatar';
import CONST from '@src/CONST';
@@ -14,7 +14,6 @@ export default {
component: SubscriptAvatar,
args: {
mainAvatar: {source: defaultAvatars.Avatar5, name: '', type: CONST.ICON_TYPE_AVATAR},
- secondaryAvatar: {source: defaultWorkspaceAvatars.WorkspaceE, name: '', type: CONST.ICON_TYPE_WORKSPACE},
size: CONST.AVATAR_SIZE.DEFAULT,
},
argTypes: {
@@ -39,4 +38,15 @@ AvatarURLStory.args = {
secondaryAvatar: {source: defaultAvatars.Avatar3, name: '', type: CONST.ICON_TYPE_AVATAR},
};
-export {Default, AvatarURLStory};
+const SubscriptIcon = Template.bind({});
+SubscriptIcon.args = {
+ subscriptIcon: {source: Expensicons.DownArrow, width: 8, height: 8},
+};
+
+const WorkspaceSubscriptIcon = Template.bind({});
+WorkspaceSubscriptIcon.args = {
+ mainAvatar: {source: defaultAvatars.Avatar1, name: '', type: CONST.ICON_TYPE_WORKSPACE},
+ subscriptIcon: {source: Expensicons.DownArrow, width: 8, height: 8},
+};
+
+export {Default, AvatarURLStory, SubscriptIcon, WorkspaceSubscriptIcon};
diff --git a/src/styles/index.ts b/src/styles/index.ts
index 713e32eeab45..5c7743ecb01b 100644
--- a/src/styles/index.ts
+++ b/src/styles/index.ts
@@ -2149,6 +2149,15 @@ const styles = (theme: ThemeColors) =>
marginRight: variables.avatarChatSpacing - 4,
},
+ subscriptIcon: {
+ position: 'absolute',
+ bottom: -4,
+ right: -4,
+ width: 20,
+ height: 20,
+ backgroundColor: theme.buttonDefaultBG,
+ },
+
borderTop: {
borderTopWidth: variables.borderTopWidth,
borderColor: theme.border,
diff --git a/src/styles/theme/themes/dark.ts b/src/styles/theme/themes/dark.ts
index 315593a3a8b2..7a94988eb019 100644
--- a/src/styles/theme/themes/dark.ts
+++ b/src/styles/theme/themes/dark.ts
@@ -12,7 +12,7 @@ const darkTheme = {
borderLighter: colors.productDark400,
borderFocus: colors.green400,
icon: colors.productDark700,
- iconMenu: colors.productDark700,
+ iconMenu: colors.green400,
iconHovered: colors.productDark900,
iconMenuHovered: colors.green400,
iconSuccessFill: colors.green400,
@@ -45,7 +45,7 @@ const darkTheme = {
hoverComponentBG: colors.productDark300,
activeComponentBG: colors.productDark400,
signInSidebar: colors.green800,
- sidebar: colors.productDark200,
+ sidebar: colors.productDark100,
sidebarHover: colors.productDark300,
heading: colors.productDark900,
textLight: colors.productDark900,
diff --git a/src/styles/theme/themes/light.ts b/src/styles/theme/themes/light.ts
index c957bccf6fbe..228917d73d26 100644
--- a/src/styles/theme/themes/light.ts
+++ b/src/styles/theme/themes/light.ts
@@ -12,7 +12,7 @@ const lightTheme = {
borderLighter: colors.productLight400,
borderFocus: colors.green400,
icon: colors.productLight700,
- iconMenu: colors.productLight700,
+ iconMenu: colors.green400,
iconHovered: colors.productLight900,
iconMenuHovered: colors.green400,
iconSuccessFill: colors.green400,
@@ -45,7 +45,7 @@ const lightTheme = {
hoverComponentBG: colors.productLight300,
activeComponentBG: colors.productLight400,
signInSidebar: colors.green800,
- sidebar: colors.productLight200,
+ sidebar: colors.productLight100,
sidebarHover: colors.productLight300,
heading: colors.productLight900,
textLight: colors.white,
diff --git a/src/styles/utils/index.ts b/src/styles/utils/index.ts
index c4130d9b2475..ab2f42065c72 100644
--- a/src/styles/utils/index.ts
+++ b/src/styles/utils/index.ts
@@ -1301,12 +1301,12 @@ const createStyleUtils = (theme: ThemeColors, styles: ThemeStyles) => ({
* @param buttonState - One of {'default', 'hovered', 'pressed'}
* @param isMenuIcon - whether this icon is apart of a list
*/
- getIconFillColor: (buttonState: ButtonStateName = CONST.BUTTON_STATES.DEFAULT, isMenuIcon = false): string => {
+ getIconFillColor: (buttonState: ButtonStateName = CONST.BUTTON_STATES.DEFAULT, isMenuIcon = false, isPane = false): string => {
switch (buttonState) {
case CONST.BUTTON_STATES.ACTIVE:
case CONST.BUTTON_STATES.PRESSED:
- if (isMenuIcon) {
- return theme.iconMenuHovered;
+ if (isPane) {
+ return theme.iconMenu;
}
return theme.iconHovered;
case CONST.BUTTON_STATES.COMPLETE:
@@ -1314,7 +1314,7 @@ const createStyleUtils = (theme: ThemeColors, styles: ThemeStyles) => ({
case CONST.BUTTON_STATES.DEFAULT:
case CONST.BUTTON_STATES.DISABLED:
default:
- if (isMenuIcon) {
+ if (isMenuIcon && !isPane) {
return theme.iconMenu;
}
return theme.icon;
diff --git a/src/styles/utils/spacing.ts b/src/styles/utils/spacing.ts
index b2597fc64603..8551bee420ba 100644
--- a/src/styles/utils/spacing.ts
+++ b/src/styles/utils/spacing.ts
@@ -553,6 +553,10 @@ export default {
gap: 20,
},
+ gap6: {
+ gap: 24,
+ },
+
gap7: {
gap: 28,
},