-
-
-
{t("home.quick_links.empty")}
-
+
+
);
};
diff --git a/apps/web/core/components/home/widgets/empty-states/recents.tsx b/apps/web/core/components/home/widgets/empty-states/recents.tsx
index 4839e9bfa9..bca5bf603c 100644
--- a/apps/web/core/components/home/widgets/empty-states/recents.tsx
+++ b/apps/web/core/components/home/widgets/empty-states/recents.tsx
@@ -1,41 +1,40 @@
-import { History } from "lucide-react";
import { useTranslation } from "@plane/i18n";
-import { PageIcon, ProjectIcon, WorkItemsIcon } from "@plane/propel/icons";
+import { EmptyStateCompact } from "@plane/propel/empty-state";
+import type { CompactAssetType } from "@plane/propel/empty-state";
-const getDisplayContent = (type: string) => {
+const getDisplayContent = (type: string): { assetKey: CompactAssetType; text: string } => {
switch (type) {
case "project":
return {
- icon:
,
+ assetKey: "project",
text: "home.recents.empty.project",
};
case "page":
return {
- icon:
,
+ assetKey: "note",
text: "home.recents.empty.page",
};
case "issue":
return {
- icon:
,
+ assetKey: "work-item",
text: "home.recents.empty.issue",
};
default:
return {
- icon:
,
+ assetKey: "work-item",
text: "home.recents.empty.default",
};
}
};
+
export const RecentsEmptyState = ({ type }: { type: string }) => {
const { t } = useTranslation();
- const { icon, text } = getDisplayContent(type);
+ const { assetKey, text } = getDisplayContent(type);
return (
-
-
+
+
);
};
diff --git a/apps/web/core/components/home/widgets/empty-states/stickies.tsx b/apps/web/core/components/home/widgets/empty-states/stickies.tsx
index 5a639ceef4..37a3299dac 100644
--- a/apps/web/core/components/home/widgets/empty-states/stickies.tsx
+++ b/apps/web/core/components/home/widgets/empty-states/stickies.tsx
@@ -1,15 +1,11 @@
-// plane ui
import { useTranslation } from "@plane/i18n";
-import { RecentStickyIcon } from "@plane/propel/icons";
+import { EmptyStateCompact } from "@plane/propel/empty-state";
export const StickiesEmptyState = () => {
const { t } = useTranslation();
return (
-
-
-
-
{t("stickies.empty_state.simple")}
-
+
+
);
};
diff --git a/apps/web/core/components/inbox/root.tsx b/apps/web/core/components/inbox/root.tsx
index 4327c3aefa..a8660ecce3 100644
--- a/apps/web/core/components/inbox/root.tsx
+++ b/apps/web/core/components/inbox/root.tsx
@@ -4,11 +4,11 @@ import { observer } from "mobx-react";
import { PanelLeft } from "lucide-react";
// plane imports
import { useTranslation } from "@plane/i18n";
+import { EmptyStateCompact } from "@plane/propel/empty-state";
import { IntakeIcon } from "@plane/propel/icons";
import { EInboxIssueCurrentTab } from "@plane/types";
import { cn } from "@plane/utils";
// components
-import { SimpleEmptyState } from "@/components/empty-state/simple-empty-state-root";
import { InboxContentRoot } from "@/components/inbox/content";
import { InboxSidebar } from "@/components/inbox/sidebar";
import { InboxLayoutLoader } from "@/components/ui/loader/layouts/project-inbox/inbox-layout-loader";
@@ -101,9 +101,7 @@ export const InboxIssueRoot: FC
= observer((props) => {
inboxIssueId={inboxIssueId.toString()}
/>
) : (
-
-
-
+
)}
>
diff --git a/apps/web/core/components/inbox/sidebar/root.tsx b/apps/web/core/components/inbox/sidebar/root.tsx
index b76c638342..88b59dc62a 100644
--- a/apps/web/core/components/inbox/sidebar/root.tsx
+++ b/apps/web/core/components/inbox/sidebar/root.tsx
@@ -4,20 +4,19 @@ import type { FC } from "react";
import { useCallback, useEffect, useRef, useState } from "react";
import { observer } from "mobx-react";
import { useTranslation } from "@plane/i18n";
+import { EmptyStateDetailed } from "@plane/propel/empty-state";
import type { TInboxIssueCurrentTab } from "@plane/types";
import { EInboxIssueCurrentTab } from "@plane/types";
// plane imports
import { Header, Loader, EHeaderVariant } from "@plane/ui";
import { cn } from "@plane/utils";
// components
-import { SimpleEmptyState } from "@/components/empty-state/simple-empty-state-root";
import { InboxSidebarLoader } from "@/components/ui/loader/layouts/project-inbox/inbox-sidebar-loader";
// hooks
import { useProject } from "@/hooks/store/use-project";
import { useProjectInbox } from "@/hooks/store/use-project-inbox";
import { useAppRouter } from "@/hooks/use-app-router";
import { useIntersectionObserver } from "@/hooks/use-intersection-observer";
-import { useResolvedAssetPath } from "@/hooks/use-resolved-asset-path";
// local imports
import { FiltersRoot } from "../inbox-filter";
import { InboxIssueAppliedFilters } from "../inbox-filter/applied-filters/root";
@@ -62,11 +61,6 @@ export const InboxSidebar: FC
= observer((props) => {
getAppliedFiltersCount,
} = useProjectInbox();
// derived values
- const sidebarAssetPath = useResolvedAssetPath({ basePath: "/empty-state/intake/intake-issue" });
- const sidebarFilterAssetPath = useResolvedAssetPath({
- basePath: "/empty-state/intake/filter-issue",
- });
-
const fetchNextPages = useCallback(() => {
if (!workspaceSlug || !projectId) return;
fetchInboxPaginationIssues(workspaceSlug.toString(), projectId.toString());
@@ -141,22 +135,33 @@ export const InboxSidebar: FC = observer((props) => {
) : (
{getAppliedFiltersCount > 0 ? (
-
) : currentTab === EInboxIssueCurrentTab.OPEN ? (
- router.push(`/${workspaceSlug}/projects/${projectId}/intake`),
+ variant: "primary",
+ },
+ ]}
/>
) : (
-
)}
diff --git a/apps/web/core/components/issues/issue-layouts/empty-states/cycle.tsx b/apps/web/core/components/issues/issue-layouts/empty-states/cycle.tsx
index 30a82d476c..c7ae0e89f5 100644
--- a/apps/web/core/components/issues/issue-layouts/empty-states/cycle.tsx
+++ b/apps/web/core/components/issues/issue-layouts/empty-states/cycle.tsx
@@ -7,19 +7,18 @@ import { useParams } from "next/navigation";
// plane imports
import { EUserPermissionsLevel, WORK_ITEM_TRACKER_ELEMENTS } from "@plane/constants";
import { useTranslation } from "@plane/i18n";
+import { EmptyStateDetailed } from "@plane/propel/empty-state";
import { TOAST_TYPE, setToast } from "@plane/propel/toast";
import type { ISearchIssueResponse } from "@plane/types";
import { EIssuesStoreType, EUserProjectRoles } from "@plane/types";
// components
import { ExistingIssuesListModal } from "@/components/core/modals/existing-issues-list-modal";
-import { DetailedEmptyState } from "@/components/empty-state/detailed-empty-state-root";
import { captureClick } from "@/helpers/event-tracker.helper";
import { useCommandPalette } from "@/hooks/store/use-command-palette";
import { useCycle } from "@/hooks/store/use-cycle";
import { useIssues } from "@/hooks/store/use-issues";
import { useUserPermissions } from "@/hooks/store/user";
import { useWorkItemFilterInstance } from "@/hooks/store/work-item-filters/use-work-item-filter-instance";
-import { useResolvedAssetPath } from "@/hooks/use-resolved-asset-path";
export const CycleEmptyState: React.FC = observer(() => {
// router
@@ -33,31 +32,18 @@ export const CycleEmptyState: React.FC = observer(() => {
const { t } = useTranslation();
// store hooks
const { getCycleById } = useCycle();
- const { issues, issuesFilter } = useIssues(EIssuesStoreType.CYCLE);
+ const { issues } = useIssues(EIssuesStoreType.CYCLE);
const { toggleCreateIssueModal } = useCommandPalette();
const { allowPermissions } = useUserPermissions();
// derived values
const cycleWorkItemFilter = cycleId ? useWorkItemFilterInstance(EIssuesStoreType.CYCLE, cycleId) : undefined;
const cycleDetails = cycleId ? getCycleById(cycleId) : undefined;
- const activeLayout = issuesFilter?.issueFilters?.displayFilters?.layout;
const isCompletedCycleSnapshotAvailable = !isEmpty(cycleDetails?.progress_snapshot ?? {});
const isCompletedAndEmpty = isCompletedCycleSnapshotAvailable || cycleDetails?.status?.toLowerCase() === "completed";
- const additionalPath = activeLayout ?? "list";
const canPerformEmptyStateActions = allowPermissions(
[EUserProjectRoles.ADMIN, EUserProjectRoles.MEMBER],
EUserPermissionsLevel.PROJECT
);
- const emptyFilterResolvedPath = useResolvedAssetPath({
- basePath: "/empty-state/empty-filters/",
- additionalPath: additionalPath,
- });
- const noIssueResolvedPath = useResolvedAssetPath({
- basePath: "/empty-state/cycle-issues/",
- additionalPath: additionalPath,
- });
- const completedNoIssuesResolvedPath = useResolvedAssetPath({
- basePath: "/empty-state/cycle/completed-no-issues",
- });
const handleAddIssuesToCycle = async (data: ISearchIssueResponse[]) => {
if (!workspaceSlug || !projectId || !cycleId) return;
@@ -94,39 +80,50 @@ export const CycleEmptyState: React.FC = observer(() => {
/>
{isCompletedAndEmpty ? (
-
) : cycleWorkItemFilter?.hasActiveFilters ? (
-
) : (
- {
- captureClick({ elementName: WORK_ITEM_TRACKER_ELEMENTS.EMPTY_STATE_ADD_BUTTON.CYCLE });
- toggleCreateIssueModal(true, EIssuesStoreType.CYCLE);
+ {
+ captureClick({ elementName: WORK_ITEM_TRACKER_ELEMENTS.EMPTY_STATE_ADD_BUTTON.CYCLE });
+ toggleCreateIssueModal(true, EIssuesStoreType.CYCLE);
+ },
+ disabled: !canPerformEmptyStateActions,
+ variant: "primary",
+ "data-ph-element": WORK_ITEM_TRACKER_ELEMENTS.EMPTY_STATE_ADD_BUTTON.CYCLE,
},
- disabled: !canPerformEmptyStateActions,
- }}
- secondaryButton={{
- text: t("project_cycles.empty_state.no_issues.secondary_button.text"),
- onClick: () => setCycleIssuesListModal(true),
- disabled: !canPerformEmptyStateActions,
- }}
+ {
+ label: t("project.cycle_work_items.cta_secondary"),
+ onClick: () => setCycleIssuesListModal(true),
+ disabled: !canPerformEmptyStateActions,
+ variant: "outline-primary",
+ "data-ph-element": WORK_ITEM_TRACKER_ELEMENTS.EMPTY_STATE_ADD_BUTTON.CYCLE,
+ },
+ ]}
/>
)}
diff --git a/apps/web/core/components/issues/issue-layouts/empty-states/global-view.tsx b/apps/web/core/components/issues/issue-layouts/empty-states/global-view.tsx
index 00935f1cd1..e8ded291e1 100644
--- a/apps/web/core/components/issues/issue-layouts/empty-states/global-view.tsx
+++ b/apps/web/core/components/issues/issue-layouts/empty-states/global-view.tsx
@@ -1,21 +1,16 @@
import { observer } from "mobx-react";
-import { useParams } from "next/navigation";
// plane imports
import { EUserPermissionsLevel, WORK_ITEM_TRACKER_ELEMENTS } from "@plane/constants";
import { useTranslation } from "@plane/i18n";
+import { EmptyStateDetailed } from "@plane/propel/empty-state";
import { EIssuesStoreType, EUserWorkspaceRoles } from "@plane/types";
-// components
-import { ComicBoxButton } from "@/components/empty-state/comic-box-button";
-import { DetailedEmptyState } from "@/components/empty-state/detailed-empty-state-root";
// hooks
import { captureClick } from "@/helpers/event-tracker.helper";
import { useCommandPalette } from "@/hooks/store/use-command-palette";
import { useProject } from "@/hooks/store/use-project";
import { useUserPermissions } from "@/hooks/store/user";
-import { useResolvedAssetPath } from "@/hooks/use-resolved-asset-path";
export const GlobalViewEmptyState: React.FC = observer(() => {
- const { globalViewId } = useParams();
// plane imports
const { t } = useTranslation();
// store hooks
@@ -27,56 +22,46 @@ export const GlobalViewEmptyState: React.FC = observer(() => {
[EUserWorkspaceRoles.ADMIN, EUserWorkspaceRoles.MEMBER],
EUserPermissionsLevel.WORKSPACE
);
- const isDefaultView = ["all-issues", "assigned", "created", "subscribed"].includes(globalViewId?.toString() ?? "");
- const currentView = isDefaultView && globalViewId ? globalViewId : "custom-view";
- const resolvedCurrentView = currentView?.toString();
- const noProjectResolvedPath = useResolvedAssetPath({ basePath: "/empty-state/onboarding/projects" });
- const globalViewsResolvedPath = useResolvedAssetPath({
- basePath: "/empty-state/all-issues/",
- additionalPath: resolvedCurrentView,
- });
if (workspaceProjectIds?.length === 0) {
return (
- {
+ assetKey="project"
+ assetClassName="size-40"
+ actions={[
+ {
+ label: t("workspace_projects.empty_state.no_projects.primary_button.text"),
+ onClick: () => {
toggleCreateProjectModal(true);
captureClick({ elementName: WORK_ITEM_TRACKER_ELEMENTS.EMPTY_STATE_ADD_BUTTON.GLOBAL_VIEW });
- }}
- disabled={!hasMemberLevelPermission}
- />
- }
+ },
+ disabled: !hasMemberLevelPermission,
+ variant: "primary",
+ },
+ ]}
/>
);
}
return (
- {
- captureClick({ elementName: WORK_ITEM_TRACKER_ELEMENTS.EMPTY_STATE_ADD_BUTTON.GLOBAL_VIEW });
- toggleCreateIssueModal(true, EIssuesStoreType.PROJECT);
- },
- disabled: !hasMemberLevelPermission,
- }
- : undefined
- }
+ {
+ captureClick({ elementName: WORK_ITEM_TRACKER_ELEMENTS.EMPTY_STATE_ADD_BUTTON.GLOBAL_VIEW });
+ toggleCreateIssueModal(true, EIssuesStoreType.PROJECT);
+ },
+ disabled: !hasMemberLevelPermission,
+ variant: "primary",
+ },
+ ]}
/>
);
});
diff --git a/apps/web/core/components/issues/issue-layouts/empty-states/module.tsx b/apps/web/core/components/issues/issue-layouts/empty-states/module.tsx
index 2510f5b5d4..f884de82d6 100644
--- a/apps/web/core/components/issues/issue-layouts/empty-states/module.tsx
+++ b/apps/web/core/components/issues/issue-layouts/empty-states/module.tsx
@@ -6,19 +6,18 @@ import { useParams } from "next/navigation";
// plane imports
import { EUserPermissionsLevel, WORK_ITEM_TRACKER_ELEMENTS } from "@plane/constants";
import { useTranslation } from "@plane/i18n";
+import { EmptyStateDetailed } from "@plane/propel/empty-state";
import { TOAST_TYPE, setToast } from "@plane/propel/toast";
import type { ISearchIssueResponse } from "@plane/types";
import { EIssuesStoreType, EUserProjectRoles } from "@plane/types";
// components
import { ExistingIssuesListModal } from "@/components/core/modals/existing-issues-list-modal";
-import { DetailedEmptyState } from "@/components/empty-state/detailed-empty-state-root";
import { captureClick } from "@/helpers/event-tracker.helper";
// hooks
import { useCommandPalette } from "@/hooks/store/use-command-palette";
import { useIssues } from "@/hooks/store/use-issues";
import { useUserPermissions } from "@/hooks/store/user";
import { useWorkItemFilterInstance } from "@/hooks/store/work-item-filters/use-work-item-filter-instance";
-import { useResolvedAssetPath } from "@/hooks/use-resolved-asset-path";
export const ModuleEmptyState: React.FC = observer(() => {
// router
@@ -31,25 +30,15 @@ export const ModuleEmptyState: React.FC = observer(() => {
// plane hooks
const { t } = useTranslation();
// store hooks
- const { issues, issuesFilter } = useIssues(EIssuesStoreType.MODULE);
+ const { issues } = useIssues(EIssuesStoreType.MODULE);
const { toggleCreateIssueModal } = useCommandPalette();
const { allowPermissions } = useUserPermissions();
// derived values
const moduleWorkItemFilter = moduleId ? useWorkItemFilterInstance(EIssuesStoreType.MODULE, moduleId) : undefined;
- const activeLayout = issuesFilter?.issueFilters?.displayFilters?.layout;
- const additionalPath = activeLayout ?? "list";
const canPerformEmptyStateActions = allowPermissions(
[EUserProjectRoles.ADMIN, EUserProjectRoles.MEMBER],
EUserPermissionsLevel.PROJECT
);
- const emptyFilterResolvedPath = useResolvedAssetPath({
- basePath: "/empty-state/empty-filters/",
- additionalPath: additionalPath,
- });
- const moduleIssuesResolvedPath = useResolvedAssetPath({
- basePath: "/empty-state/module-issues/",
- additionalPath: additionalPath,
- });
const handleAddIssuesToModule = async (data: ISearchIssueResponse[]) => {
if (!workspaceSlug || !projectId || !moduleId) return;
@@ -85,33 +74,41 @@ export const ModuleEmptyState: React.FC = observer(() => {
/>
{moduleWorkItemFilter?.hasActiveFilters ? (
-
) : (
- {
- captureClick({ elementName: WORK_ITEM_TRACKER_ELEMENTS.EMPTY_STATE_ADD_BUTTON.MODULE });
- toggleCreateIssueModal(true, EIssuesStoreType.MODULE);
+ {
+ captureClick({ elementName: WORK_ITEM_TRACKER_ELEMENTS.EMPTY_STATE_ADD_BUTTON.MODULE });
+ toggleCreateIssueModal(true, EIssuesStoreType.MODULE);
+ },
+ disabled: !canPerformEmptyStateActions,
+ variant: "primary",
},
- disabled: !canPerformEmptyStateActions,
- }}
- secondaryButton={{
- text: t("project_module.empty_state.no_issues.secondary_button.text"),
- onClick: () => setModuleIssuesListModal(true),
- disabled: !canPerformEmptyStateActions,
- }}
+ {
+ label: t("project.module_work_items.cta_secondary"),
+ onClick: () => setModuleIssuesListModal(true),
+ disabled: !canPerformEmptyStateActions,
+ variant: "outline-primary",
+ },
+ ]}
/>
)}
diff --git a/apps/web/core/components/issues/issue-layouts/empty-states/project-issues.tsx b/apps/web/core/components/issues/issue-layouts/empty-states/project-issues.tsx
index c8a776850e..dd52019d6b 100644
--- a/apps/web/core/components/issues/issue-layouts/empty-states/project-issues.tsx
+++ b/apps/web/core/components/issues/issue-layouts/empty-states/project-issues.tsx
@@ -3,17 +3,14 @@ import { useParams } from "next/navigation";
// plane imports
import { EUserPermissionsLevel, WORK_ITEM_TRACKER_ELEMENTS } from "@plane/constants";
import { useTranslation } from "@plane/i18n";
+import { EmptyStateDetailed } from "@plane/propel/empty-state";
import { EIssuesStoreType, EUserProjectRoles } from "@plane/types";
// components
-import { ComicBoxButton } from "@/components/empty-state/comic-box-button";
-import { DetailedEmptyState } from "@/components/empty-state/detailed-empty-state-root";
import { captureClick } from "@/helpers/event-tracker.helper";
// hooks
import { useCommandPalette } from "@/hooks/store/use-command-palette";
-import { useIssues } from "@/hooks/store/use-issues";
import { useUserPermissions } from "@/hooks/store/user";
import { useWorkItemFilterInstance } from "@/hooks/store/work-item-filters/use-work-item-filter-instance";
-import { useResolvedAssetPath } from "@/hooks/use-resolved-asset-path";
export const ProjectEmptyState: React.FC = observer(() => {
// router
@@ -23,53 +20,47 @@ export const ProjectEmptyState: React.FC = observer(() => {
const { t } = useTranslation();
// store hooks
const { toggleCreateIssueModal } = useCommandPalette();
- const { issuesFilter } = useIssues(EIssuesStoreType.PROJECT);
const { allowPermissions } = useUserPermissions();
// derived values
const projectWorkItemFilter = projectId ? useWorkItemFilterInstance(EIssuesStoreType.PROJECT, projectId) : undefined;
- const activeLayout = issuesFilter?.issueFilters?.displayFilters?.layout;
- const additionalPath = projectWorkItemFilter?.hasActiveFilters ? (activeLayout ?? "list") : undefined;
+
const canPerformEmptyStateActions = allowPermissions(
[EUserProjectRoles.ADMIN, EUserProjectRoles.MEMBER],
EUserPermissionsLevel.PROJECT
);
- const emptyFilterResolvedPath = useResolvedAssetPath({
- basePath: "/empty-state/empty-filters/",
- additionalPath: additionalPath,
- });
- const projectIssuesResolvedPath = useResolvedAssetPath({
- basePath: "/empty-state/onboarding/issues",
- });
return (
{projectWorkItemFilter?.hasActiveFilters ? (
-
) : (
- {
+ {
captureClick({ elementName: WORK_ITEM_TRACKER_ELEMENTS.EMPTY_STATE_ADD_BUTTON.WORK_ITEMS });
toggleCreateIssueModal(true, EIssuesStoreType.PROJECT);
- }}
- disabled={!canPerformEmptyStateActions}
- />
- }
+ },
+ disabled: !canPerformEmptyStateActions,
+ variant: "primary",
+ },
+ ]}
/>
)}
diff --git a/apps/web/core/components/issues/issue-layouts/empty-states/project-view.tsx b/apps/web/core/components/issues/issue-layouts/empty-states/project-view.tsx
index 6b03a61e0f..1652631776 100644
--- a/apps/web/core/components/issues/issue-layouts/empty-states/project-view.tsx
+++ b/apps/web/core/components/issues/issue-layouts/empty-states/project-view.tsx
@@ -1,15 +1,12 @@
import { observer } from "mobx-react";
-import { PlusIcon } from "lucide-react";
// components
import { EUserPermissions, EUserPermissionsLevel, WORK_ITEM_TRACKER_ELEMENTS } from "@plane/constants";
+import { EmptyStateDetailed } from "@plane/propel/empty-state";
import { EIssuesStoreType } from "@plane/types";
-import { EmptyState } from "@/components/common/empty-state";
import { captureClick } from "@/helpers/event-tracker.helper";
// hooks
import { useCommandPalette } from "@/hooks/store/use-command-palette";
import { useUserPermissions } from "@/hooks/store/user";
-// assets
-import emptyIssue from "@/public/empty-state/issue.svg";
export const ProjectViewEmptyState: React.FC = observer(() => {
// store hooks
@@ -23,24 +20,22 @@ export const ProjectViewEmptyState: React.FC = observer(() => {
);
return (
-
- ,
- onClick: () => {
- captureClick({ elementName: WORK_ITEM_TRACKER_ELEMENTS.EMPTY_STATE_ADD_BUTTON.PROJECT_VIEW });
- toggleCreateIssueModal(true, EIssuesStoreType.PROJECT_VIEW);
- },
- }
- : undefined
- }
- />
-
+ // TODO: Add translation
+ {
+ captureClick({ elementName: WORK_ITEM_TRACKER_ELEMENTS.EMPTY_STATE_ADD_BUTTON.PROJECT_VIEW });
+ toggleCreateIssueModal(true, EIssuesStoreType.PROJECT_VIEW);
+ },
+ disabled: !isCreatingIssueAllowed,
+ variant: "primary",
+ },
+ ]}
+ />
);
});
diff --git a/apps/web/core/components/issues/workspace-draft/empty-state.tsx b/apps/web/core/components/issues/workspace-draft/empty-state.tsx
index 4d6a195a51..89ff7cb141 100644
--- a/apps/web/core/components/issues/workspace-draft/empty-state.tsx
+++ b/apps/web/core/components/issues/workspace-draft/empty-state.tsx
@@ -6,12 +6,11 @@ import { Fragment, useState } from "react";
import { observer } from "mobx-react";
import { EUserPermissionsLevel } from "@plane/constants";
import { useTranslation } from "@plane/i18n";
+import { EmptyStateDetailed } from "@plane/propel/empty-state";
import { EIssuesStoreType, EUserWorkspaceRoles } from "@plane/types";
-import { DetailedEmptyState } from "@/components/empty-state/detailed-empty-state-root";
import { CreateUpdateIssueModal } from "@/components/issues/issue-modal/modal";
// constants
import { useUserPermissions } from "@/hooks/store/user";
-import { useResolvedAssetPath } from "@/hooks/use-resolved-asset-path";
export const WorkspaceDraftEmptyState: FC = observer(() => {
// state
@@ -24,7 +23,6 @@ export const WorkspaceDraftEmptyState: FC = observer(() => {
[EUserWorkspaceRoles.ADMIN, EUserWorkspaceRoles.MEMBER],
EUserPermissionsLevel.WORKSPACE
);
- const resolvedPath = useResolvedAssetPath({ basePath: "/empty-state/onboarding/cycles" });
return (
@@ -35,17 +33,21 @@ export const WorkspaceDraftEmptyState: FC = observer(() => {
isDraft
/>
- {
- setIsDraftIssueModalOpen(true);
+ {
+ setIsDraftIssueModalOpen(true);
+ },
+ disabled: !canPerformEmptyStateActions,
+ variant: "primary",
},
- disabled: !canPerformEmptyStateActions,
- }}
+ ]}
/>
diff --git a/apps/web/core/components/issues/workspace-draft/root.tsx b/apps/web/core/components/issues/workspace-draft/root.tsx
index cf74383a97..636b898e39 100644
--- a/apps/web/core/components/issues/workspace-draft/root.tsx
+++ b/apps/web/core/components/issues/workspace-draft/root.tsx
@@ -7,11 +7,10 @@ import useSWR from "swr";
// plane imports
import { EUserPermissionsLevel, EDraftIssuePaginationType, PROJECT_TRACKER_ELEMENTS } from "@plane/constants";
import { useTranslation } from "@plane/i18n";
+import { EmptyStateDetailed } from "@plane/propel/empty-state";
import { EUserWorkspaceRoles } from "@plane/types";
// components
import { cn } from "@plane/utils";
-import { ComicBoxButton } from "@/components/empty-state/comic-box-button";
-import { DetailedEmptyState } from "@/components/empty-state/detailed-empty-state-root";
import { captureClick } from "@/helpers/event-tracker.helper";
// constants
@@ -70,23 +69,22 @@ export const WorkspaceDraftIssuesRoot: FC = observer(
if (workspaceProjectIds?.length === 0)
return (
- {
+ assetKey="project"
+ assetClassName="size-40"
+ actions={[
+ {
+ label: t("workspace_projects.empty_state.no_projects.primary_button.text"),
+ onClick: () => {
toggleCreateProjectModal(true);
captureClick({ elementName: PROJECT_TRACKER_ELEMENTS.EMPTY_STATE_CREATE_PROJECT_BUTTON });
- }}
- disabled={!hasMemberLevelPermission}
- />
- }
+ },
+ disabled: !hasMemberLevelPermission,
+ variant: "primary",
+ },
+ ]}
/>
);
diff --git a/apps/web/core/components/labels/project-setting-label-list.tsx b/apps/web/core/components/labels/project-setting-label-list.tsx
index d634e248b2..62f60250ef 100644
--- a/apps/web/core/components/labels/project-setting-label-list.tsx
+++ b/apps/web/core/components/labels/project-setting-label-list.tsx
@@ -6,9 +6,9 @@ import { useParams } from "next/navigation";
// plane imports
import { EUserPermissions, EUserPermissionsLevel, PROJECT_SETTINGS_TRACKER_ELEMENTS } from "@plane/constants";
import { useTranslation } from "@plane/i18n";
+import { EmptyStateCompact } from "@plane/propel/empty-state";
import type { IIssueLabel } from "@plane/types";
import { Loader } from "@plane/ui";
-import { DetailedEmptyState } from "@/components/empty-state/detailed-empty-state-root";
import type { TLabelOperationsCallbacks } from "@/components/labels";
import {
CreateUpdateLabelInline,
@@ -20,7 +20,6 @@ import {
import { captureClick } from "@/helpers/event-tracker.helper";
import { useLabel } from "@/hooks/store/use-label";
import { useUserPermissions } from "@/hooks/store/user";
-import { useResolvedAssetPath } from "@/hooks/use-resolved-asset-path";
// local imports
import { SettingsHeading } from "../settings/heading";
@@ -40,7 +39,6 @@ export const ProjectSettingsLabelList: React.FC = observer(() => {
const { allowPermissions } = useUserPermissions();
// derived values
const isEditable = allowPermissions([EUserPermissions.ADMIN], EUserPermissionsLevel.PROJECT);
- const resolvedPath = useResolvedAssetPath({ basePath: "/empty-state/project-settings/labels" });
const labelOperationsCallbacks: TLabelOperationsCallbacks = {
createLabel: (data: Partial) => createLabel(workspaceSlug?.toString(), projectId?.toString(), data),
updateLabel: (labelId: string, data: Partial) =>
@@ -111,24 +109,25 @@ export const ProjectSettingsLabelList: React.FC = observer(() => {
)}
{projectLabels ? (
projectLabels.length === 0 && !showLabelForm ? (
-
- {
newLabel();
captureClick({
elementName: PROJECT_SETTINGS_TRACKER_ELEMENTS.LABELS_EMPTY_STATE_CREATE_BUTTON,
});
},
- }}
- assetPath={resolvedPath}
- className="w-full !px-0 !py-0"
- size="md"
- />
-
+ },
+ ]}
+ align="start"
+ rootClassName="py-20"
+ />
) : (
projectLabelsTree && (
diff --git a/apps/web/core/components/modules/modules-list-view.tsx b/apps/web/core/components/modules/modules-list-view.tsx
index 877855c8e7..5d80ccf2cc 100644
--- a/apps/web/core/components/modules/modules-list-view.tsx
+++ b/apps/web/core/components/modules/modules-list-view.tsx
@@ -1,14 +1,12 @@
import { observer } from "mobx-react";
-import Image from "next/image";
import { useParams, useSearchParams } from "next/navigation";
// components
import { EUserPermissionsLevel, MODULE_TRACKER_ELEMENTS } from "@plane/constants";
import { useTranslation } from "@plane/i18n";
+import { EmptyStateDetailed } from "@plane/propel/empty-state";
import { EUserProjectRoles } from "@plane/types";
import { ContentWrapper, Row, ERowVariant } from "@plane/ui";
import { ListLayout } from "@/components/core/list";
-import { ComicBoxButton } from "@/components/empty-state/comic-box-button";
-import { DetailedEmptyState } from "@/components/empty-state/detailed-empty-state-root";
import { ModuleCardItem, ModuleListItem, ModulePeekOverview, ModulesListGanttChartView } from "@/components/modules";
import { CycleModuleBoardLayoutLoader } from "@/components/ui/loader/cycle-module-board-loader";
import { CycleModuleListLayoutLoader } from "@/components/ui/loader/cycle-module-list-loader";
@@ -18,9 +16,6 @@ import { useCommandPalette } from "@/hooks/store/use-command-palette";
import { useModule } from "@/hooks/store/use-module";
import { useModuleFilter } from "@/hooks/store/use-module-filter";
import { useUserPermissions } from "@/hooks/store/user";
-import { useResolvedAssetPath } from "@/hooks/use-resolved-asset-path";
-import AllFiltersImage from "@/public/empty-state/module/all-filters.svg";
-import NameFilterImage from "@/public/empty-state/module/name-filter.svg";
export const ModulesListView: React.FC = observer(() => {
// router
@@ -32,7 +27,7 @@ export const ModulesListView: React.FC = observer(() => {
// store hooks
const { toggleCreateModuleModal } = useCommandPalette();
const { getProjectModuleIds, getFilteredModuleIds, loader } = useModule();
- const { currentProjectDisplayFilters: displayFilters, searchQuery } = useModuleFilter();
+ const { currentProjectDisplayFilters: displayFilters } = useModuleFilter();
const { allowPermissions } = useUserPermissions();
// derived values
const projectModuleIds = projectId ? getProjectModuleIds(projectId.toString()) : undefined;
@@ -41,9 +36,6 @@ export const ModulesListView: React.FC = observer(() => {
[EUserProjectRoles.ADMIN, EUserProjectRoles.MEMBER],
EUserPermissionsLevel.PROJECT
);
- const generalViewResolvedPath = useResolvedAssetPath({
- basePath: "/empty-state/onboarding/modules",
- });
if (loader || !projectModuleIds || !filteredModuleIds)
return (
@@ -56,42 +48,29 @@ export const ModulesListView: React.FC = observer(() => {
if (projectModuleIds.length === 0)
return (
-
{
- toggleCreateModuleModal(true);
- }}
- disabled={!canPerformEmptyStateActions}
- />
- }
+ toggleCreateModuleModal(true),
+ disabled: !canPerformEmptyStateActions,
+ variant: "primary",
+ "data-ph-element": MODULE_TRACKER_ELEMENTS.EMPTY_STATE_ADD_BUTTON,
+ },
+ ]}
/>
);
if (filteredModuleIds.length === 0)
return (
-
-
-
-
No matching modules
-
- {searchQuery.trim() === ""
- ? "Remove the filters to see all modules"
- : "Remove the search criteria to see all modules"}
-
-
-
+
);
return (
diff --git a/apps/web/core/components/pages/pages-list-main-content.tsx b/apps/web/core/components/pages/pages-list-main-content.tsx
index ee39f38c0b..42fbf1cce7 100644
--- a/apps/web/core/components/pages/pages-list-main-content.tsx
+++ b/apps/web/core/components/pages/pages-list-main-content.tsx
@@ -1,7 +1,6 @@
"use client";
import { useState } from "react";
import { observer } from "mobx-react";
-import Image from "next/image";
// plane imports
import { useParams, useRouter } from "next/navigation";
import {
@@ -11,16 +10,15 @@ import {
PROJECT_PAGE_TRACKER_EVENTS,
} from "@plane/constants";
import { useTranslation } from "@plane/i18n";
+import { EmptyStateDetailed } from "@plane/propel/empty-state";
import { TOAST_TYPE, setToast } from "@plane/propel/toast";
import type { TPage, TPageNavigationTabs } from "@plane/types";
import { EUserProjectRoles } from "@plane/types";
// components
-import { DetailedEmptyState } from "@/components/empty-state/detailed-empty-state-root";
import { PageLoader } from "@/components/pages/loaders/page-loader";
import { captureClick, captureError, captureSuccess } from "@/helpers/event-tracker.helper";
import { useProject } from "@/hooks/store/use-project";
import { useUserPermissions } from "@/hooks/store/user";
-import { useResolvedAssetPath } from "@/hooks/use-resolved-asset-path";
// plane web hooks
import { EPageStoreType, usePageStore } from "@/plane-web/hooks/store";
@@ -52,23 +50,6 @@ export const PagesListMainContent: React.FC = observer((props) => {
[EUserProjectRoles.ADMIN, EUserProjectRoles.MEMBER],
EUserPermissionsLevel.PROJECT
);
- const generalPageResolvedPath = useResolvedAssetPath({
- basePath: "/empty-state/onboarding/pages",
- });
- const publicPageResolvedPath = useResolvedAssetPath({
- basePath: "/empty-state/wiki/public",
- });
- const privatePageResolvedPath = useResolvedAssetPath({
- basePath: "/empty-state/wiki/private",
- });
- const archivedPageResolvedPath = useResolvedAssetPath({
- basePath: "/empty-state/wiki/archived",
- });
- const resolvedFiltersImage = useResolvedAssetPath({ basePath: "/empty-state/wiki/all-filters", extension: "svg" });
- const resolvedNameFilterImage = useResolvedAssetPath({
- basePath: "/empty-state/wiki/name-filter",
- extension: "svg",
- });
// handle page create
const handleCreatePage = async () => {
@@ -111,80 +92,79 @@ export const PagesListMainContent: React.FC = observer((props) => {
if (!isAnyPageAvailable || pageIds?.length === 0) {
if (!isAnyPageAvailable) {
return (
- {
- handleCreatePage();
- captureClick({ elementName: PROJECT_PAGE_TRACKER_ELEMENTS.EMPTY_STATE_CREATE_BUTTON });
+ {
+ handleCreatePage();
+ captureClick({ elementName: PROJECT_PAGE_TRACKER_ELEMENTS.EMPTY_STATE_CREATE_BUTTON });
+ },
+ variant: "primary",
+ disabled: !canPerformEmptyStateActions || isCreatingPage,
},
- disabled: !canPerformEmptyStateActions || isCreatingPage,
- }}
+ ]}
/>
);
}
if (pageType === "public")
return (
- {
- handleCreatePage();
- captureClick({ elementName: PROJECT_PAGE_TRACKER_ELEMENTS.EMPTY_STATE_CREATE_BUTTON });
+ {
+ handleCreatePage();
+ captureClick({ elementName: PROJECT_PAGE_TRACKER_ELEMENTS.EMPTY_STATE_CREATE_BUTTON });
+ },
+ variant: "primary",
+ disabled: !canPerformEmptyStateActions || isCreatingPage,
},
- disabled: !canPerformEmptyStateActions || isCreatingPage,
- }}
+ ]}
/>
);
if (pageType === "private")
return (
- {
- handleCreatePage();
- captureClick({ elementName: PROJECT_PAGE_TRACKER_ELEMENTS.EMPTY_STATE_CREATE_BUTTON });
+ {
+ handleCreatePage();
+ captureClick({ elementName: PROJECT_PAGE_TRACKER_ELEMENTS.EMPTY_STATE_CREATE_BUTTON });
+ },
+ variant: "primary",
+ disabled: !canPerformEmptyStateActions || isCreatingPage,
},
- disabled: !canPerformEmptyStateActions || isCreatingPage,
- }}
+ ]}
/>
);
if (pageType === "archived")
return (
-
);
}
// if no pages match the filter criteria
if (filteredPageIds?.length === 0)
return (
-
-
-
0 ? resolvedNameFilterImage : resolvedFiltersImage}
- className="h-36 sm:h-48 w-36 sm:w-48 mx-auto"
- alt="No matching modules"
- />
- No matching pages
-
- {filters.searchQuery.length > 0
- ? "Remove the search criteria to see all pages"
- : "Remove the filters to see all pages"}
-
-
-
+
);
return {children}
;
diff --git a/apps/web/core/components/profile/overview/activity.tsx b/apps/web/core/components/profile/overview/activity.tsx
index f52255400e..2af5e2079d 100644
--- a/apps/web/core/components/profile/overview/activity.tsx
+++ b/apps/web/core/components/profile/overview/activity.tsx
@@ -5,6 +5,7 @@ import { useParams } from "next/navigation";
import useSWR from "swr";
// ui
import { useTranslation } from "@plane/i18n";
+import { EmptyStateCompact } from "@plane/propel/empty-state";
import { Loader, Card } from "@plane/ui";
import { calculateTimeAgo, getFileURL } from "@plane/utils";
// components
@@ -83,11 +84,7 @@ export const ProfileActivity = observer(() => {
))}
) : (
-
+
)
) : (
diff --git a/apps/web/core/components/profile/overview/priority-distribution.tsx b/apps/web/core/components/profile/overview/priority-distribution.tsx
index d97a687321..98f79a5189 100644
--- a/apps/web/core/components/profile/overview/priority-distribution.tsx
+++ b/apps/web/core/components/profile/overview/priority-distribution.tsx
@@ -3,13 +3,10 @@
// plane imports
import { useTranslation } from "@plane/i18n";
import { BarChart } from "@plane/propel/charts/bar-chart";
+import { EmptyStateCompact } from "@plane/propel/empty-state";
import type { IUserProfileData } from "@plane/types";
import { Loader, Card } from "@plane/ui";
import { capitalizeFirstLetter } from "@plane/utils";
-// components
-import { ProfileEmptyState } from "@/components/ui/profile-empty-state";
-// assets
-import emptyBarGraph from "@/public/empty-state/empty_bar_graph.svg";
type Props = {
userProfile: IUserProfileData | undefined;
@@ -62,13 +59,11 @@ export const ProfilePriorityDistribution: React.FC = ({ userProfile }) =>
barSize={20}
/>
) : (
-
+
)}
) : (
diff --git a/apps/web/core/components/profile/overview/state-distribution.tsx b/apps/web/core/components/profile/overview/state-distribution.tsx
index 9b7c15f42b..0b4024f21a 100644
--- a/apps/web/core/components/profile/overview/state-distribution.tsx
+++ b/apps/web/core/components/profile/overview/state-distribution.tsx
@@ -2,13 +2,10 @@
import { STATE_GROUPS } from "@plane/constants";
import { useTranslation } from "@plane/i18n";
import { PieChart } from "@plane/propel/charts/pie-chart";
+import { EmptyStateCompact } from "@plane/propel/empty-state";
import type { IUserProfileData, IUserStateDistribution } from "@plane/types";
import { Card } from "@plane/ui";
import { capitalizeFirstLetter } from "@plane/utils";
-// components
-import { ProfileEmptyState } from "@/components/ui/profile-empty-state";
-// assets
-import stateGraph from "@/public/empty-state/state_graph.svg";
type Props = {
stateDistribution: IUserStateDistribution[];
@@ -74,10 +71,10 @@ export const ProfileStateDistribution: React.FC = ({ stateDistribution, u
) : (
-