diff --git a/assets/images/filters.svg b/assets/images/filters.svg
new file mode 100644
index 000000000000..ed0f1169d168
--- /dev/null
+++ b/assets/images/filters.svg
@@ -0,0 +1,6 @@
+
diff --git a/assets/images/simple-illustrations/simple-illustration__filters.svg b/assets/images/simple-illustrations/simple-illustration__filters.svg
new file mode 100644
index 000000000000..c1d574f154f4
--- /dev/null
+++ b/assets/images/simple-illustrations/simple-illustration__filters.svg
@@ -0,0 +1,24 @@
+
diff --git a/src/components/Icon/Expensicons.ts b/src/components/Icon/Expensicons.ts
index 0b9306d1c977..3aacf2ae88c8 100644
--- a/src/components/Icon/Expensicons.ts
+++ b/src/components/Icon/Expensicons.ts
@@ -82,6 +82,7 @@ import ExpensifyLogoNew from '@assets/images/expensify-logo-new.svg';
import ExpensifyWordmark from '@assets/images/expensify-wordmark.svg';
import EyeDisabled from '@assets/images/eye-disabled.svg';
import Eye from '@assets/images/eye.svg';
+import Filters from '@assets/images/filters.svg';
import Flag from '@assets/images/flag.svg';
import FlagLevelOne from '@assets/images/flag_level_01.svg';
import FlagLevelTwo from '@assets/images/flag_level_02.svg';
@@ -373,5 +374,6 @@ export {
CheckCircle,
CheckmarkCircle,
NetSuiteSquare,
+ Filters,
CalendarSolid,
};
diff --git a/src/components/Icon/Illustrations.ts b/src/components/Icon/Illustrations.ts
index ccbf4b3a5da9..1ef0ca14bf51 100644
--- a/src/components/Icon/Illustrations.ts
+++ b/src/components/Icon/Illustrations.ts
@@ -56,6 +56,7 @@ import CreditCardsNew from '@assets/images/simple-illustrations/simple-illustrat
import CreditCardEyes from '@assets/images/simple-illustrations/simple-illustration__creditcardeyes.svg';
import EmailAddress from '@assets/images/simple-illustrations/simple-illustration__email-address.svg';
import EmptyState from '@assets/images/simple-illustrations/simple-illustration__empty-state.svg';
+import Filters from '@assets/images/simple-illustrations/simple-illustration__filters.svg';
import FolderOpen from '@assets/images/simple-illustrations/simple-illustration__folder-open.svg';
import Gears from '@assets/images/simple-illustrations/simple-illustration__gears.svg';
import HandCard from '@assets/images/simple-illustrations/simple-illustration__handcard.svg';
@@ -210,4 +211,5 @@ export {
FolderWithPapers,
VirtualCard,
Tire,
+ Filters,
};
diff --git a/src/components/Search/SearchListWithHeader.tsx b/src/components/Search/SearchListWithHeader.tsx
index abb1bc45aebe..aafa8141e99e 100644
--- a/src/components/Search/SearchListWithHeader.tsx
+++ b/src/components/Search/SearchListWithHeader.tsx
@@ -11,13 +11,14 @@ import * as SearchUtils from '@libs/SearchUtils';
import CONST from '@src/CONST';
import type {SearchDataTypes, SearchReport} from '@src/types/onyx/SearchResults';
import SearchPageHeader from './SearchPageHeader';
-import type {SearchStatus, SelectedTransactionInfo, SelectedTransactions} from './types';
+import type {SearchQueryJSON, SelectedTransactionInfo, SelectedTransactions} from './types';
type SearchListWithHeaderProps = Omit, 'onSelectAll' | 'onCheckboxPress' | 'sections'> & {
- status: SearchStatus;
+ queryJSON: SearchQueryJSON;
hash: number;
data: TransactionListItemType[] | ReportListItemType[];
searchType: SearchDataTypes;
+ isCustomQuery: boolean;
};
function mapTransactionItemToSelectedEntry(item: TransactionListItemType): [string, SelectedTransactionInfo] {
@@ -38,7 +39,7 @@ function mapToItemWithSelectionInfo(item: TransactionListItemType | ReportListIt
};
}
-function SearchListWithHeader({ListItem, onSelectRow, status, hash, data, searchType, ...props}: SearchListWithHeaderProps, ref: ForwardedRef) {
+function SearchListWithHeader({ListItem, onSelectRow, queryJSON, hash, data, searchType, isCustomQuery, ...props}: SearchListWithHeaderProps, ref: ForwardedRef) {
const {isSmallScreenWidth} = useWindowDimensions();
const {translate} = useLocalize();
const [selectedTransactions, setSelectedTransactions] = useState({});
@@ -148,10 +149,11 @@ function SearchListWithHeader({ListItem, onSelectRow, status, hash, data, search
setOfflineModalVisible(true)}
setDownloadErrorModalOpen={() => setDownloadErrorModalVisible(true)}
/>
diff --git a/src/components/Search/SearchPageHeader.tsx b/src/components/Search/SearchPageHeader.tsx
index 0dd83853456d..97ab5383ff9c 100644
--- a/src/components/Search/SearchPageHeader.tsx
+++ b/src/components/Search/SearchPageHeader.tsx
@@ -1,10 +1,15 @@
import React, {useMemo} from 'react';
+import type {StyleProp, TextStyle} from 'react-native';
+import {View} from 'react-native';
import {useOnyx} from 'react-native-onyx';
import ButtonWithDropdownMenu from '@components/ButtonWithDropdownMenu';
import type {DropdownOption} from '@components/ButtonWithDropdownMenu/types';
-import HeaderWithBackButton from '@components/HeaderWithBackButton';
+import Header from '@components/Header';
+import type HeaderWithBackButtonProps from '@components/HeaderWithBackButton/types';
+import Icon from '@components/Icon';
import * as Expensicons from '@components/Icon/Expensicons';
import * as Illustrations from '@components/Icon/Illustrations';
+import Text from '@components/Text';
import useActiveWorkspace from '@hooks/useActiveWorkspace';
import useLocalize from '@hooks/useLocalize';
import useNetwork from '@hooks/useNetwork';
@@ -14,32 +19,97 @@ import useThemeStyles from '@hooks/useThemeStyles';
import {turnOffMobileSelectionMode} from '@libs/actions/MobileSelectionMode';
import * as SearchActions from '@libs/actions/Search';
import Navigation from '@libs/Navigation/Navigation';
+import * as SearchUtils from '@libs/SearchUtils';
import SearchSelectedNarrow from '@pages/Search/SearchSelectedNarrow';
import variables from '@styles/variables';
import CONST from '@src/CONST';
+import type {TranslationPaths} from '@src/languages/types';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
import type {SearchReport} from '@src/types/onyx/SearchResults';
import type DeepValueOf from '@src/types/utils/DeepValueOf';
import type IconAsset from '@src/types/utils/IconAsset';
import {useSearchContext} from './SearchContext';
-import type {SearchStatus, SelectedTransactions} from './types';
+import type {SearchQueryJSON, SearchStatus, SelectedTransactions} from './types';
+
+type HeaderWrapperProps = Pick & {
+ subtitleStyles?: StyleProp;
+};
+
+function HeaderWrapper({icon, title, subtitle, children, subtitleStyles = {}}: HeaderWrapperProps) {
+ const styles = useThemeStyles();
+
+ // If the icon is present, the header bar should be taller and use different font.
+ const isCentralPaneSettings = !!icon;
+
+ const middleContent = useMemo(() => {
+ return (
+
+ {title}
+
+ }
+ subtitle={
+
+ {subtitle}
+
+ }
+ />
+ );
+ }, [styles.mutedTextLabel, styles.pre, styles.textLarge, subtitle, subtitleStyles, title]);
+
+ return (
+
+
+ {icon && (
+
+ )}
+
+ {middleContent}
+ {children}
+
+
+ );
+}
type SearchPageHeaderProps = {
- status: SearchStatus;
+ queryJSON: SearchQueryJSON;
selectedTransactions?: SelectedTransactions;
selectedReports?: Array;
clearSelectedItems?: () => void;
hash: number;
onSelectDeleteOption?: (itemsToDelete: string[]) => void;
+ isCustomQuery: boolean;
setOfflineModalOpen?: () => void;
setDownloadErrorModalOpen?: () => void;
};
type SearchHeaderOptionValue = DeepValueOf | undefined;
+const headerContent: {[key in SearchStatus]: {icon: IconAsset; titleTx: TranslationPaths}} = {
+ all: {icon: Illustrations.MoneyReceipts, titleTx: 'common.expenses'},
+ shared: {icon: Illustrations.SendMoney, titleTx: 'common.shared'},
+ drafts: {icon: Illustrations.Pencil, titleTx: 'common.drafts'},
+ finished: {icon: Illustrations.CheckmarkCircle, titleTx: 'common.finished'},
+};
+
function SearchPageHeader({
- status,
+ queryJSON,
selectedTransactions = {},
hash,
clearSelectedItems,
@@ -47,6 +117,7 @@ function SearchPageHeader({
setOfflineModalOpen,
setDownloadErrorModalOpen,
selectedReports,
+ isCustomQuery,
}: SearchPageHeaderProps) {
const {translate} = useLocalize();
const theme = useTheme();
@@ -55,17 +126,16 @@ function SearchPageHeader({
const {activeWorkspaceID} = useActiveWorkspace();
const {isSmallScreenWidth} = useResponsiveLayout();
const {setSelectedTransactionIDs} = useSearchContext();
+ const {status} = queryJSON;
+ const headerSubtitle = isCustomQuery ? SearchUtils.getSearchHeaderTitle(queryJSON) : translate(headerContent[status]?.titleTx);
+ const headerTitle = isCustomQuery ? translate('search.filtersHeader') : '';
+ const headerIcon = isCustomQuery ? Illustrations.Filters : headerContent[status]?.icon;
const [selectionMode] = useOnyx(ONYXKEYS.MOBILE_SELECTION_MODE);
- const headerContent: {[key in SearchStatus]: {icon: IconAsset; title: string}} = {
- all: {icon: Illustrations.MoneyReceipts, title: translate('common.expenses')},
- shared: {icon: Illustrations.SendMoney, title: translate('common.shared')},
- drafts: {icon: Illustrations.Pencil, title: translate('common.drafts')},
- finished: {icon: Illustrations.CheckmarkCircle, title: translate('common.finished')},
- };
-
const selectedTransactionsKeys = Object.keys(selectedTransactions ?? []);
+ const subtitleStyles = isCustomQuery ? {} : styles.textHeadlineH2;
+
const headerButtonsOptions = useMemo(() => {
if (selectedTransactionsKeys.length === 0) {
return [];
@@ -210,10 +280,11 @@ function SearchPageHeader({
}
return (
-
{headerButtonsOptions.length > 0 && (
)}
-
+
);
}
diff --git a/src/components/Search/index.tsx b/src/components/Search/index.tsx
index de08af11cefc..28fe2ebef7c6 100644
--- a/src/components/Search/index.tsx
+++ b/src/components/Search/index.tsx
@@ -32,6 +32,7 @@ import type {SearchColumnType, SearchQueryJSON, SearchStatus, SortOrder} from '.
type SearchProps = {
queryJSON: SearchQueryJSON;
policyIDs?: string;
+ isCustomQuery: boolean;
};
const sortableSearchTabs: SearchStatus[] = [CONST.SEARCH.STATUS.ALL];
@@ -40,7 +41,7 @@ const reportItemTransactionHeight = 52;
const listItemPadding = 12; // this is equivalent to 'mb3' on every transaction/report list item
const searchHeaderHeight = 54;
-function Search({queryJSON, policyIDs}: SearchProps) {
+function Search({queryJSON, policyIDs, isCustomQuery}: SearchProps) {
const {isOffline} = useNetwork();
const styles = useThemeStyles();
const {isLargeScreenWidth, isSmallScreenWidth} = useWindowDimensions();
@@ -109,7 +110,8 @@ function Search({queryJSON, policyIDs}: SearchProps) {
return (
<>
@@ -123,7 +125,8 @@ function Search({queryJSON, policyIDs}: SearchProps) {
return (
<>
@@ -182,10 +185,11 @@ function Search({queryJSON, policyIDs}: SearchProps) {
return (
> {
if (screenName === SCREENS.SEARCH.CENTRAL_PANE) {
// Generate default query string with buildSearchQueryString without argument.
- return {q: buildSearchQueryString()};
+ return {q: buildSearchQueryString(), isCustomQuery: false};
}
if (screenName === SCREENS.REPORT) {
diff --git a/src/libs/Navigation/linkingConfig/config.ts b/src/libs/Navigation/linkingConfig/config.ts
index d0aeb644f27d..f2d1bfb36d7e 100644
--- a/src/libs/Navigation/linkingConfig/config.ts
+++ b/src/libs/Navigation/linkingConfig/config.ts
@@ -55,7 +55,12 @@ const config: LinkingOptions['config'] = {
exact: true,
},
[SCREENS.SETTINGS.WORKSPACES]: ROUTES.SETTINGS_WORKSPACES,
- [SCREENS.SEARCH.CENTRAL_PANE]: ROUTES.SEARCH_CENTRAL_PANE.route,
+ [SCREENS.SEARCH.CENTRAL_PANE]: {
+ path: ROUTES.SEARCH_CENTRAL_PANE.route,
+ parse: {
+ isCustomQuery: (isCustomQuery) => isCustomQuery.toLowerCase() === 'true',
+ },
+ },
[SCREENS.SETTINGS.SAVE_THE_WORLD]: ROUTES.SETTINGS_SAVE_THE_WORLD,
[SCREENS.SETTINGS.SUBSCRIPTION.ROOT]: ROUTES.SETTINGS_SUBSCRIPTION,
diff --git a/src/libs/SearchUtils.ts b/src/libs/SearchUtils.ts
index 4c3229760d71..367f414eb53d 100644
--- a/src/libs/SearchUtils.ts
+++ b/src/libs/SearchUtils.ts
@@ -8,8 +8,8 @@ import ONYXKEYS from '@src/ONYXKEYS';
import type {SearchAdvancedFiltersForm} from '@src/types/form';
import INPUT_IDS from '@src/types/form/SearchAdvancedFiltersForm';
import type * as OnyxTypes from '@src/types/onyx';
-import type {SearchAccountDetails, SearchDataTypes, SearchPersonalDetails, SearchTransaction, SearchTypeToItemMap, SectionsType} from '@src/types/onyx/SearchResults';
import type SearchResults from '@src/types/onyx/SearchResults';
+import type {SearchAccountDetails, SearchDataTypes, SearchPersonalDetails, SearchTransaction, SearchTypeToItemMap, SectionsType} from '@src/types/onyx/SearchResults';
import DateUtils from './DateUtils';
import getTopmostCentralPaneRoute from './Navigation/getTopmostCentralPaneRoute';
import navigationRef from './Navigation/navigationRef';
@@ -33,6 +33,18 @@ const columnNamesToSortingProperty = {
[CONST.SEARCH.TABLE_COLUMNS.RECEIPT]: null,
};
+// This map contains signs with spaces that match each operator
+const operatorToSignMap = {
+ [CONST.SEARCH.SYNTAX_OPERATORS.EQUAL_TO]: ':' as const,
+ [CONST.SEARCH.SYNTAX_OPERATORS.LOWER_THAN]: '<' as const,
+ [CONST.SEARCH.SYNTAX_OPERATORS.LOWER_THAN_OR_EQUAL_TO]: '<=' as const,
+ [CONST.SEARCH.SYNTAX_OPERATORS.GREATER_THAN]: '>' as const,
+ [CONST.SEARCH.SYNTAX_OPERATORS.GREATER_THAN_OR_EQUAL_TO]: '>=' as const,
+ [CONST.SEARCH.SYNTAX_OPERATORS.NOT_EQUAL_TO]: '!=' as const,
+ [CONST.SEARCH.SYNTAX_OPERATORS.AND]: ',' as const,
+ [CONST.SEARCH.SYNTAX_OPERATORS.OR]: ' ' as const,
+};
+
/**
* @private
*/
@@ -429,11 +441,11 @@ function getFilters(query: SearchQueryString, fields: Array {
+ // If the previous queryFilter has the same operator (this rule applies only to eq and neq operators) then append the current value
+ if ((queryFilter.operator === 'eq' && queryFilters[index - 1]?.operator === 'eq') || (queryFilter.operator === 'neq' && queryFilters[index - 1]?.operator === 'neq')) {
+ filterValueString += `,${queryFilter.value}`;
+ } else {
+ filterValueString += ` ${filterName}${operatorToSignMap[queryFilter.operator]}${queryFilter.value}`;
+ }
+ });
+
+ return filterValueString;
+}
+
+function getSearchHeaderTitle(queryJSON: SearchQueryJSON) {
+ const {inputQuery, type, status} = queryJSON;
+ const filters = getFilters(inputQuery, Object.values(CONST.SEARCH.SYNTAX_FILTER_KEYS)) ?? {};
+
+ let title = `type:${type} status:${status}`;
+
+ Object.keys(filters).forEach((key) => {
+ const queryFilter = filters[key as ValueOf] as QueryFilter[];
+ title += buildFilterValueString(key, queryFilter);
+ });
+
+ return title;
+}
+
export {
+ buildQueryStringFromFilters,
buildSearchQueryJSON,
buildSearchQueryString,
getCurrentSearchParams,
+ getFilters,
getListItem,
getQueryHash,
+ getSearchHeaderTitle,
+ getSearchType,
getSections,
- getSortedSections,
getShouldShowMerchant,
- getSearchType,
- shouldShowYear,
+ getSortedSections,
isReportListItemType,
- isTransactionListItemType,
isSearchResultsEmpty,
- getFilters,
+ isTransactionListItemType,
normalizeQuery,
- buildQueryStringFromFilters,
+ shouldShowYear,
};
diff --git a/src/pages/Search/SearchPage.tsx b/src/pages/Search/SearchPage.tsx
index c95290dbc006..e2495c02d44f 100644
--- a/src/pages/Search/SearchPage.tsx
+++ b/src/pages/Search/SearchPage.tsx
@@ -17,10 +17,9 @@ type SearchPageProps = StackScreenProps buildSearchQueryJSON(route.params.q, policyIDs), [route.params.q, policyIDs]);
+ const queryJSON = useMemo(() => buildSearchQueryJSON(q, policyIDs), [q, policyIDs]);
const handleOnBackButtonPress = () => Navigation.goBack(ROUTES.SEARCH_CENTRAL_PANE.getRoute({query: CONST.SEARCH.TAB.EXPENSE.ALL}));
@@ -44,6 +43,7 @@ function SearchPage({route}: SearchPageProps) {
>
{queryJSON && (
diff --git a/src/pages/Search/SearchPageBottomTab.tsx b/src/pages/Search/SearchPageBottomTab.tsx
index 4f3138aef110..c8254af295d7 100644
--- a/src/pages/Search/SearchPageBottomTab.tsx
+++ b/src/pages/Search/SearchPageBottomTab.tsx
@@ -26,7 +26,7 @@ function SearchPageBottomTab() {
const styles = useThemeStyles();
const [selectionMode] = useOnyx(ONYXKEYS.MOBILE_SELECTION_MODE);
- const {queryJSON, policyIDs} = useMemo(() => {
+ const {queryJSON, policyIDs, isCustomQuery} = useMemo(() => {
if (!activeCentralPaneRoute || activeCentralPaneRoute.name !== SCREENS.SEARCH.CENTRAL_PANE) {
return {queryJSON: undefined, policyIDs: undefined};
}
@@ -37,6 +37,7 @@ function SearchPageBottomTab() {
return {
queryJSON: buildSearchQueryJSON(searchParams.q, searchParams.policyIDs),
policyIDs: searchParams.policyIDs,
+ isCustomQuery: searchParams.isCustomQuery,
};
}, [activeCentralPaneRoute]);
@@ -60,7 +61,10 @@ function SearchPageBottomTab() {
breadcrumbLabel={translate('common.search')}
shouldDisplaySearch={false}
/>
-
+
>
) : (
)}
diff --git a/src/pages/Search/SearchStatusMenu.tsx b/src/pages/Search/SearchStatusMenu.tsx
index e1470bdc4e75..9b8e890bbefd 100644
--- a/src/pages/Search/SearchStatusMenu.tsx
+++ b/src/pages/Search/SearchStatusMenu.tsx
@@ -1,13 +1,14 @@
import React from 'react';
import {View} from 'react-native';
import MenuItem from '@components/MenuItem';
-import type {SearchStatus} from '@components/Search/types';
+import type {SearchQueryJSON, SearchStatus} from '@components/Search/types';
import useLocalize from '@hooks/useLocalize';
import useResponsiveLayout from '@hooks/useResponsiveLayout';
import useSingleExecution from '@hooks/useSingleExecution';
import useThemeStyles from '@hooks/useThemeStyles';
import Navigation from '@libs/Navigation/Navigation';
import {normalizeQuery} from '@libs/SearchUtils';
+import * as SearchUtils from '@libs/SearchUtils';
import variables from '@styles/variables';
import * as Expensicons from '@src/components/Icon/Expensicons';
import CONST from '@src/CONST';
@@ -17,17 +18,19 @@ import type IconAsset from '@src/types/utils/IconAsset';
import SearchStatusMenuNarrow from './SearchStatusMenuNarrow';
type SearchStatusMenuProps = {
- status: SearchStatus;
+ queryJSON: SearchQueryJSON;
+ isCustomQuery: boolean;
};
type SearchStatusMenuItem = {
title: string;
status: SearchStatus;
icon: IconAsset;
- route: Route;
+ route?: Route;
};
-function SearchStatusMenu({status}: SearchStatusMenuProps) {
+function SearchStatusMenu({queryJSON, isCustomQuery}: SearchStatusMenuProps) {
+ const {status} = queryJSON;
const styles = useThemeStyles();
const {shouldUseNarrowLayout} = useResponsiveLayout();
const {singleExecution} = useSingleExecution();
@@ -62,10 +65,13 @@ function SearchStatusMenu({status}: SearchStatusMenuProps) {
const activeItemIndex = statusMenuItems.findIndex((item) => item.status === status);
if (shouldUseNarrowLayout) {
+ const title = isCustomQuery ? SearchUtils.getSearchHeaderTitle(queryJSON) : undefined;
+
return (
);
}
diff --git a/src/pages/Search/SearchStatusMenuNarrow.tsx b/src/pages/Search/SearchStatusMenuNarrow.tsx
index e80db44ce3dc..1d10dc1dd431 100644
--- a/src/pages/Search/SearchStatusMenuNarrow.tsx
+++ b/src/pages/Search/SearchStatusMenuNarrow.tsx
@@ -1,4 +1,4 @@
-import React, {useRef, useState} from 'react';
+import React, {useMemo, useRef, useState} from 'react';
import {Animated, View} from 'react-native';
import Icon from '@components/Icon';
import PopoverMenu from '@components/PopoverMenu';
@@ -15,9 +15,10 @@ import type {SearchStatusMenuItem} from './SearchStatusMenu';
type SearchStatusMenuNarrowProps = {
statusMenuItems: SearchStatusMenuItem[];
activeItemIndex: number;
+ title?: string;
};
-function SearchStatusMenuNarrow({statusMenuItems, activeItemIndex}: SearchStatusMenuNarrowProps) {
+function SearchStatusMenuNarrow({statusMenuItems, activeItemIndex, title}: SearchStatusMenuNarrowProps) {
const theme = useTheme();
const styles = useThemeStyles();
const {singleExecution} = useSingleExecution();
@@ -29,34 +30,61 @@ function SearchStatusMenuNarrow({statusMenuItems, activeItemIndex}: SearchStatus
const openMenu = () => setIsPopoverVisible(true);
const closeMenu = () => setIsPopoverVisible(false);
- const popoverMenuItems = statusMenuItems.map((item, index) => ({
- text: item.title,
- onSelected: singleExecution(() => Navigation.navigate(item.route)),
- icon: item.icon,
- iconFill: index === activeItemIndex ? theme.iconSuccessFill : theme.icon,
- iconRight: Expensicons.Checkmark,
- shouldShowRightIcon: index === activeItemIndex,
- success: index === activeItemIndex,
- containerStyle: index === activeItemIndex ? [{backgroundColor: theme.border}] : undefined,
- }));
+ const popoverMenuItems = statusMenuItems.map((item, index) => {
+ const isSelected = title ? false : index === activeItemIndex;
+
+ return {
+ text: item.title,
+ onSelected: singleExecution(() => Navigation.navigate(item.route)),
+ icon: item.icon,
+ iconFill: isSelected ? theme.iconSuccessFill : theme.icon,
+ iconRight: Expensicons.Checkmark,
+ shouldShowRightIcon: isSelected,
+ success: isSelected,
+ containerStyle: isSelected ? [{backgroundColor: theme.border}] : undefined,
+ };
+ });
+
+ if (title) {
+ popoverMenuItems.push({
+ text: title,
+ onSelected: closeMenu,
+ icon: Expensicons.Filters,
+ iconFill: theme.iconSuccessFill,
+ success: true,
+ containerStyle: [{backgroundColor: theme.border}],
+ iconRight: Expensicons.Checkmark,
+ shouldShowRightIcon: false,
+ });
+ }
+
+ const menuIcon = useMemo(() => (title ? Expensicons.Filters : popoverMenuItems[activeItemIndex]?.icon ?? Expensicons.Receipt), [activeItemIndex, popoverMenuItems, title]);
+ const menuTitle = useMemo(() => title ?? popoverMenuItems[activeItemIndex]?.text, [activeItemIndex, popoverMenuItems, title]);
+ const titleViewStyles = title ? {...styles.flex1, ...styles.justifyContentCenter} : {};
return (
-
+
{({hovered}) => (
-
+
- {popoverMenuItems[activeItemIndex]?.text}
+
+ {menuTitle}
+