diff --git a/assets/images/product-illustrations/fireworks.svg b/assets/images/product-illustrations/fireworks.svg
new file mode 100644
index 000000000000..e5da607d0909
--- /dev/null
+++ b/assets/images/product-illustrations/fireworks.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/images/product-illustrations/folder-with-papers-and-watch.svg b/assets/images/product-illustrations/folder-with-papers-and-watch.svg
new file mode 100644
index 000000000000..935280fa0eee
--- /dev/null
+++ b/assets/images/product-illustrations/folder-with-papers-and-watch.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/images/product-illustrations/planet-with-mobile-app.svg b/assets/images/product-illustrations/planet-with-mobile-app.svg
new file mode 100644
index 000000000000..8397cce09f19
--- /dev/null
+++ b/assets/images/product-illustrations/planet-with-mobile-app.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/components/BlockingViews/BlockingView.tsx b/src/components/BlockingViews/BlockingView.tsx
index 68d1ff21c87c..ce8f833f08ed 100644
--- a/src/components/BlockingViews/BlockingView.tsx
+++ b/src/components/BlockingViews/BlockingView.tsx
@@ -182,4 +182,5 @@ function BlockingView({
BlockingView.displayName = 'BlockingView';
+export type {BlockingViewProps};
export default BlockingView;
diff --git a/src/components/EmptyStateComponent/GenericEmptyStateComponent.tsx b/src/components/EmptyStateComponent/GenericEmptyStateComponent.tsx
new file mode 100644
index 000000000000..aaf20fd9b04b
--- /dev/null
+++ b/src/components/EmptyStateComponent/GenericEmptyStateComponent.tsx
@@ -0,0 +1,12 @@
+import React from 'react';
+import EmptyStateComponent from '.';
+import type {EmptyStateComponentProps, GenericEmptyStateComponentProps} from './types';
+
+// Only use this component when you need to pass/spread the props in a generic way, as
+// EmptyStateComponent component wouldn't allow it in some cases.
+function GenericEmptyStateComponent(props: GenericEmptyStateComponentProps) {
+ // eslint-disable-next-line react/jsx-props-no-spreading
+ return ;
+}
+
+export default GenericEmptyStateComponent;
diff --git a/src/components/EmptyStateComponent/index.tsx b/src/components/EmptyStateComponent/index.tsx
index a00475785702..88f1e5bdcd12 100644
--- a/src/components/EmptyStateComponent/index.tsx
+++ b/src/components/EmptyStateComponent/index.tsx
@@ -1,7 +1,7 @@
import type {VideoReadyForDisplayEvent} from 'expo-av';
import isEmpty from 'lodash/isEmpty';
import React, {useMemo, useState} from 'react';
-import {View} from 'react-native';
+import {StyleSheet, View} from 'react-native';
import Button from '@components/Button';
import ButtonWithDropdownMenu from '@components/ButtonWithDropdownMenu';
import ImageSVG from '@components/ImageSVG';
@@ -80,7 +80,7 @@ function EmptyStateComponent({
case CONST.EMPTY_STATE_MEDIA.ILLUSTRATION:
return (
);
diff --git a/src/components/EmptyStateComponent/types.ts b/src/components/EmptyStateComponent/types.ts
index 5f62c0eac26f..23601b8087a3 100644
--- a/src/components/EmptyStateComponent/types.ts
+++ b/src/components/EmptyStateComponent/types.ts
@@ -10,6 +10,7 @@ import type IconAsset from '@src/types/utils/IconAsset';
type ValidSkeletons = typeof SearchRowSkeleton | typeof TableRowSkeleton;
type MediaTypes = ValueOf;
+type HeaderMedia = string | IconAsset | DotLottieAnimation;
type EmptyStateButton = {
buttonText?: string;
buttonAction?: () => void;
@@ -24,7 +25,7 @@ type EmptyStateButton = {
>;
};
-type SharedProps = {
+type SharedProps = {
SkeletonComponent?: ValidSkeletons;
title: string;
titleStyles?: StyleProp;
@@ -35,15 +36,15 @@ type SharedProps = {
cardStyles?: StyleProp;
cardContentStyles?: StyleProp;
headerStyles?: StyleProp;
- headerMediaType: T;
+ headerMediaType: TMediaType;
headerContentStyles?: StyleProp;
lottieWebViewStyles?: React.CSSProperties | undefined;
minModalHeight?: number;
subtitleText?: React.ReactNode;
};
-type MediaType = SharedProps & {
- headerMedia: HeaderMedia;
+type MediaType = SharedProps & {
+ headerMedia: THeaderMedia;
};
type VideoProps = MediaType;
@@ -51,6 +52,7 @@ type IllustrationProps = MediaType;
type AnimationProps = MediaType;
type EmptyStateComponentProps = VideoProps | IllustrationProps | AnimationProps;
+type GenericEmptyStateComponentProps = SharedProps & {headerMedia: HeaderMedia};
type VideoLoadedEventType = {
srcElement: {
@@ -59,4 +61,4 @@ type VideoLoadedEventType = {
};
};
-export type {EmptyStateComponentProps, VideoLoadedEventType, EmptyStateButton};
+export type {EmptyStateComponentProps, VideoLoadedEventType, EmptyStateButton, GenericEmptyStateComponentProps, MediaTypes, HeaderMedia};
diff --git a/src/components/Icon/chunks/illustrations.chunk.ts b/src/components/Icon/chunks/illustrations.chunk.ts
index fa28809fadb6..31a3e8c55d01 100644
--- a/src/components/Icon/chunks/illustrations.chunk.ts
+++ b/src/components/Icon/chunks/illustrations.chunk.ts
@@ -49,6 +49,8 @@ import DjBoothReferenceHands from '@assets/images/product-illustrations/dj-booth
import EmptyStateExpenses from '@assets/images/product-illustrations/emptystate__expenses.svg';
import HoldExpense from '@assets/images/product-illustrations/emptystate__holdexpense.svg';
import ReceiptFairy from '@assets/images/product-illustrations/emptystate__receiptfairy.svg';
+import Fireworks from '@assets/images/product-illustrations/fireworks.svg';
+import FolderWithPapersAndWatch from '@assets/images/product-illustrations/folder-with-papers-and-watch.svg';
import FolderWithPapers from '@assets/images/product-illustrations/folder-with-papers.svg';
import Hands from '@assets/images/product-illustrations/home-illustration-hands.svg';
import CardReplacementSuccess from '@assets/images/product-illustrations/illustration__card-replacement-success.svg';
@@ -56,6 +58,7 @@ import MagicCode from '@assets/images/product-illustrations/magic-code.svg';
import ModalHoldOrReject from '@assets/images/product-illustrations/modal-hold-or-reject.svg';
import MushroomTopHat from '@assets/images/product-illustrations/mushroom-top-hat.svg';
import PaymentHands from '@assets/images/product-illustrations/payment-hands.svg';
+import PlanetWithMobileApp from '@assets/images/product-illustrations/planet-with-mobile-app.svg';
import ReceiptsStackedOnPin from '@assets/images/product-illustrations/receipts-stacked-on-pin.svg';
import RocketBlue from '@assets/images/product-illustrations/rocket--blue.svg';
import RocketDude from '@assets/images/product-illustrations/rocket-dude.svg';
@@ -204,6 +207,8 @@ const Illustrations = {
EmptyStateExpenses,
HoldExpense,
ReceiptFairy,
+ Fireworks,
+ FolderWithPapersAndWatch,
FolderWithPapers,
Hands,
CardReplacementSuccess,
@@ -211,6 +216,7 @@ const Illustrations = {
ModalHoldOrReject,
MushroomTopHat,
PaymentHands,
+ PlanetWithMobileApp,
ReceiptsStackedOnPin,
RocketBlue,
RocketDude,
diff --git a/src/components/LHNOptionsList/LHNOptionsList.tsx b/src/components/LHNOptionsList/LHNOptionsList.tsx
index 6a73cfeba010..14436979ab03 100644
--- a/src/components/LHNOptionsList/LHNOptionsList.tsx
+++ b/src/components/LHNOptionsList/LHNOptionsList.tsx
@@ -7,10 +7,10 @@ import type {ReactElement} from 'react';
import React, {memo, useCallback, useContext, useEffect, useMemo, useRef} from 'react';
import {StyleSheet, View} from 'react-native';
import type {OnyxEntry} from 'react-native-onyx';
+import type {BlockingViewProps} from '@components/BlockingViews/BlockingView';
import BlockingView from '@components/BlockingViews/BlockingView';
import Icon from '@components/Icon';
import * as Expensicons from '@components/Icon/Expensicons';
-import LottieAnimations from '@components/LottieAnimations';
import {ScrollOffsetContext} from '@components/ScrollOffsetContextProvider';
import TextBlock from '@components/TextBlock';
import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
@@ -46,6 +46,7 @@ import {isEmptyObject} from '@src/types/utils/EmptyObject';
import OptionRowLHNData from './OptionRowLHNData';
import OptionRowRendererComponent from './OptionRowRendererComponent';
import type {LHNOptionsListProps, RenderItemProps} from './types';
+import useEmptyLHNIllustration from './useEmptyLHNIllustration';
const keyExtractor = (item: Report) => `report_${item.reportID}`;
@@ -79,6 +80,7 @@ function LHNOptionsList({style, contentContainerStyles, data, onSelectRow, optio
const estimatedItemSize = optionMode === CONST.OPTION_MODE.COMPACT ? variables.optionRowHeightCompact : variables.optionRowHeight;
const platform = getPlatform();
const isWebOrDesktop = platform === CONST.PLATFORM.WEB || platform === CONST.PLATFORM.DESKTOP;
+ const emptyLHNIllustration = useEmptyLHNIllustration();
const firstReportIDWithGBRorRBR = useMemo(() => {
const firstReportWithGBRorRBR = data.find((report) => {
@@ -420,9 +422,8 @@ function LHNOptionsList({style, contentContainerStyles, data, onSelectRow, optio
{shouldShowEmptyLHN ? (
{
+ const styles = useThemeStyles();
+
+ return {
+ animation: LottieAnimations.Fireworks,
+ animationStyles: styles.emptyLHNAnimation,
+ animationWebStyle: styles.emptyLHNAnimation,
+ };
+};
+
+export default useEmptyLHNIllustration;
diff --git a/src/components/LHNOptionsList/useEmptyLHNIllustration/index.ts b/src/components/LHNOptionsList/useEmptyLHNIllustration/index.ts
new file mode 100644
index 000000000000..c5c8985dddba
--- /dev/null
+++ b/src/components/LHNOptionsList/useEmptyLHNIllustration/index.ts
@@ -0,0 +1,16 @@
+import {useMemoizedLazyIllustrations} from '@hooks/useLazyAsset';
+import useThemeStyles from '@hooks/useThemeStyles';
+import type UseEmptyLHNIllustration from './types';
+
+const useEmptyLHNIllustration: UseEmptyLHNIllustration = () => {
+ const illustrations = useMemoizedLazyIllustrations(['Fireworks'] as const);
+ const styles = useThemeStyles();
+
+ return {
+ icon: illustrations.Fireworks,
+ iconWidth: styles.emptyStateFireworksStaticIllustration.width,
+ iconHeight: styles.emptyStateFireworksStaticIllustration.height,
+ };
+};
+
+export default useEmptyLHNIllustration;
diff --git a/src/components/LHNOptionsList/useEmptyLHNIllustration/types.ts b/src/components/LHNOptionsList/useEmptyLHNIllustration/types.ts
new file mode 100644
index 000000000000..b32c65b44cae
--- /dev/null
+++ b/src/components/LHNOptionsList/useEmptyLHNIllustration/types.ts
@@ -0,0 +1,5 @@
+import type {BlockingViewProps} from '@components/BlockingViews/BlockingView';
+
+type UseEmptyLHNIllustration = () => Pick;
+
+export default UseEmptyLHNIllustration;
diff --git a/src/libs/SearchUIUtils.ts b/src/libs/SearchUIUtils.ts
index e00127fdb1ef..39e2528750a2 100644
--- a/src/libs/SearchUIUtils.ts
+++ b/src/libs/SearchUIUtils.ts
@@ -2,8 +2,6 @@ import type {TextStyle, ViewStyle} from 'react-native';
import type {OnyxCollection, OnyxEntry} from 'react-native-onyx';
import type {ValueOf} from 'type-fest';
import type {LocaleContextProps, LocalizedTranslate} from '@components/LocaleContextProvider';
-import DotLottieAnimations from '@components/LottieAnimations';
-import type DotLottieAnimation from '@components/LottieAnimations/types';
import type {MenuItemWithLink} from '@components/MenuItemList';
import type {MultiSelectItem} from '@components/Search/FilterDropdowns/MultiSelectPopup';
import type {SingleSelectItem} from '@components/Search/FilterDropdowns/SingleSelectPopup';
@@ -274,7 +272,6 @@ type SearchTypeMenuItem = {
hash: number;
similarSearchHash: number;
emptyState?: {
- headerMedia: DotLottieAnimation;
title: TranslationPaths;
subtitle: TranslationPaths;
buttons?: Array<{
@@ -2136,7 +2133,6 @@ function createTypeMenuSections(
todoSection.menuItems.push({
...suggestedSearches[CONST.SEARCH.SEARCH_KEYS.SUBMIT],
emptyState: {
- headerMedia: DotLottieAnimations.Fireworks,
title: 'search.searchResults.emptySubmitResults.title',
subtitle: 'search.searchResults.emptySubmitResults.subtitle',
buttons:
@@ -2165,7 +2161,6 @@ function createTypeMenuSections(
todoSection.menuItems.push({
...suggestedSearches[CONST.SEARCH.SEARCH_KEYS.APPROVE],
emptyState: {
- headerMedia: DotLottieAnimations.Fireworks,
title: 'search.searchResults.emptyApproveResults.title',
subtitle: 'search.searchResults.emptyApproveResults.subtitle',
},
@@ -2175,7 +2170,6 @@ function createTypeMenuSections(
todoSection.menuItems.push({
...suggestedSearches[CONST.SEARCH.SEARCH_KEYS.PAY],
emptyState: {
- headerMedia: DotLottieAnimations.Fireworks,
title: 'search.searchResults.emptyPayResults.title',
subtitle: 'search.searchResults.emptyPayResults.subtitle',
},
@@ -2185,7 +2179,6 @@ function createTypeMenuSections(
todoSection.menuItems.push({
...suggestedSearches[CONST.SEARCH.SEARCH_KEYS.EXPORT],
emptyState: {
- headerMedia: DotLottieAnimations.Fireworks,
title: 'search.searchResults.emptyExportResults.title',
subtitle: 'search.searchResults.emptyExportResults.subtitle',
},
@@ -2208,7 +2201,6 @@ function createTypeMenuSections(
accountingSection.menuItems.push({
...suggestedSearches[CONST.SEARCH.SEARCH_KEYS.STATEMENTS],
emptyState: {
- headerMedia: DotLottieAnimations.Fireworks,
title: 'search.searchResults.emptyStatementsResults.title',
subtitle: 'search.searchResults.emptyStatementsResults.subtitle',
},
@@ -2218,7 +2210,6 @@ function createTypeMenuSections(
accountingSection.menuItems.push({
...suggestedSearches[CONST.SEARCH.SEARCH_KEYS.UNAPPROVED_CASH],
emptyState: {
- headerMedia: DotLottieAnimations.Fireworks,
title: 'search.searchResults.emptyUnapprovedResults.title',
subtitle: 'search.searchResults.emptyUnapprovedResults.subtitle',
},
@@ -2228,7 +2219,6 @@ function createTypeMenuSections(
accountingSection.menuItems.push({
...suggestedSearches[CONST.SEARCH.SEARCH_KEYS.UNAPPROVED_CARD],
emptyState: {
- headerMedia: DotLottieAnimations.Fireworks,
title: 'search.searchResults.emptyUnapprovedResults.title',
subtitle: 'search.searchResults.emptyUnapprovedResults.subtitle',
},
@@ -2238,7 +2228,6 @@ function createTypeMenuSections(
accountingSection.menuItems.push({
...suggestedSearches[CONST.SEARCH.SEARCH_KEYS.RECONCILIATION],
emptyState: {
- headerMedia: DotLottieAnimations.Fireworks,
title: 'search.searchResults.emptyStatementsResults.title',
subtitle: 'search.searchResults.emptyStatementsResults.subtitle',
},
diff --git a/src/pages/Search/EmptySearchView.tsx b/src/pages/Search/EmptySearchView.tsx
index 909057025aad..f24503361c1c 100644
--- a/src/pages/Search/EmptySearchView.tsx
+++ b/src/pages/Search/EmptySearchView.tsx
@@ -8,11 +8,10 @@ import {Linking, View} from 'react-native';
import type {OnyxCollection, OnyxEntry} from 'react-native-onyx';
import BookTravelButton from '@components/BookTravelButton';
import ConfirmModal from '@components/ConfirmModal';
-import EmptyStateComponent from '@components/EmptyStateComponent';
-import type {EmptyStateButton} from '@components/EmptyStateComponent/types';
+import GenericEmptyStateComponent from '@components/EmptyStateComponent/GenericEmptyStateComponent';
+import type {EmptyStateButton, HeaderMedia, MediaTypes} from '@components/EmptyStateComponent/types';
import type {FeatureListItem} from '@components/FeatureList';
import LottieAnimations from '@components/LottieAnimations';
-import type DotLottieAnimation from '@components/LottieAnimations/types';
import MenuItem from '@components/MenuItem';
import PressableWithSecondaryInteraction from '@components/PressableWithSecondaryInteraction';
import ScrollView from '@components/ScrollView';
@@ -51,6 +50,7 @@ import ROUTES from '@src/ROUTES';
import type {IntroSelected, PersonalDetails, Policy, Report, Transaction} from '@src/types/onyx';
import type {SearchDataTypes} from '@src/types/onyx/SearchResults';
import getEmptyArray from '@src/types/utils/getEmptyArray';
+import useSearchEmptyStateIllustration from './useSearchEmptyStateIllustration';
type EmptySearchViewProps = {
similarSearchHash: number;
@@ -72,7 +72,8 @@ type EmptySearchViewContentProps = EmptySearchViewProps & {
};
type EmptySearchViewItem = {
- headerMedia: DotLottieAnimation;
+ headerMediaType: MediaTypes;
+ headerMedia: HeaderMedia;
title: string;
subtitle?: string;
headerContentStyles: Array>;
@@ -312,14 +313,7 @@ function EmptySearchViewContent({
}, [contextMenuAnchor, handleContextMenuAnchorRef, styles, translate, tripsFeatures]);
// Default 'Folder' lottie animation, along with its background styles
- const defaultViewItemHeader = useMemo(
- () => ({
- headerMedia: LottieAnimations.GenericEmptyState,
- headerContentStyles: [styles.emptyStateFolderWebStyles, StyleUtils.getBackgroundColorStyle(theme.emptyFolderBG)],
- lottieWebViewStyles: {backgroundColor: theme.emptyFolderBG, ...styles.emptyStateFolderWebStyles},
- }),
- [StyleUtils, styles.emptyStateFolderWebStyles, theme.emptyFolderBG],
- );
+ const defaultViewItemHeader = useSearchEmptyStateIllustration();
const content: EmptySearchViewItem = useMemo(() => {
// Begin by going through all of our To-do searches, and returning their empty state
@@ -327,12 +321,9 @@ function EmptySearchViewContent({
for (const menuItem of typeMenuItems) {
if (menuItem.similarSearchHash === similarSearchHash && menuItem.emptyState) {
return {
- headerMedia: menuItem.emptyState.headerMedia,
+ ...defaultViewItemHeader.fireworks,
title: translate(menuItem.emptyState.title),
subtitle: translate(menuItem.emptyState.subtitle),
- headerStyles: StyleUtils.getBackgroundColorStyle(theme.todoBG),
- headerContentStyles: [StyleUtils.getWidthAndHeightStyle(375, 240), StyleUtils.getBackgroundColorStyle(theme.todoBG)],
- lottieWebViewStyles: styles.emptyStateFireworksWebStyles,
buttons: menuItem.emptyState.buttons?.map((button) => ({
...button,
buttonText: translate(button.buttonText),
@@ -349,6 +340,7 @@ function EmptySearchViewContent({
switch (type) {
case CONST.SEARCH.DATA_TYPES.TRIP:
return {
+ headerMediaType: CONST.EMPTY_STATE_MEDIA.ANIMATION,
headerMedia: LottieAnimations.TripsEmptyState,
headerContentStyles: [styles.emptyStateFolderWebStyles, StyleUtils.getBackgroundColorStyle(theme.travelBG)],
title: translate('travel.title'),
@@ -359,14 +351,14 @@ function EmptySearchViewContent({
case CONST.SEARCH.DATA_TYPES.EXPENSE_REPORT:
if (hasResults && (!queryJSON || !isDefaultExpenseReportsQuery(queryJSON) || hasExpenseReports)) {
return {
- ...defaultViewItemHeader,
+ ...defaultViewItemHeader.folder,
title: translate('search.searchResults.emptyResults.title'),
subtitle: translate('search.searchResults.emptyResults.subtitle'),
};
}
if (!hasResults || !hasExpenseReports) {
return {
- ...defaultViewItemHeader,
+ ...defaultViewItemHeader.folder,
title: translate('search.searchResults.emptyReportResults.title'),
subtitle: translate(hasSeenTour ? 'search.searchResults.emptyReportResults.subtitleWithOnlyCreateButton' : 'search.searchResults.emptyReportResults.subtitle'),
buttons: [
@@ -413,14 +405,14 @@ function EmptySearchViewContent({
case CONST.SEARCH.DATA_TYPES.EXPENSE:
if (hasResults && (!queryJSON || !isDefaultExpensesQuery(queryJSON) || hasTransactions)) {
return {
- ...defaultViewItemHeader,
+ ...defaultViewItemHeader.folder,
title: translate('search.searchResults.emptyResults.title'),
subtitle: translate('search.searchResults.emptyResults.subtitle'),
};
}
if (!hasResults || !hasTransactions) {
return {
- ...defaultViewItemHeader,
+ ...defaultViewItemHeader.folder,
title: translate('search.searchResults.emptyExpenseResults.title'),
subtitle: translate(hasSeenTour ? 'search.searchResults.emptyExpenseResults.subtitleWithOnlyCreateButton' : 'search.searchResults.emptyExpenseResults.subtitle'),
buttons: [
@@ -476,14 +468,14 @@ function EmptySearchViewContent({
success: true,
},
],
- ...defaultViewItemHeader,
+ ...defaultViewItemHeader.folder,
};
}
// eslint-disable-next-line no-fallthrough
case CONST.SEARCH.DATA_TYPES.CHAT:
default:
return {
- ...defaultViewItemHeader,
+ ...defaultViewItemHeader.folder,
title: translate('search.searchResults.emptyResults.title'),
subtitle: translate('search.searchResults.emptyResults.subtitle'),
};
@@ -494,9 +486,7 @@ function EmptySearchViewContent({
similarSearchHash,
translate,
StyleUtils,
- theme.todoBG,
theme.travelBG,
- styles.emptyStateFireworksWebStyles,
styles.emptyStateFolderWebStyles,
styles.textAlignLeft,
styles.tripEmptyStateLottieWebView,
@@ -504,7 +494,8 @@ function EmptySearchViewContent({
tryNewDot?.hasBeenAddedToNudgeMigration,
isUserPaidPolicyMember,
hasResults,
- defaultViewItemHeader,
+ defaultViewItemHeader.fireworks,
+ defaultViewItemHeader.folder,
hasSeenTour,
groupPoliciesWithChatEnabled.length,
tripViewChildren,
@@ -523,9 +514,9 @@ function EmptySearchViewContent({
showsVerticalScrollIndicator={false}
contentContainerStyle={[styles.flexGrow1, styles.flexShrink0]}
>
-
{content.children}
-
+
{CreateReportConfirmationModal}
{
+ const theme = useTheme();
+ const StyleUtils = useStyleUtils();
+ const styles = useThemeStyles();
+
+ return {
+ fireworks: {
+ headerMediaType: CONST.EMPTY_STATE_MEDIA.ANIMATION,
+ headerMedia: LottieAnimations.Fireworks,
+ headerStyles: StyleUtils.getBackgroundColorStyle(theme.todoBG),
+ headerContentStyles: [StyleUtils.getWidthAndHeightStyle(375, 240), StyleUtils.getBackgroundColorStyle(theme.todoBG)],
+ lottieWebViewStyles: styles.emptyStateFireworksWebStyles,
+ },
+ folder: {
+ headerMediaType: CONST.EMPTY_STATE_MEDIA.ANIMATION,
+ headerMedia: LottieAnimations.GenericEmptyState,
+ headerContentStyles: [styles.emptyStateFolderWebStyles, StyleUtils.getBackgroundColorStyle(theme.emptyFolderBG)],
+ lottieWebViewStyles: {backgroundColor: theme.emptyFolderBG, ...styles.emptyStateFolderWebStyles},
+ },
+ };
+};
+
+export default useSearchEmptyStateIllustration;
diff --git a/src/pages/Search/useSearchEmptyStateIllustration/index.ts b/src/pages/Search/useSearchEmptyStateIllustration/index.ts
new file mode 100644
index 000000000000..98a5bf37f33a
--- /dev/null
+++ b/src/pages/Search/useSearchEmptyStateIllustration/index.ts
@@ -0,0 +1,30 @@
+import {useMemoizedLazyIllustrations} from '@hooks/useLazyAsset';
+import useStyleUtils from '@hooks/useStyleUtils';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
+import CONST from '@src/CONST';
+import type UseSearchEmptyStateIllustration from './types';
+
+const useSearchEmptyStateIllustration: UseSearchEmptyStateIllustration = () => {
+ const illustrations = useMemoizedLazyIllustrations(['Fireworks', 'FolderWithPapersAndWatch'] as const);
+ const theme = useTheme();
+ const StyleUtils = useStyleUtils();
+ const styles = useThemeStyles();
+
+ return {
+ fireworks: {
+ headerMediaType: CONST.EMPTY_STATE_MEDIA.ILLUSTRATION,
+ headerMedia: illustrations.Fireworks,
+ headerStyles: StyleUtils.getBackgroundColorStyle(theme.todoBG),
+ headerContentStyles: [styles.emptyStateFireworksStaticIllustration, StyleUtils.getBackgroundColorStyle(theme.todoBG)],
+ },
+ folder: {
+ headerMediaType: CONST.EMPTY_STATE_MEDIA.ILLUSTRATION,
+ headerMedia: illustrations.FolderWithPapersAndWatch,
+ headerStyles: StyleUtils.getBackgroundColorStyle(theme.emptyFolderBG),
+ headerContentStyles: [styles.emptyStateFolderWebStyles, styles.emptyStateFolderStaticIllustration, StyleUtils.getBackgroundColorStyle(theme.emptyFolderBG)],
+ },
+ };
+};
+
+export default useSearchEmptyStateIllustration;
diff --git a/src/pages/Search/useSearchEmptyStateIllustration/types.ts b/src/pages/Search/useSearchEmptyStateIllustration/types.ts
new file mode 100644
index 000000000000..967d77ee74a9
--- /dev/null
+++ b/src/pages/Search/useSearchEmptyStateIllustration/types.ts
@@ -0,0 +1,8 @@
+import type {EmptySearchViewItem} from '@pages/Search/EmptySearchView';
+
+type UseSearchEmptyStateIllustration = () => Record<
+ 'fireworks' | 'folder',
+ Pick
+>;
+
+export default UseSearchEmptyStateIllustration;
diff --git a/src/components/WorkspacesEmptyStateComponent.tsx b/src/pages/workspace/WorkspacesEmptyStateComponent.tsx
similarity index 77%
rename from src/components/WorkspacesEmptyStateComponent.tsx
rename to src/pages/workspace/WorkspacesEmptyStateComponent.tsx
index a20cb77e2271..3a5755c9cca3 100644
--- a/src/components/WorkspacesEmptyStateComponent.tsx
+++ b/src/pages/workspace/WorkspacesEmptyStateComponent.tsx
@@ -1,4 +1,6 @@
import React from 'react';
+import GenericEmptyStateComponent from '@components/EmptyStateComponent/GenericEmptyStateComponent';
+import WorkspaceRowSkeleton from '@components/Skeletons/WorkspaceRowSkeleton';
import useLocalize from '@hooks/useLocalize';
import usePreferredPolicy from '@hooks/usePreferredPolicy';
import useStyleUtils from '@hooks/useStyleUtils';
@@ -7,29 +9,25 @@ import interceptAnonymousUser from '@libs/interceptAnonymousUser';
import Navigation from '@libs/Navigation/Navigation';
import colors from '@styles/theme/colors';
import variables from '@styles/variables';
-import CONST from '@src/CONST';
import ROUTES from '@src/ROUTES';
-import EmptyStateComponent from './EmptyStateComponent';
-import LottieAnimations from './LottieAnimations';
-import WorkspaceRowSkeleton from './Skeletons/WorkspaceRowSkeleton';
+import useWorkspacesEmptyStateIllustration from './useWorkspacesEmptyStateIllustration';
function WorkspacesEmptyStateComponent() {
const styles = useThemeStyles();
const {translate} = useLocalize();
const StyleUtils = useStyleUtils();
const {isRestrictedPolicyCreation} = usePreferredPolicy();
+ const illustration = useWorkspacesEmptyStateIllustration();
return (
- {
+ const styles = useThemeStyles();
+
+ return {
+ headerMediaType: CONST.EMPTY_STATE_MEDIA.ANIMATION,
+ headerMedia: LottieAnimations.WorkspacePlanet,
+ headerContentStyles: styles.emptyWorkspaceListLottieIllustrationStyle,
+ lottieWebViewStyles: styles.emptyWorkspaceListLottieIllustrationStyle,
+ };
+};
+
+export default useWorkspacesEmptyStateIllustration;
diff --git a/src/pages/workspace/useWorkspacesEmptyStateIllustration/index.ts b/src/pages/workspace/useWorkspacesEmptyStateIllustration/index.ts
new file mode 100644
index 000000000000..7f2dc7caa4dc
--- /dev/null
+++ b/src/pages/workspace/useWorkspacesEmptyStateIllustration/index.ts
@@ -0,0 +1,17 @@
+import {useMemoizedLazyIllustrations} from '@hooks/useLazyAsset';
+import useThemeStyles from '@hooks/useThemeStyles';
+import CONST from '@src/CONST';
+import type UseWorkspacesEmptyStateIllustration from './types';
+
+const useWorkspacesEmptyStateIllustration: UseWorkspacesEmptyStateIllustration = () => {
+ const illustrations = useMemoizedLazyIllustrations(['PlanetWithMobileApp'] as const);
+ const styles = useThemeStyles();
+
+ return {
+ headerMediaType: CONST.EMPTY_STATE_MEDIA.ILLUSTRATION,
+ headerMedia: illustrations.PlanetWithMobileApp,
+ headerContentStyles: styles.emptyWorkspaceListStaticIllustrationStyle,
+ };
+};
+
+export default useWorkspacesEmptyStateIllustration;
diff --git a/src/pages/workspace/useWorkspacesEmptyStateIllustration/types.ts b/src/pages/workspace/useWorkspacesEmptyStateIllustration/types.ts
new file mode 100644
index 000000000000..7be58885e00f
--- /dev/null
+++ b/src/pages/workspace/useWorkspacesEmptyStateIllustration/types.ts
@@ -0,0 +1,5 @@
+import type {EmptyStateComponentProps} from '@components/EmptyStateComponent/types';
+
+type UseWorkspacesEmptyStateIllustration = () => Pick;
+
+export default UseWorkspacesEmptyStateIllustration;
diff --git a/src/styles/index.ts b/src/styles/index.ts
index 815536b71f8e..a8e22b665bc0 100644
--- a/src/styles/index.ts
+++ b/src/styles/index.ts
@@ -1871,11 +1871,15 @@ const staticStyles = (theme: ThemeColors) =>
marginBottom: -20,
},
- emptyWorkspaceListIllustrationStyle: {
+ emptyWorkspaceListLottieIllustrationStyle: {
marginTop: 12,
marginBottom: -20,
height: '100%',
},
+ emptyWorkspaceListStaticIllustrationStyle: {
+ width: 203,
+ height: 166,
+ },
appContent: {
backgroundColor: theme.appBG,
@@ -5163,6 +5167,11 @@ const staticStyles = (theme: ThemeColors) =>
...display.dFlex,
},
+ emptyStateFolderStaticIllustration: {
+ width: 184,
+ height: 112,
+ },
+
emptyStateFireworksWebStyles: {
width: 250,
...flex.alignItemsCenter,
@@ -5170,6 +5179,11 @@ const staticStyles = (theme: ThemeColors) =>
...display.dFlex,
},
+ emptyStateFireworksStaticIllustration: {
+ width: 164,
+ height: 148,
+ },
+
tripEmptyStateLottieWebView: {
width: 335,
height: 220,