Skip to content

Commit b165e2a

Browse files
[WEB-5614] chore: platform header and breadcrumb enhancements (#8383)
1 parent 3df5839 commit b165e2a

File tree

16 files changed

+163
-85
lines changed

16 files changed

+163
-85
lines changed

apps/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/cycles/(detail)/header.tsx

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {
1414
import { usePlatformOS } from "@plane/hooks";
1515
import { useTranslation } from "@plane/i18n";
1616
import { Button } from "@plane/propel/button";
17+
import { IconButton } from "@plane/propel/icon-button";
1718
import { CycleIcon } from "@plane/propel/icons";
1819
import { Tooltip } from "@plane/propel/tooltip";
1920
import type { ICustomSearchSelectOption, IIssueDisplayFilterOptions, IIssueDisplayProperties } from "@plane/types";
@@ -236,7 +237,6 @@ export const CycleIssuesHeader = observer(function CycleIssuesHeader() {
236237
<Button
237238
variant="primary"
238239
size="lg"
239-
className="self-start"
240240
onClick={() => {
241241
toggleCreateIssueModal(true, EIssuesStoreType.CYCLE);
242242
}}
@@ -247,9 +247,15 @@ export const CycleIssuesHeader = observer(function CycleIssuesHeader() {
247247
)}
248248
</>
249249
)}
250-
<Button variant="ghost" size="lg" onClick={toggleSidebar}>
251-
<PanelRight className={cn("h-4 w-4", !isSidebarCollapsed ? "text-accent-primary" : "text-secondary")} />
252-
</Button>
250+
<IconButton
251+
variant="tertiary"
252+
size="lg"
253+
icon={PanelRight}
254+
onClick={toggleSidebar}
255+
className={cn({
256+
"text-accent-primary bg-accent-subtle": !isSidebarCollapsed,
257+
})}
258+
/>
253259
<CycleQuickActions
254260
parentRef={parentRef}
255261
cycleId={cycleId}

apps/web/app/(all)/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/modules/(detail)/header.tsx

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ import useLocalStorage from "@/hooks/use-local-storage";
4242
import { usePlatformOS } from "@/hooks/use-platform-os";
4343
// plane web imports
4444
import { CommonProjectBreadcrumbs } from "@/plane-web/components/breadcrumbs/common";
45+
import { IconButton } from "@plane/propel/icon-button";
4546

4647
export const ModuleIssuesHeader = observer(function ModuleIssuesHeader() {
4748
// refs
@@ -242,9 +243,15 @@ export const ModuleIssuesHeader = observer(function ModuleIssuesHeader() {
242243
) : (
243244
<></>
244245
)}
245-
<Button variant="ghost" size="lg" onClick={toggleSidebar}>
246-
<PanelRight className={cn("h-4 w-4", !isSidebarCollapsed ? "text-accent-primary" : "text-secondary")} />
247-
</Button>
246+
<IconButton
247+
variant="tertiary"
248+
size="lg"
249+
icon={PanelRight}
250+
onClick={toggleSidebar}
251+
className={cn({
252+
"text-accent-primary bg-accent-subtle": !isSidebarCollapsed,
253+
})}
254+
/>
248255
{moduleId && (
249256
<ModuleQuickActions
250257
parentRef={parentRef}

apps/web/ce/components/cycles/active-cycle/root.tsx

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { observer } from "mobx-react";
22
import { useTheme } from "next-themes";
33
import { Disclosure } from "@headlessui/react";
4+
import { EmptyStateDetailed } from "@plane/propel/empty-state";
45
// plane imports
56
import { useTranslation } from "@plane/i18n";
67
import type { ICycle } from "@plane/types";
@@ -15,7 +16,6 @@ import { ActiveCycleProgress } from "@/components/cycles/active-cycle/progress";
1516
import useCyclesDetails from "@/components/cycles/active-cycle/use-cycles-details";
1617
import { CycleListGroupHeader } from "@/components/cycles/list/cycle-list-group-header";
1718
import { CyclesListItem } from "@/components/cycles/list/cycles-list-item";
18-
import { DetailedEmptyState } from "@/components/empty-state/detailed-empty-state-root";
1919
// hooks
2020
import { useCycle } from "@/hooks/store/use-cycle";
2121
import type { ActiveCycleIssueDetails } from "@/store/issue/cycle";
@@ -50,10 +50,11 @@ const ActiveCyclesComponent = observer(function ActiveCyclesComponent({
5050

5151
if (!cycleId || !activeCycle) {
5252
return (
53-
<DetailedEmptyState
53+
<EmptyStateDetailed
54+
assetKey="cycle"
5455
title={t("project_cycles.empty_state.active.title")}
5556
description={t("project_cycles.empty_state.active.description")}
56-
assetPath={activeCycleResolvedPath}
57+
rootClassName="py-10 h-auto"
5758
/>
5859
);
5960
}
@@ -114,7 +115,7 @@ export const ActiveCycleRoot = observer(function ActiveCycleRoot(props: IActiveC
114115
<Disclosure as="div" className="flex flex-shrink-0 flex-col" defaultOpen>
115116
{({ open }) => (
116117
<>
117-
<Disclosure.Button className="sticky top-0 z-[2] w-full flex-shrink-0 border-b border-subtle bg-layer-2 cursor-pointer">
118+
<Disclosure.Button className="sticky top-0 z-[2] w-full flex-shrink-0 border-b border-subtle bg-layer-1 cursor-pointer">
118119
<CycleListGroupHeader title={t("project_cycles.active_cycle.label")} type="current" isExpanded={open} />
119120
</Disclosure.Button>
120121
<Disclosure.Panel>

apps/web/core/components/cycles/cycles-view-header.tsx

Lines changed: 34 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -70,49 +70,50 @@ export const CyclesViewHeader = observer(function CyclesViewHeader(props: Props)
7070
}, [searchQuery]);
7171

7272
return (
73-
<div className="flex items-center gap-3">
74-
{!isSearchOpen && (
73+
<div className="flex items-center gap-2">
74+
{!isSearchOpen ? (
7575
<IconButton
7676
variant="ghost"
7777
size="lg"
78-
className="-mr-5"
7978
onClick={() => {
8079
setIsSearchOpen(true);
8180
inputRef.current?.focus();
8281
}}
8382
icon={Search}
8483
/>
84+
) : (
85+
<div
86+
className={cn(
87+
"ml-auto flex items-center justify-start gap-1 rounded-md border border-transparent bg-surface-1 text-placeholder w-0 transition-[width] ease-linear overflow-hidden opacity-0",
88+
{
89+
"w-64 px-2.5 py-1.5 border-subtle opacity-100": isSearchOpen,
90+
}
91+
)}
92+
>
93+
<Search className="h-3.5 w-3.5" />
94+
<input
95+
ref={inputRef}
96+
className="w-full max-w-[234px] border-none bg-transparent text-13 text-primary placeholder:text-placeholder focus:outline-none"
97+
placeholder="Search"
98+
value={searchQuery}
99+
onChange={(e) => updateSearchQuery(e.target.value)}
100+
onKeyDown={handleInputKeyDown}
101+
/>
102+
{isSearchOpen && (
103+
<button
104+
type="button"
105+
className="grid place-items-center"
106+
onClick={() => {
107+
updateSearchQuery("");
108+
setIsSearchOpen(false);
109+
}}
110+
>
111+
<CloseIcon className="h-3 w-3" />
112+
</button>
113+
)}
114+
</div>
85115
)}
86-
<div
87-
className={cn(
88-
"ml-auto flex items-center justify-start gap-1 rounded-md border border-transparent bg-surface-1 text-placeholder w-0 transition-[width] ease-linear overflow-hidden opacity-0",
89-
{
90-
"w-64 px-2.5 py-1.5 border-subtle opacity-100": isSearchOpen,
91-
}
92-
)}
93-
>
94-
<Search className="h-3.5 w-3.5" />
95-
<input
96-
ref={inputRef}
97-
className="w-full max-w-[234px] border-none bg-transparent text-13 text-primary placeholder:text-placeholder focus:outline-none"
98-
placeholder="Search"
99-
value={searchQuery}
100-
onChange={(e) => updateSearchQuery(e.target.value)}
101-
onKeyDown={handleInputKeyDown}
102-
/>
103-
{isSearchOpen && (
104-
<button
105-
type="button"
106-
className="grid place-items-center"
107-
onClick={() => {
108-
updateSearchQuery("");
109-
setIsSearchOpen(false);
110-
}}
111-
>
112-
<CloseIcon className="h-3 w-3" />
113-
</button>
114-
)}
115-
</div>
116+
116117
<FiltersDropdown
117118
icon={<ListFilter className="h-3 w-3" />}
118119
title={t("common.filters")}

apps/web/core/components/cycles/list/cycle-list-item-action.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,7 @@ export const CycleListItemAction = observer(function CycleListItemAction(props:
301301
{createdByDetails && !isActive && <ButtonAvatars showTooltip={false} userIds={createdByDetails?.id} />}
302302
{!isActive && (
303303
<Tooltip tooltipContent={`${cycleDetails.assignee_ids?.length} Members`} isMobile={isMobile}>
304-
<div className="flex w-10 cursor-default items-center justify-center">
304+
<div className="flex w-min cursor-default items-center justify-center">
305305
{cycleDetails.assignee_ids && cycleDetails.assignee_ids?.length > 0 ? (
306306
<AvatarGroup showTooltip={false}>
307307
{cycleDetails.assignee_ids?.map((assignee_id) => {

apps/web/core/components/cycles/list/root.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ export const CyclesList = observer(function CyclesList(props: ICyclesList) {
4040
<Disclosure as="div" className="flex flex-shrink-0 flex-col" defaultOpen>
4141
{({ open }) => (
4242
<>
43-
<Disclosure.Button className="sticky top-0 z-[2] w-full flex-shrink-0 border-b border-subtle bg-layer-2 cursor-pointer">
43+
<Disclosure.Button className="sticky top-0 z-[2] w-full flex-shrink-0 border-b border-subtle bg-layer-1 cursor-pointer">
4444
<CycleListGroupHeader
4545
title={t("project_cycles.upcoming_cycle.label")}
4646
type="upcoming"
@@ -59,7 +59,7 @@ export const CyclesList = observer(function CyclesList(props: ICyclesList) {
5959
<Disclosure as="div" className="flex flex-shrink-0 flex-col pb-7">
6060
{({ open }) => (
6161
<>
62-
<Disclosure.Button className="sticky top-0 z-2 w-full flex-shrink-0 border-b border-subtle bg-layer-2 cursor-pointer">
62+
<Disclosure.Button className="sticky top-0 z-2 w-full flex-shrink-0 border-b border-subtle bg-layer-1 cursor-pointer">
6363
<CycleListGroupHeader
6464
title={t("project_cycles.completed_cycle.label")}
6565
type="completed"

apps/web/core/components/cycles/quick-actions.tsx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { useState } from "react";
22
import { observer } from "mobx-react";
3+
import { MoreHorizontal } from "lucide-react";
34

45
// ui
56
import {
@@ -9,6 +10,7 @@ import {
910
CYCLE_TRACKER_ELEMENTS,
1011
} from "@plane/constants";
1112
import { useTranslation } from "@plane/i18n";
13+
import { IconButton } from "@plane/propel/icon-button";
1214
import { TOAST_TYPE, setToast } from "@plane/propel/toast";
1315
import type { TContextMenuItem } from "@plane/ui";
1416
import { ContextMenu, CustomMenu } from "@plane/ui";
@@ -155,7 +157,13 @@ export const CycleQuickActions = observer(function CycleQuickActions(props: Prop
155157
</div>
156158
)}
157159
<ContextMenu parentRef={parentRef} items={CONTEXT_MENU_ITEMS} />
158-
<CustomMenu ellipsis placement="bottom-end" closeOnSelect maxHeight="lg" buttonClassName={customClassName}>
160+
<CustomMenu
161+
customButton={<IconButton variant="tertiary" size="lg" icon={MoreHorizontal} />}
162+
placement="bottom-end"
163+
closeOnSelect
164+
maxHeight="lg"
165+
buttonClassName={customClassName}
166+
>
159167
{MENU_ITEMS.map((item) => {
160168
if (item.shouldRender === false) return null;
161169
return (

apps/web/core/components/modules/module-view-header.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ export const ModuleViewHeader = observer(function ModuleViewHeader() {
9494
const isFiltersApplied = calculateTotalFilters(filters ?? {}) !== 0 || displayFilters?.favorites;
9595

9696
return (
97-
<div className="hidden h-full sm:flex items-center gap-3 self-end">
97+
<div className="hidden h-full sm:flex items-center gap-2 self-end">
9898
<div className="flex items-center">
9999
{!isSearchOpen && (
100100
<IconButton

apps/web/core/components/modules/quick-actions.tsx

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { useState } from "react";
22
import { observer } from "mobx-react";
3+
import { MoreHorizontal } from "lucide-react";
34

45
// plane imports
56
import {
@@ -9,6 +10,7 @@ import {
910
MODULE_TRACKER_EVENTS,
1011
} from "@plane/constants";
1112
import { useTranslation } from "@plane/i18n";
13+
import { IconButton } from "@plane/propel/icon-button";
1214
import { TOAST_TYPE, setToast } from "@plane/propel/toast";
1315
import type { TContextMenuItem } from "@plane/ui";
1416
import { ContextMenu, CustomMenu } from "@plane/ui";
@@ -112,15 +114,18 @@ export const ModuleQuickActions = observer(function ModuleQuickActions(props: Pr
112114
const MENU_ITEMS: TContextMenuItem[] = Array.isArray(menuResult) ? menuResult : menuResult.items;
113115
const additionalModals = Array.isArray(menuResult) ? null : menuResult.modals;
114116

115-
const CONTEXT_MENU_ITEMS: TContextMenuItem[] = MENU_ITEMS.map((item) => ({
116-
...item,
117-
action: () => {
118-
captureClick({
119-
elementName: MODULE_TRACKER_ELEMENTS.CONTEXT_MENU,
120-
});
121-
item.action();
122-
},
123-
}));
117+
const CONTEXT_MENU_ITEMS = MENU_ITEMS.map(function CONTEXT_MENU_ITEMS(item) {
118+
return {
119+
...item,
120+
121+
onClick: () => {
122+
captureClick({
123+
elementName: MODULE_TRACKER_ELEMENTS.CONTEXT_MENU,
124+
});
125+
item.action();
126+
},
127+
};
128+
});
124129

125130
return (
126131
<>
@@ -145,7 +150,12 @@ export const ModuleQuickActions = observer(function ModuleQuickActions(props: Pr
145150
</div>
146151
)}
147152
<ContextMenu parentRef={parentRef} items={CONTEXT_MENU_ITEMS} />
148-
<CustomMenu ellipsis placement="bottom-end" closeOnSelect buttonClassName={customClassName}>
153+
<CustomMenu
154+
customButton={<IconButton variant="tertiary" size="lg" icon={MoreHorizontal} />}
155+
placement="bottom-end"
156+
closeOnSelect
157+
buttonClassName={customClassName}
158+
>
149159
{MENU_ITEMS.map((item) => {
150160
if (item.shouldRender === false) return null;
151161
return (

apps/web/core/components/rich-filters/filters-toggle.tsx

Lines changed: 11 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import { observer } from "mobx-react";
2-
import { ListFilter } from "lucide-react";
32
// plane imports
3+
import { IconButton } from "@plane/propel/icon-button";
4+
import { FilterIcon, FilterAppliedIcon } from "@plane/propel/icons";
5+
import { cn } from "@plane/utils";
46
import type { IFilterInstance } from "@plane/shared-state";
57
import type { TExternalFilter, TFilterProperty } from "@plane/types";
6-
import { cn } from "@plane/ui";
78
// components
89
import { AddFilterButton } from "@/components/rich-filters/add-filters/button";
910

@@ -49,28 +50,14 @@ export const FiltersToggle = observer(function FiltersToggle<P extends TFilterPr
4950
}
5051

5152
return (
52-
<button
53-
className={cn(COMMON_CLASSNAME, {
54-
"border-transparent bg-accent-primary/10 hover:bg-accent-primary/20": isFilterRowVisible,
55-
"hover:bg-surface-1": !isFilterRowVisible,
56-
})}
53+
<IconButton
54+
size="lg"
55+
variant="secondary"
56+
icon={showFilterRowChangesPill ? FilterAppliedIcon : FilterIcon}
5757
onClick={handleToggleFilter}
58-
>
59-
<div className="relative">
60-
<ListFilter
61-
className={cn("size-4", {
62-
"text-accent-primary": isFilterRowVisible,
63-
"text-tertiary": !isFilterRowVisible,
64-
})}
65-
/>
66-
{showFilterRowChangesPill && (
67-
<span
68-
className={cn("p-[3px] rounded-full bg-accent-primary absolute top-[0.2px] -right-[0.4px]", {
69-
"bg-layer-1": hasAnyConditions === false && filter?.hasChanges === true, // If there are no conditions and there are changes, show the pill in the background color
70-
})}
71-
/>
72-
)}
73-
</div>
74-
</button>
58+
className={cn({
59+
"text-accent-primary bg-accent-subtle border border-accent-subtle-1": showFilterRowChangesPill,
60+
})}
61+
/>
7562
);
7663
});

0 commit comments

Comments
 (0)