From 72e6bfaf4e1e88523b8a7b2e35fad5a89e3950f5 Mon Sep 17 00:00:00 2001 From: anmolsinghbhatia Date: Mon, 31 Aug 2026 16:42:17 +0530 Subject: [PATCH 1/2] refactor: migrate web Avatar to @makeplane/propel Avatar Replace @plane/ui Avatar and AvatarGroup with the published Propel components across apps/web. 41 files, 51 Avatar sites, 4 group sites. Propel's size scale is @plane/ui's shifted one step, so every enum maps with no pixel change: sm(16)->2xs, md(20)->xs, base(24)->sm, lg(28)->md. Unsized avatars took the old md default and become xs. Notable mapping decisions: - name -> alt plus fallback={name?.[0]?.toUpperCase()}, preserving the initial that @plane/ui derived internally. - Six numeric px sizes mapped to the nearest enum step. Five are exact; the notification card avatar moves 42px -> xl (40px). - Ten classNames removed, as published Propel takes no className. Seven were already redundant with Propel's base class (shrink-0, bg-layer-1); the remaining three overrode initials typography, which Propel now sets per size. - shape="circle" and fallback colour props dropped; Propel is always circular and picks initials colours from a fixed palette. AvatarGroup needs app chrome. @plane/ui defaulted to max={2}, rendering two avatars plus a +N counter, while Propel's AvatarGroup renders every child. No call site passed max explicitly, so all four relied on that default and would have rendered entire member lists. The new common/avatar-group-overflow.tsx restores the cap around Propel's group. ButtonAvatars' size prop is narrowed to AvatarGroupSize accordingly; no caller passes size. Tooltips are intentionally not migrated. @plane/ui Avatar wrapped itself in a Tooltip defaulting to on, and Propel has no built-in tooltip, so roughly 29 direct sites plus the ButtonAvatars subtree lose a tooltip. ButtonAvatars additionally inverted the flag (showTooltip={!showTooltip}), so its callers passing false were the ones showing tooltips. Restoring these is deliberately deferred to a follow-up. --- .../work-items/workitems-insight-table.tsx | 9 +-- .../core/components/comments/card/display.tsx | 4 +- .../common/applied-filters/members.tsx | 8 +-- .../common/avatar-group-overflow.tsx | 63 +++++++++++++++++++ .../components/common/filters/created-by.tsx | 9 +-- .../description-versions/dropdown-item.tsx | 8 ++- .../core/description-versions/modal.tsx | 8 ++- .../core/sidebar/progress-stats/assignee.tsx | 9 ++- .../cycles/active-cycle/cycle-stats.tsx | 7 ++- .../analytics-sidebar/sidebar-details.tsx | 19 ++++-- .../cycles/list/cycle-list-item-action.tsx | 15 +++-- .../components/dropdowns/member/avatar.tsx | 26 +++++--- .../dropdowns/member/member-options.tsx | 9 ++- .../editor/embeds/mentions/user.tsx | 9 ++- .../components/home/widgets/recents/page.tsx | 9 ++- .../inbox-filter/applied-filters/member.tsx | 9 ++- .../inbox/inbox-filter/filters/members.tsx | 9 +-- .../inbox/sidebar/inbox-list-item.tsx | 7 ++- .../filters/applied-filters/members.tsx | 9 ++- .../filters/header/filters/assignee.tsx | 9 +-- .../filters/header/filters/created-by.tsx | 12 +++- .../filters/header/filters/mentions.tsx | 9 +-- .../components/issues/issue-layouts/utils.tsx | 23 +++++-- .../modules/applied-filters/members.tsx | 9 ++- .../modules/dropdowns/filters/lead.tsx | 9 +-- .../modules/dropdowns/filters/members.tsx | 9 +-- .../pages/list/block-item-action.tsx | 10 ++- .../tab-panels/info/actors-info.tsx | 14 ++--- .../tab-panels/info/version-history.tsx | 8 +-- .../core/components/power-k/menus/members.tsx | 9 +-- .../project/applied-filters/members.tsx | 9 ++- apps/web/core/components/project/card.tsx | 15 +++-- .../project/dropdowns/filters/lead.tsx | 9 +-- .../project/dropdowns/filters/members.tsx | 9 +-- .../core/components/project/member-select.tsx | 17 ++++- .../project/send-project-invitation-modal.tsx | 14 ++++- .../settings/profile/sidebar/header.tsx | 11 ++-- .../sidebar/notification-card/item.tsx | 11 ++-- .../workspace/sidebar/user-menu-root.tsx | 16 ++--- .../core/hooks/editor/use-editor-mention.tsx | 8 +-- .../use-work-item-filters-config.tsx | 27 ++++---- 41 files changed, 341 insertions(+), 172 deletions(-) create mode 100644 apps/web/core/components/common/avatar-group-overflow.tsx diff --git a/apps/web/core/components/analytics/work-items/workitems-insight-table.tsx b/apps/web/core/components/analytics/work-items/workitems-insight-table.tsx index 52f3abd66ca..73d18192a1e 100644 --- a/apps/web/core/components/analytics/work-items/workitems-insight-table.tsx +++ b/apps/web/core/components/analytics/work-items/workitems-insight-table.tsx @@ -10,13 +10,14 @@ import { observer } from "mobx-react"; import { useParams } from "next/navigation"; import useSWR from "swr"; import { UserRound } from "lucide-react"; +import { Avatar } from "@makeplane/propel/components/avatar"; import { useTranslation } from "@plane/i18n"; import { Logo } from "@plane/propel/emoji-icon-picker"; import { ProjectIcon } from "@plane/propel/icons"; // plane package imports import type { AnalyticsTableDataMap, WorkItemInsightColumns } from "@plane/types"; // plane web components -import { Avatar } from "@plane/ui"; + import { getFileURL } from "@plane/utils"; // hooks import { useAnalytics } from "@/hooks/store/use-analytics"; @@ -111,10 +112,10 @@ const WorkItemsInsightTable = observer(function WorkItemsInsightTable() {
{row.original.avatar_url && row.original.avatar_url !== "" ? ( ) : (
diff --git a/apps/web/core/components/comments/card/display.tsx b/apps/web/core/components/comments/card/display.tsx index 18857f2dcd8..85bc7f66119 100644 --- a/apps/web/core/components/comments/card/display.tsx +++ b/apps/web/core/components/comments/card/display.tsx @@ -9,6 +9,7 @@ import { useCallback, useEffect, useState } from "react"; import { observer } from "mobx-react"; import { usePathname } from "next/navigation"; // plane imports +import { Avatar } from "@makeplane/propel/components/avatar"; import { Tooltip } from "@makeplane/propel/components/tooltip"; import type { EditorRefApi } from "@plane/editor"; import { useHashScroll } from "@plane/hooks"; @@ -22,7 +23,6 @@ import { LiteTextEditor } from "@/components/editor/lite-text"; import { CommentReactions } from "../comment-reaction"; import { CommentCardEditForm } from "./edit-form"; import { EmojiReactionButton, EmojiReactionPicker } from "@plane/propel/emoji-reaction"; -import { Avatar } from "@plane/ui"; import { useMember } from "@/hooks/store/use-member"; export type TCommentCardDisplayProps = { @@ -118,7 +118,7 @@ export const CommentCardDisplay = observer(function CommentCardDisplay(props: TC
)}
- +
{displayName}
diff --git a/apps/web/core/components/common/applied-filters/members.tsx b/apps/web/core/components/common/applied-filters/members.tsx index fe5e6a5cc0e..1982fa82520 100644 --- a/apps/web/core/components/common/applied-filters/members.tsx +++ b/apps/web/core/components/common/applied-filters/members.tsx @@ -7,7 +7,7 @@ import { observer } from "mobx-react"; import { CloseIcon } from "@plane/propel/icons"; // plane ui -import { Avatar } from "@plane/ui"; +import { Avatar } from "@makeplane/propel/components/avatar"; // helpers import { getFileURL } from "@plane/utils"; // types @@ -36,10 +36,10 @@ export const AppliedMembersFilters = observer(function AppliedMembersFilters(pro return (
{memberDetails.display_name} {editable && ( diff --git a/apps/web/core/components/common/avatar-group-overflow.tsx b/apps/web/core/components/common/avatar-group-overflow.tsx new file mode 100644 index 00000000000..0c91a208391 --- /dev/null +++ b/apps/web/core/components/common/avatar-group-overflow.tsx @@ -0,0 +1,63 @@ +/** + * Copyright (c) 2023-present Plane Software, Inc. and contributors + * SPDX-License-Identifier: AGPL-3.0-only + * See the LICENSE file for details. + */ + +import React from "react"; +// plane imports +import { AvatarGroup, type AvatarGroupSize } from "@makeplane/propel/components/avatar-group"; +import { cn } from "@plane/utils"; + +const OVERFLOW_COUNTER_SIZE: Record = { + "2xs": "size-4", + xs: "size-5", + sm: "size-6", +}; + +type Props = { + children: React.ReactNode; + /** + * Shared size for every avatar in the stack. + */ + size: AvatarGroupSize; + /** + * The maximum number of avatars to display. If the number of children exceeds this value, the + * additional avatars are replaced by a count of the remaining avatars. + * @default 2 + */ + max?: number; +}; + +/** + * An overlapping avatar stack that collapses the tail into a `+N` counter. + * + * Propel's `AvatarGroup` renders every child it is given, so the capping behaviour that + * `@plane/ui`'s `AvatarGroup` provided through `max` lives here as app chrome instead. + */ +export function AvatarGroupOverflow(props: Props) { + const { children, size, max = 2 } = props; + + const avatars = React.Children.toArray(children); + const totalAvatars = avatars.length; + // If there is only one avatar past the limit, render it instead of a "+1" counter. + const maxAvatarsToRender = totalAvatars <= max + 1 ? max + 1 : max; + + return ( + + {avatars.slice(0, maxAvatarsToRender)} + {maxAvatarsToRender < totalAvatars && ( +
+ +{totalAvatars - max} +
+ )} +
+ ); +} diff --git a/apps/web/core/components/common/filters/created-by.tsx b/apps/web/core/components/common/filters/created-by.tsx index 0009496db0f..f70cef7ae5c 100644 --- a/apps/web/core/components/common/filters/created-by.tsx +++ b/apps/web/core/components/common/filters/created-by.tsx @@ -8,7 +8,8 @@ import { useMemo, useState } from "react"; import { sortBy } from "lodash-es"; import { observer } from "mobx-react"; // ui -import { Avatar, Loader } from "@plane/ui"; +import { Avatar } from "@makeplane/propel/components/avatar"; +import { Loader } from "@plane/ui"; // components import { getFileURL } from "@plane/utils"; import { FilterHeader, FilterOption } from "@/components/issues/issue-layouts/filters"; @@ -78,10 +79,10 @@ export const FilterCreatedBy = observer(function FilterCreatedBy(props: Props) { onClick={() => handleUpdate(member.id)} icon={ } title={currentUser?.id === member.id ? "You" : member?.display_name} diff --git a/apps/web/core/components/core/description-versions/dropdown-item.tsx b/apps/web/core/components/core/description-versions/dropdown-item.tsx index b8abb5baadd..3c64f2b5d6a 100644 --- a/apps/web/core/components/core/description-versions/dropdown-item.tsx +++ b/apps/web/core/components/core/description-versions/dropdown-item.tsx @@ -6,9 +6,10 @@ import { observer } from "mobx-react"; // plane imports +import { Avatar } from "@makeplane/propel/components/avatar"; import { useTranslation } from "@plane/i18n"; import type { TDescriptionVersion } from "@plane/types"; -import { Avatar, CustomMenu } from "@plane/ui"; +import { CustomMenu } from "@plane/ui"; import { calculateTimeAgo, getFileURL } from "@plane/utils"; // hooks import { useMember } from "@/hooks/store/use-member"; @@ -31,8 +32,9 @@ export const DescriptionVersionsDropdownItem = observer(function DescriptionVers onClick(version.id)}> diff --git a/apps/web/core/components/core/description-versions/modal.tsx b/apps/web/core/components/core/description-versions/modal.tsx index 854b50922cf..d940b107389 100644 --- a/apps/web/core/components/core/description-versions/modal.tsx +++ b/apps/web/core/components/core/description-versions/modal.tsx @@ -7,6 +7,7 @@ import { useCallback, useRef } from "react"; import { observer } from "mobx-react"; // plane imports +import { Avatar } from "@makeplane/propel/components/avatar"; import type { EditorRefApi } from "@plane/editor"; import { useTranslation } from "@plane/i18n"; import { Button } from "@plane/propel/button"; @@ -14,7 +15,7 @@ import { CopyIcon, ChevronLeftIcon, ChevronRightIcon } from "@plane/propel/icons import { setToast, TOAST_TYPE } from "@plane/propel/toast"; import { Tooltip } from "@plane/propel/tooltip"; import type { TDescriptionVersion } from "@plane/types"; -import { Avatar, EModalPosition, EModalWidth, Loader, ModalCore } from "@plane/ui"; +import { EModalPosition, EModalWidth, Loader, ModalCore } from "@plane/ui"; import { calculateTimeAgo, cn, getFileURL } from "@plane/utils"; // components import { RichTextEditor } from "@/components/editor/rich-text"; @@ -85,9 +86,10 @@ export const DescriptionVersionsModal = observer(function DescriptionVersionsMod {t("description_versions.edited_by")}

diff --git a/apps/web/core/components/core/sidebar/progress-stats/assignee.tsx b/apps/web/core/components/core/sidebar/progress-stats/assignee.tsx index 102123bea31..ce202eef9ad 100644 --- a/apps/web/core/components/core/sidebar/progress-stats/assignee.tsx +++ b/apps/web/core/components/core/sidebar/progress-stats/assignee.tsx @@ -6,8 +6,8 @@ import { observer } from "mobx-react"; // plane imports +import { Avatar } from "@makeplane/propel/components/avatar"; import { useTranslation } from "@plane/i18n"; -import { Avatar } from "@plane/ui"; import { getFileURL } from "@plane/utils"; // assets import emptyMembers from "@/app/assets/empty-state/empty_members.svg?url"; @@ -43,7 +43,12 @@ export const AssigneeStatComponent = observer(function AssigneeStatComponent(pro key={assignee?.id} title={
- + {assignee?.title ?? ""}
} diff --git a/apps/web/core/components/cycles/active-cycle/cycle-stats.tsx b/apps/web/core/components/cycles/active-cycle/cycle-stats.tsx index 42189b2f639..0e2e6788ef4 100644 --- a/apps/web/core/components/cycles/active-cycle/cycle-stats.tsx +++ b/apps/web/core/components/cycles/active-cycle/cycle-stats.tsx @@ -12,6 +12,7 @@ import { CalendarCheck } from "lucide-react"; // headless ui import { Tab } from "@headlessui/react"; // plane imports +import { Avatar } from "@makeplane/propel/components/avatar"; import { useTranslation } from "@plane/i18n"; import { PriorityIcon } from "@plane/propel/icons"; import { Tooltip } from "@plane/propel/tooltip"; @@ -19,7 +20,7 @@ import type { TWorkItemFilterCondition } from "@plane/shared-state"; import type { ICycle } from "@plane/types"; import { EIssuesStoreType } from "@plane/types"; // ui -import { Loader, Avatar } from "@plane/ui"; +import { Loader } from "@plane/ui"; import { cn, renderFormattedDate, renderFormattedDateWithoutYear, getFileURL } from "@plane/utils"; // assets import darkAssigneeAsset from "@/app/assets/empty-state/active-cycle/assignee-dark.webp?url"; @@ -276,8 +277,10 @@ export const ActiveCycleStats = observer(function ActiveCycleStats(props: Active title={
{assignee.display_name} diff --git a/apps/web/core/components/cycles/analytics-sidebar/sidebar-details.tsx b/apps/web/core/components/cycles/analytics-sidebar/sidebar-details.tsx index 9c8ba8ac2ab..f1645397a52 100644 --- a/apps/web/core/components/cycles/analytics-sidebar/sidebar-details.tsx +++ b/apps/web/core/components/cycles/analytics-sidebar/sidebar-details.tsx @@ -11,13 +11,15 @@ import { SquareUser } from "lucide-react"; // plane types import { EEstimateSystem } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; +import { Avatar } from "@makeplane/propel/components/avatar"; import { MembersPropertyIcon, WorkItemsIcon } from "@plane/propel/icons"; import type { ICycle } from "@plane/types"; // plane ui -import { Avatar, AvatarGroup, TextArea } from "@plane/ui"; +import { TextArea } from "@plane/ui"; // helpers import { getFileURL } from "@plane/utils"; // hooks +import { AvatarGroupOverflow } from "@/components/common/avatar-group-overflow"; import { useProjectEstimates } from "@/hooks/store/estimates"; import { useMember } from "@/hooks/store/use-member"; // plane web constants @@ -83,7 +85,12 @@ export const CycleSidebarDetails = observer(function CycleSidebarDetails(props:
- + {cycleOwnerDetails?.display_name}
@@ -98,19 +105,19 @@ export const CycleSidebarDetails = observer(function CycleSidebarDetails(props:
{cycleDetails?.assignee_ids && cycleDetails.assignee_ids.length > 0 ? ( <> - + {cycleDetails.assignee_ids.map((member) => { const memberDetails = getUserDetails(member); return ( ); })} - + ) : ( {t("no_assignee")} diff --git a/apps/web/core/components/cycles/list/cycle-list-item-action.tsx b/apps/web/core/components/cycles/list/cycle-list-item-action.tsx index ad43d4a960a..672127ec4e7 100644 --- a/apps/web/core/components/cycles/list/cycle-list-item-action.tsx +++ b/apps/web/core/components/cycles/list/cycle-list-item-action.tsx @@ -14,13 +14,15 @@ import { Eye, ArrowRight, CalendarDays } from "lucide-react"; import { EUserPermissions, EUserPermissionsLevel, IS_FAVORITE_MENU_OPEN } from "@plane/constants"; import { useLocalStorage } from "@plane/hooks"; import { useTranslation } from "@plane/i18n"; +import { Avatar } from "@makeplane/propel/components/avatar"; import { TransferIcon, WorkItemsIcon, MembersPropertyIcon } from "@plane/propel/icons"; import { setPromiseToast } from "@plane/propel/toast"; import { Tooltip } from "@plane/propel/tooltip"; import type { ICycle, TCycleGroups } from "@plane/types"; -import { Avatar, AvatarGroup, FavoriteStar } from "@plane/ui"; +import { FavoriteStar } from "@plane/ui"; import { getDate, getFileURL, generateQueryParams } from "@plane/utils"; // components +import { AvatarGroupOverflow } from "@/components/common/avatar-group-overflow"; import { DateRangeDropdown } from "@/components/dropdowns/date-range"; import { ButtonAvatars } from "@/components/dropdowns/member/avatar"; import { MergedDateDisplay } from "@/components/dropdowns/merged-date"; @@ -274,14 +276,19 @@ export const CycleListItemAction = observer(function CycleListItemAction(props:
{cycleDetails.assignee_ids && cycleDetails.assignee_ids?.length > 0 ? ( - + {cycleDetails.assignee_ids?.map((assignee_id) => { const member = getUserDetails(assignee_id); return ( - + ); })} - + ) : ( )} diff --git a/apps/web/core/components/dropdowns/member/avatar.tsx b/apps/web/core/components/dropdowns/member/avatar.tsx index 82bc2e0c5e3..aa88d21d66e 100644 --- a/apps/web/core/components/dropdowns/member/avatar.tsx +++ b/apps/web/core/components/dropdowns/member/avatar.tsx @@ -6,38 +6,46 @@ import { observer } from "mobx-react"; import type { LucideIcon } from "lucide-react"; +import { Avatar } from "@makeplane/propel/components/avatar"; +import type { AvatarGroupSize } from "@makeplane/propel/components/avatar-group"; import { MembersPropertyIcon } from "@plane/propel/icons"; -// plane ui -import { Avatar, AvatarGroup } from "@plane/ui"; import { cn, getFileURL } from "@plane/utils"; // plane utils // helpers // hooks +import { AvatarGroupOverflow } from "@/components/common/avatar-group-overflow"; import { useMember } from "@/hooks/store/use-member"; type AvatarProps = { showTooltip: boolean; userIds: string | string[] | null; icon?: LucideIcon; - size?: "sm" | "md" | "base" | "lg" | number; + size?: AvatarGroupSize; }; export const ButtonAvatars = observer(function ButtonAvatars(props: AvatarProps) { - const { showTooltip, userIds, icon: Icon, size = "md" } = props; + const { userIds, icon: Icon, size = "xs" } = props; // store hooks const { getUserDetails } = useMember(); if (Array.isArray(userIds)) { if (userIds.length > 0) return ( - + {userIds.map((userId) => { const userDetails = getUserDetails(userId); if (!userDetails) return; - return ; + return ( + + ); })} - + ); } else { if (userIds) { @@ -45,9 +53,9 @@ export const ButtonAvatars = observer(function ButtonAvatars(props: AvatarProps) return ( ); } diff --git a/apps/web/core/components/dropdowns/member/member-options.tsx b/apps/web/core/components/dropdowns/member/member-options.tsx index a653ad0cd35..5e122309d1a 100644 --- a/apps/web/core/components/dropdowns/member/member-options.tsx +++ b/apps/web/core/components/dropdowns/member/member-options.tsx @@ -12,11 +12,11 @@ import { createPortal } from "react-dom"; import { usePopper } from "react-popper"; import { Combobox } from "@headlessui/react"; // plane imports +import { Avatar } from "@makeplane/propel/components/avatar"; import { useTranslation } from "@plane/i18n"; import { CheckIcon, SearchIcon, SuspendedUserIcon } from "@plane/propel/icons"; import { EPillSize, EPillVariant, Pill } from "@plane/propel/pill"; import type { IUserLite } from "@plane/types"; -import { Avatar } from "@plane/ui"; import { cn, getFileURL, sortByCurrentUserThenSelected } from "@plane/utils"; // hooks import { useMember } from "@/hooks/store/use-member"; @@ -102,7 +102,12 @@ export const MemberOptions = observer(function MemberOptions(props: Props) { {isUserSuspended(userId, workspaceSlug?.toString()) ? ( ) : ( - + )}
diff --git a/apps/web/core/components/home/widgets/recents/page.tsx b/apps/web/core/components/home/widgets/recents/page.tsx index cfb6f4cad68..8669ff95459 100644 --- a/apps/web/core/components/home/widgets/recents/page.tsx +++ b/apps/web/core/components/home/widgets/recents/page.tsx @@ -5,11 +5,11 @@ */ import { useRouter } from "next/navigation"; +import { Avatar } from "@makeplane/propel/components/avatar"; import { Logo } from "@plane/propel/emoji-icon-picker"; import { PageIcon } from "@plane/propel/icons"; // plane import import type { TActivityEntityData, TPageEntityData } from "@plane/types"; -import { Avatar } from "@plane/ui"; import { calculateTimeAgo, getFileURL, getPageName } from "@plane/utils"; import { ListItem } from "@/components/core/list"; // hooks @@ -65,7 +65,12 @@ export function RecentPage(props: BlockProps) { } quickActionElement={
- +
} parentRef={ref} diff --git a/apps/web/core/components/inbox/inbox-filter/applied-filters/member.tsx b/apps/web/core/components/inbox/inbox-filter/applied-filters/member.tsx index 4542fd123f2..322382d2ee5 100644 --- a/apps/web/core/components/inbox/inbox-filter/applied-filters/member.tsx +++ b/apps/web/core/components/inbox/inbox-filter/applied-filters/member.tsx @@ -7,10 +7,9 @@ import { observer } from "mobx-react"; // plane types +import { Avatar } from "@makeplane/propel/components/avatar"; import { CloseIcon } from "@plane/propel/icons"; import type { TInboxIssueFilterMemberKeys } from "@plane/types"; -// plane ui -import { Avatar } from "@plane/ui"; // helpers import { getFileURL } from "@plane/utils"; // hooks @@ -49,10 +48,10 @@ export const InboxIssueAppliedFiltersMember = observer(function InboxIssueApplie
{optionDetail?.display_name}
diff --git a/apps/web/core/components/inbox/inbox-filter/filters/members.tsx b/apps/web/core/components/inbox/inbox-filter/filters/members.tsx index d555aa81b85..497a49f65ee 100644 --- a/apps/web/core/components/inbox/inbox-filter/filters/members.tsx +++ b/apps/web/core/components/inbox/inbox-filter/filters/members.tsx @@ -8,9 +8,10 @@ import { useMemo, useState } from "react"; import { sortBy } from "lodash-es"; import { observer } from "mobx-react"; // plane types +import { Avatar } from "@makeplane/propel/components/avatar"; import type { TInboxIssueFilterMemberKeys } from "@plane/types"; // plane ui -import { Avatar, Loader } from "@plane/ui"; +import { Loader } from "@plane/ui"; // components import { getFileURL } from "@plane/utils"; import { FilterHeader, FilterOption } from "@/components/issues/issue-layouts/filters"; @@ -86,10 +87,10 @@ export const FilterMember = observer(function FilterMember(props: Props) { onClick={() => handleInboxIssueFilters(filterKey, handleFilterValue(member.id))} icon={ } title={currentUser?.id === member.id ? "You" : member?.display_name} diff --git a/apps/web/core/components/inbox/sidebar/inbox-list-item.tsx b/apps/web/core/components/inbox/sidebar/inbox-list-item.tsx index 22503e8a3b6..1cfbbeb2aee 100644 --- a/apps/web/core/components/inbox/sidebar/inbox-list-item.tsx +++ b/apps/web/core/components/inbox/sidebar/inbox-list-item.tsx @@ -9,10 +9,11 @@ import { observer } from "mobx-react"; import Link from "next/link"; import { useSearchParams } from "next/navigation"; // plane imports +import { Avatar } from "@makeplane/propel/components/avatar"; import { PriorityIcon } from "@plane/propel/icons"; import { Tooltip } from "@plane/propel/tooltip"; -import { Row, Avatar } from "@plane/ui"; -import { cn, renderFormattedDate, getFileURL } from "@plane/utils"; +import { Row } from "@plane/ui"; +import { cn, renderFormattedDate } from "@plane/utils"; // components import { ButtonAvatars } from "@/components/dropdowns/member/avatar"; // hooks @@ -127,7 +128,7 @@ export const InboxIssueListItem = observer(function InboxIssueListItem(props: In
{/* created by */} {createdByDetails && createdByDetails.email?.includes("intake@plane.so") ? ( - + ) : createdByDetails ? ( ) : null} diff --git a/apps/web/core/components/issues/issue-layouts/filters/applied-filters/members.tsx b/apps/web/core/components/issues/issue-layouts/filters/applied-filters/members.tsx index 760be503ff0..411c28e75a5 100644 --- a/apps/web/core/components/issues/issue-layouts/filters/applied-filters/members.tsx +++ b/apps/web/core/components/issues/issue-layouts/filters/applied-filters/members.tsx @@ -5,9 +5,8 @@ */ import { observer } from "mobx-react"; +import { Avatar } from "@makeplane/propel/components/avatar"; import { CloseIcon } from "@plane/propel/icons"; -// plane ui -import { Avatar } from "@plane/ui"; // helpers import { getFileURL } from "@plane/utils"; // hooks @@ -36,10 +35,10 @@ export const AppliedMembersFilters = observer(function AppliedMembersFilters(pro return (
{memberDetails.display_name} {editable && ( diff --git a/apps/web/core/components/issues/issue-layouts/filters/header/filters/assignee.tsx b/apps/web/core/components/issues/issue-layouts/filters/header/filters/assignee.tsx index e75eb406b53..33d324551b4 100644 --- a/apps/web/core/components/issues/issue-layouts/filters/header/filters/assignee.tsx +++ b/apps/web/core/components/issues/issue-layouts/filters/header/filters/assignee.tsx @@ -8,7 +8,8 @@ import { useMemo, useState } from "react"; import { sortBy } from "lodash-es"; import { observer } from "mobx-react"; // plane ui -import { Avatar, Loader } from "@plane/ui"; +import { Avatar } from "@makeplane/propel/components/avatar"; +import { Loader } from "@plane/ui"; // components import { getFileURL } from "@plane/utils"; import { FilterHeader, FilterOption } from "@/components/issues/issue-layouts/filters"; @@ -78,10 +79,10 @@ export const FilterAssignees = observer(function FilterAssignees(props: Props) { onClick={() => handleUpdate(member.id)} icon={ } title={currentUser?.id === member.id ? "You" : member?.display_name} diff --git a/apps/web/core/components/issues/issue-layouts/filters/header/filters/created-by.tsx b/apps/web/core/components/issues/issue-layouts/filters/header/filters/created-by.tsx index e78662422ed..f6267432f3a 100644 --- a/apps/web/core/components/issues/issue-layouts/filters/header/filters/created-by.tsx +++ b/apps/web/core/components/issues/issue-layouts/filters/header/filters/created-by.tsx @@ -8,7 +8,8 @@ import { useMemo, useState } from "react"; import { sortBy } from "lodash-es"; import { observer } from "mobx-react"; // plane ui -import { Avatar, Loader } from "@plane/ui"; +import { Avatar } from "@makeplane/propel/components/avatar"; +import { Loader } from "@plane/ui"; // components import { getFileURL } from "@plane/utils"; import { FilterHeader, FilterOption } from "@/components/issues/issue-layouts/filters"; @@ -76,7 +77,14 @@ export const FilterCreatedBy = observer(function FilterCreatedBy(props: Props) { key={`created-by-${member.id}`} isChecked={appliedFilters?.includes(member.id) ? true : false} onClick={() => handleUpdate(member.id)} - icon={} + icon={ + + } title={currentUser?.id === member.id ? "You" : member?.display_name} /> ); diff --git a/apps/web/core/components/issues/issue-layouts/filters/header/filters/mentions.tsx b/apps/web/core/components/issues/issue-layouts/filters/header/filters/mentions.tsx index 6aa1d881efb..d872a33e3c7 100644 --- a/apps/web/core/components/issues/issue-layouts/filters/header/filters/mentions.tsx +++ b/apps/web/core/components/issues/issue-layouts/filters/header/filters/mentions.tsx @@ -8,7 +8,8 @@ import { useMemo, useState } from "react"; import { sortBy } from "lodash-es"; import { observer } from "mobx-react"; // plane ui -import { Loader, Avatar } from "@plane/ui"; +import { Avatar } from "@makeplane/propel/components/avatar"; +import { Loader } from "@plane/ui"; // components import { getFileURL } from "@plane/utils"; import { FilterHeader, FilterOption } from "@/components/issues/issue-layouts/filters"; @@ -78,10 +79,10 @@ export const FilterMentions = observer(function FilterMentions(props: Props) { onClick={() => handleUpdate(member.id)} icon={ } title={currentUser?.id === member.id ? "You" : member?.display_name} diff --git a/apps/web/core/components/issues/issue-layouts/utils.tsx b/apps/web/core/components/issues/issue-layouts/utils.tsx index 1a0cd69729a..ecb40b07d04 100644 --- a/apps/web/core/components/issues/issue-layouts/utils.tsx +++ b/apps/web/core/components/issues/issue-layouts/utils.tsx @@ -12,6 +12,7 @@ import scrollIntoView from "smooth-scroll-into-view-if-needed"; import type { FC } from "react"; import { CalendarDays, LayersIcon, Paperclip } from "lucide-react"; // plane types +import { Avatar } from "@makeplane/propel/components/avatar"; import { EIconSize, ISSUE_PRIORITIES, STATE_GROUPS } from "@plane/constants"; import { Logo } from "@plane/propel/emoji-icon-picker"; import type { ISvgIcons } from "@plane/propel/icons"; @@ -47,7 +48,7 @@ import type { } from "@plane/types"; import { EIssuesStoreType } from "@plane/types"; // plane ui -import { Avatar } from "@plane/ui"; + import { renderFormattedDate, getFileURL } from "@plane/utils"; // store import { store } from "@/lib/store-context"; @@ -314,12 +315,19 @@ const getAssigneeColumns = ({ isWorkspaceLevel, projectId }: TGetColumns): IGrou assigneeColumns.push({ id: memberId, name: member?.display_name || "", - icon: , + icon: ( + + ), payload: { assignee_ids: [memberId] }, }); }); if (includeNone) { - assigneeColumns.push({ id: "None", name: "None", icon: , payload: {} }); + assigneeColumns.push({ id: "None", name: "None", icon: , payload: {} }); } return assigneeColumns; @@ -337,7 +345,14 @@ const getCreatedByColumns = (): IGroupByColumn[] | undefined => { return { id: memberId, name: member?.display_name || "", - icon: , + icon: ( + + ), payload: {}, }; }); diff --git a/apps/web/core/components/modules/applied-filters/members.tsx b/apps/web/core/components/modules/applied-filters/members.tsx index e280b1c2064..30c9615cf54 100644 --- a/apps/web/core/components/modules/applied-filters/members.tsx +++ b/apps/web/core/components/modules/applied-filters/members.tsx @@ -5,9 +5,8 @@ */ import { observer } from "mobx-react"; +import { Avatar } from "@makeplane/propel/components/avatar"; import { CloseIcon } from "@plane/propel/icons"; -// plane ui -import { Avatar } from "@plane/ui"; // helpers import { getFileURL } from "@plane/utils"; // hooks @@ -36,10 +35,10 @@ export const AppliedMembersFilters = observer(function AppliedMembersFilters(pro return (
{memberDetails.display_name} {editable && ( diff --git a/apps/web/core/components/modules/dropdowns/filters/lead.tsx b/apps/web/core/components/modules/dropdowns/filters/lead.tsx index 286759dd22a..b47ec8c3678 100644 --- a/apps/web/core/components/modules/dropdowns/filters/lead.tsx +++ b/apps/web/core/components/modules/dropdowns/filters/lead.tsx @@ -8,7 +8,8 @@ import { useMemo, useState } from "react"; import { sortBy } from "lodash-es"; import { observer } from "mobx-react"; // plane ui -import { Avatar, Loader } from "@plane/ui"; +import { Avatar } from "@makeplane/propel/components/avatar"; +import { Loader } from "@plane/ui"; // components import { getFileURL } from "@plane/utils"; import { FilterHeader, FilterOption } from "@/components/issues/issue-layouts/filters"; @@ -78,10 +79,10 @@ export const FilterLead = observer(function FilterLead(props: Props) { onClick={() => handleUpdate(member.id)} icon={ } title={currentUser?.id === member.id ? "You" : member?.display_name} diff --git a/apps/web/core/components/modules/dropdowns/filters/members.tsx b/apps/web/core/components/modules/dropdowns/filters/members.tsx index 1e94ac62cdc..b13b7e35886 100644 --- a/apps/web/core/components/modules/dropdowns/filters/members.tsx +++ b/apps/web/core/components/modules/dropdowns/filters/members.tsx @@ -8,7 +8,8 @@ import { useMemo, useState } from "react"; import { sortBy } from "lodash-es"; import { observer } from "mobx-react"; // plane ui -import { Avatar, Loader } from "@plane/ui"; +import { Avatar } from "@makeplane/propel/components/avatar"; +import { Loader } from "@plane/ui"; // components import { getFileURL } from "@plane/utils"; import { FilterHeader, FilterOption } from "@/components/issues/issue-layouts/filters"; @@ -78,10 +79,10 @@ export const FilterMembers = observer(function FilterMembers(props: Props) { onClick={() => handleUpdate(member.id)} icon={ } title={currentUser?.id === member.id ? "You" : member?.display_name} diff --git a/apps/web/core/components/pages/list/block-item-action.tsx b/apps/web/core/components/pages/list/block-item-action.tsx index 8d4408ef549..4ac3745b69b 100644 --- a/apps/web/core/components/pages/list/block-item-action.tsx +++ b/apps/web/core/components/pages/list/block-item-action.tsx @@ -7,9 +7,10 @@ import { observer } from "mobx-react"; import { Earth, Info, Minus } from "lucide-react"; // plane imports +import { Avatar } from "@makeplane/propel/components/avatar"; import { LockIcon } from "@plane/propel/icons"; import { Tooltip } from "@plane/propel/tooltip"; -import { Avatar, FavoriteStar } from "@plane/ui"; +import { FavoriteStar } from "@plane/ui"; import { renderFormattedDate, getFileURL } from "@plane/utils"; // hooks import { useMember } from "@/hooks/store/use-member"; @@ -44,7 +45,12 @@ export const BlockItemAction = observer(function BlockItemAction(props: Props) { {/* page details */}
- +
diff --git a/apps/web/core/components/pages/navigation-pane/tab-panels/info/actors-info.tsx b/apps/web/core/components/pages/navigation-pane/tab-panels/info/actors-info.tsx index f12067938cd..0a1f39e5ee2 100644 --- a/apps/web/core/components/pages/navigation-pane/tab-panels/info/actors-info.tsx +++ b/apps/web/core/components/pages/navigation-pane/tab-panels/info/actors-info.tsx @@ -8,8 +8,8 @@ import { observer } from "mobx-react"; import Link from "next/link"; import { useParams } from "next/navigation"; // plane imports +import { Avatar } from "@makeplane/propel/components/avatar"; import { useTranslation } from "@plane/i18n"; -import { Avatar } from "@plane/ui"; import { calculateTimeAgoShort, getFileURL, renderFormattedDate } from "@plane/utils"; // hooks import { useMember } from "@/hooks/store/use-member"; @@ -40,10 +40,10 @@ export const PageNavigationPaneInfoTabActorsInfo = observer(function PageNavigat
{editorInformation?.display_name ?? t("common.deactivated_user")} @@ -57,10 +57,10 @@ export const PageNavigationPaneInfoTabActorsInfo = observer(function PageNavigat
{creatorInformation?.display_name ?? t("common.deactivated_user")} diff --git a/apps/web/core/components/pages/navigation-pane/tab-panels/info/version-history.tsx b/apps/web/core/components/pages/navigation-pane/tab-panels/info/version-history.tsx index ac75db06245..f3a8e56e631 100644 --- a/apps/web/core/components/pages/navigation-pane/tab-panels/info/version-history.tsx +++ b/apps/web/core/components/pages/navigation-pane/tab-panels/info/version-history.tsx @@ -10,9 +10,9 @@ import Link from "next/link"; import { useSearchParams } from "next/navigation"; import useSWR from "swr"; // plane imports +import { Avatar } from "@makeplane/propel/components/avatar"; import { useTranslation } from "@plane/i18n"; import type { TPageVersion } from "@plane/types"; -import { Avatar } from "@plane/ui"; import { cn, getFileURL, renderFormattedDate, renderFormattedTime } from "@plane/utils"; // components import type { TPageRootHandlers } from "@/components/pages/editor/page-root"; @@ -62,10 +62,10 @@ const VersionHistoryItem = observer(function VersionHistoryItem(props: VersionHi

{versionCreator?.display_name ?? t("common.deactivated_user")}

diff --git a/apps/web/core/components/power-k/menus/members.tsx b/apps/web/core/components/power-k/menus/members.tsx index 4c9174da507..dc16d2e8f52 100644 --- a/apps/web/core/components/power-k/menus/members.tsx +++ b/apps/web/core/components/power-k/menus/members.tsx @@ -7,7 +7,8 @@ import { Command } from "cmdk"; import { observer } from "mobx-react"; // plane imports -import { Avatar } from "@plane/ui"; + +import { Avatar } from "@makeplane/propel/components/avatar"; import { getFileURL } from "@plane/utils"; // hooks import { useMember } from "@/hooks/store/use-member"; @@ -37,10 +38,10 @@ export const PowerKMembersMenu = observer(function PowerKMembersMenu(props: Prop key={memberId} iconNode={ } isSelected={value.includes(memberId)} diff --git a/apps/web/core/components/project/applied-filters/members.tsx b/apps/web/core/components/project/applied-filters/members.tsx index 6e7a8b92c07..35344a7e8b5 100644 --- a/apps/web/core/components/project/applied-filters/members.tsx +++ b/apps/web/core/components/project/applied-filters/members.tsx @@ -5,9 +5,8 @@ */ import { observer } from "mobx-react"; +import { Avatar } from "@makeplane/propel/components/avatar"; import { CloseIcon } from "@plane/propel/icons"; -// ui -import { Avatar } from "@plane/ui"; // helpers import { getFileURL } from "@plane/utils"; // types @@ -36,10 +35,10 @@ export const AppliedMembersFilters = observer(function AppliedMembersFilters(pro return (
{memberDetails.display_name} {editable && ( diff --git a/apps/web/core/components/project/card.tsx b/apps/web/core/components/project/card.tsx index c9286d15faf..3e3e8bca0c0 100644 --- a/apps/web/core/components/project/card.tsx +++ b/apps/web/core/components/project/card.tsx @@ -12,6 +12,7 @@ import { ArchiveRestoreIcon, Settings, UserPlus } from "lucide-react"; // plane imports import { EUserPermissions, EUserPermissionsLevel, IS_FAVORITE_MENU_OPEN } from "@plane/constants"; import { useLocalStorage } from "@plane/hooks"; +import { Avatar } from "@makeplane/propel/components/avatar"; import { Button } from "@plane/propel/button"; import { Logo } from "@plane/propel/emoji-icon-picker"; import { LinkIcon, LockIcon, NewTabIcon, TrashIcon, CheckIcon } from "@plane/propel/icons"; @@ -19,7 +20,7 @@ import { setPromiseToast, setToast, TOAST_TYPE } from "@plane/propel/toast"; import { Tooltip } from "@plane/propel/tooltip"; import type { IProject } from "@plane/types"; import type { TContextMenuItem } from "@plane/ui"; -import { Avatar, AvatarGroup, ContextMenu, FavoriteStar } from "@plane/ui"; +import { ContextMenu, FavoriteStar } from "@plane/ui"; import { copyUrlToClipboard, cn, getFileURL, renderFormattedDate } from "@plane/utils"; // components // hooks @@ -29,6 +30,7 @@ import { useUserPermissions } from "@/hooks/store/user"; import { useAppRouter } from "@/hooks/use-app-router"; import { usePlatformOS } from "@/hooks/use-platform-os"; // local imports +import { AvatarGroupOverflow } from "@/components/common/avatar-group-overflow"; import { CoverImage } from "@/components/common/cover-image"; import { DeleteProjectModal } from "./delete-project-modal"; import { JoinProjectModal } from "./join-project-modal"; @@ -288,15 +290,20 @@ export const ProjectCard = observer(function ProjectCard(props: Props) { > {projectMembersIds && projectMembersIds.length > 0 ? (
- + {projectMembersIds.map((memberId) => { const member = getUserDetails(memberId); if (!member) return null; return ( - + ); })} - +
) : ( No Member Yet diff --git a/apps/web/core/components/project/dropdowns/filters/lead.tsx b/apps/web/core/components/project/dropdowns/filters/lead.tsx index 286759dd22a..b47ec8c3678 100644 --- a/apps/web/core/components/project/dropdowns/filters/lead.tsx +++ b/apps/web/core/components/project/dropdowns/filters/lead.tsx @@ -8,7 +8,8 @@ import { useMemo, useState } from "react"; import { sortBy } from "lodash-es"; import { observer } from "mobx-react"; // plane ui -import { Avatar, Loader } from "@plane/ui"; +import { Avatar } from "@makeplane/propel/components/avatar"; +import { Loader } from "@plane/ui"; // components import { getFileURL } from "@plane/utils"; import { FilterHeader, FilterOption } from "@/components/issues/issue-layouts/filters"; @@ -78,10 +79,10 @@ export const FilterLead = observer(function FilterLead(props: Props) { onClick={() => handleUpdate(member.id)} icon={ } title={currentUser?.id === member.id ? "You" : member?.display_name} diff --git a/apps/web/core/components/project/dropdowns/filters/members.tsx b/apps/web/core/components/project/dropdowns/filters/members.tsx index 1e94ac62cdc..b13b7e35886 100644 --- a/apps/web/core/components/project/dropdowns/filters/members.tsx +++ b/apps/web/core/components/project/dropdowns/filters/members.tsx @@ -8,7 +8,8 @@ import { useMemo, useState } from "react"; import { sortBy } from "lodash-es"; import { observer } from "mobx-react"; // plane ui -import { Avatar, Loader } from "@plane/ui"; +import { Avatar } from "@makeplane/propel/components/avatar"; +import { Loader } from "@plane/ui"; // components import { getFileURL } from "@plane/utils"; import { FilterHeader, FilterOption } from "@/components/issues/issue-layouts/filters"; @@ -78,10 +79,10 @@ export const FilterMembers = observer(function FilterMembers(props: Props) { onClick={() => handleUpdate(member.id)} icon={ } title={currentUser?.id === member.id ? "You" : member?.display_name} diff --git a/apps/web/core/components/project/member-select.tsx b/apps/web/core/components/project/member-select.tsx index b55609c3daa..d813297d155 100644 --- a/apps/web/core/components/project/member-select.tsx +++ b/apps/web/core/components/project/member-select.tsx @@ -8,9 +8,10 @@ import React from "react"; import { observer } from "mobx-react"; import { useParams } from "next/navigation"; import { Ban } from "lucide-react"; +import { Avatar } from "@makeplane/propel/components/avatar"; import { EUserProjectRoles } from "@plane/types"; // plane ui -import { Avatar, CustomSearchSelect } from "@plane/ui"; +import { CustomSearchSelect } from "@plane/ui"; // helpers import { getFileURL } from "@plane/utils"; // hooks @@ -44,7 +45,12 @@ export const MemberSelect = observer(function MemberSelect(props: Props) { query: `${memberDetails?.member.display_name}`, content: (
- + {memberDetails?.member.display_name}
), @@ -65,7 +71,12 @@ export const MemberSelect = observer(function MemberSelect(props: Props) { label={
{selectedOption && ( - + )} {selectedOption ? ( selectedOption.member?.display_name diff --git a/apps/web/core/components/project/send-project-invitation-modal.tsx b/apps/web/core/components/project/send-project-invitation-modal.tsx index f57369ac14e..96092daf2da 100644 --- a/apps/web/core/components/project/send-project-invitation-modal.tsx +++ b/apps/web/core/components/project/send-project-invitation-modal.tsx @@ -8,12 +8,13 @@ import React, { useEffect } from "react"; import { observer } from "mobx-react"; import { useForm, Controller, useFieldArray } from "react-hook-form"; // plane imports +import { Avatar } from "@makeplane/propel/components/avatar"; import { ROLE, EUserPermissions } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; import { Button } from "@plane/propel/button"; import { PlusIcon, CloseIcon, ChevronDownIcon } from "@plane/propel/icons"; import { TOAST_TYPE, setToast } from "@plane/propel/toast"; -import { Avatar, CustomSelect, CustomSearchSelect, EModalPosition, EModalWidth, ModalCore } from "@plane/ui"; +import { CustomSelect, CustomSearchSelect, EModalPosition, EModalWidth, ModalCore } from "@plane/ui"; // helpers import { getFileURL } from "@plane/utils"; // hooks @@ -140,7 +141,12 @@ export const SendProjectInvitationModal = observer(function SendProjectInvitatio content: (
- +
{memberDetails?.member.display_name} ( @@ -200,8 +206,10 @@ export const SendProjectInvitationModal = observer(function SendProjectInvitatio {value && value !== "" ? (
{selectedMember?.member.display_name}
diff --git a/apps/web/core/components/settings/profile/sidebar/header.tsx b/apps/web/core/components/settings/profile/sidebar/header.tsx index 52f20f0a50b..a59fa2a43ca 100644 --- a/apps/web/core/components/settings/profile/sidebar/header.tsx +++ b/apps/web/core/components/settings/profile/sidebar/header.tsx @@ -6,10 +6,10 @@ import { observer } from "mobx-react"; // plane imports -import { Avatar } from "@plane/ui"; +import { Avatar } from "@makeplane/propel/components/avatar"; +import { getFileURL } from "@plane/utils"; // hooks import { useUser } from "@/hooks/store/user"; -import { getFileURL } from "@plane/utils"; export const ProfileSettingsSidebarHeader = observer(function ProfileSettingsSidebarHeader() { // store hooks @@ -19,11 +19,10 @@ export const ProfileSettingsSidebarHeader = observer(function ProfileSettingsSid
diff --git a/apps/web/core/components/workspace-notifications/sidebar/notification-card/item.tsx b/apps/web/core/components/workspace-notifications/sidebar/notification-card/item.tsx index 859070c3e0c..a2dc20fa30e 100644 --- a/apps/web/core/components/workspace-notifications/sidebar/notification-card/item.tsx +++ b/apps/web/core/components/workspace-notifications/sidebar/notification-card/item.tsx @@ -8,7 +8,8 @@ import { useState } from "react"; import { observer } from "mobx-react"; import { Clock } from "lucide-react"; // plane imports -import { Avatar, Row } from "@plane/ui"; +import { Avatar } from "@makeplane/propel/components/avatar"; +import { Row } from "@plane/ui"; import { cn, calculateTimeAgo, renderFormattedDate, renderFormattedTime, getFileURL } from "@plane/utils"; // hooks import { useWorkspaceNotifications } from "@/hooks/store/notifications"; @@ -87,11 +88,11 @@ export const NotificationItem = observer(function NotificationItem(props: TNotif
{notificationTriggeredBy && ( )}
diff --git a/apps/web/core/components/workspace/sidebar/user-menu-root.tsx b/apps/web/core/components/workspace/sidebar/user-menu-root.tsx index 153928414c8..d47cbba041c 100644 --- a/apps/web/core/components/workspace/sidebar/user-menu-root.tsx +++ b/apps/web/core/components/workspace/sidebar/user-menu-root.tsx @@ -9,10 +9,11 @@ import { observer } from "mobx-react"; import { useRouter } from "next/navigation"; import { LogOut, Settings, Settings2 } from "lucide-react"; // plane imports +import { Avatar } from "@makeplane/propel/components/avatar"; import { GOD_MODE_URL } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; import { TOAST_TYPE, setToast } from "@plane/propel/toast"; -import { Avatar, CustomMenu } from "@plane/ui"; +import { CustomMenu } from "@plane/ui"; import { getFileURL } from "@plane/utils"; // components import { CoverImage } from "@/components/common/cover-image"; @@ -62,10 +63,10 @@ export const UserMenuRoot = observer(function UserMenuRoot() { item={{ icon: ( ), isActive: isUserMenuOpen, @@ -91,11 +92,10 @@ export const UserMenuRoot = observer(function UserMenuRoot() {
diff --git a/apps/web/core/hooks/editor/use-editor-mention.tsx b/apps/web/core/hooks/editor/use-editor-mention.tsx index 910accae6a5..89ac01eca0f 100644 --- a/apps/web/core/hooks/editor/use-editor-mention.tsx +++ b/apps/web/core/hooks/editor/use-editor-mention.tsx @@ -6,11 +6,10 @@ import { useCallback } from "react"; // plane editor +import { Avatar } from "@makeplane/propel/components/avatar"; import type { TMentionSection, TMentionSuggestion } from "@plane/editor"; // plane types import type { TSearchEntities, TSearchEntityRequestPayload, TSearchResponse, TUserSearchResponse } from "@plane/types"; -// plane ui -import { Avatar } from "@plane/ui"; // helpers import { getFileURL } from "@plane/utils"; // plane web hooks @@ -47,9 +46,10 @@ export const useEditorMention = (args: TArgs) => { const items: TMentionSuggestion[] = (response as TUserSearchResponse[]).map((user) => ({ icon: ( ), id: user.member__id, diff --git a/apps/web/core/hooks/work-item-filters/use-work-item-filters-config.tsx b/apps/web/core/hooks/work-item-filters/use-work-item-filters-config.tsx index 78ac8242b7c..c9e0bce8671 100644 --- a/apps/web/core/hooks/work-item-filters/use-work-item-filters-config.tsx +++ b/apps/web/core/hooks/work-item-filters/use-work-item-filters-config.tsx @@ -7,6 +7,7 @@ import { useCallback, useMemo } from "react"; import { AtSign, Briefcase } from "lucide-react"; // plane imports +import { Avatar } from "@makeplane/propel/components/avatar"; import { Logo } from "@plane/propel/emoji-icon-picker"; import { CalendarLayoutIcon, @@ -33,7 +34,7 @@ import type { IProject, TWorkItemFilterProperty, } from "@plane/types"; -import { Avatar } from "@plane/ui"; + import { getAssigneeFilterConfig, getCreatedAtFilterConfig, @@ -222,10 +223,10 @@ export const useWorkItemFiltersConfig = (props: TUseWorkItemFiltersConfigProps): members: members ?? [], getOptionIcon: (memberDetails) => ( ), ...operatorConfigs, @@ -242,10 +243,10 @@ export const useWorkItemFiltersConfig = (props: TUseWorkItemFiltersConfigProps): members: members ?? [], getOptionIcon: (memberDetails) => ( ), ...operatorConfigs, @@ -262,10 +263,10 @@ export const useWorkItemFiltersConfig = (props: TUseWorkItemFiltersConfigProps): members: members ?? [], getOptionIcon: (memberDetails) => ( ), ...operatorConfigs, @@ -282,10 +283,10 @@ export const useWorkItemFiltersConfig = (props: TUseWorkItemFiltersConfigProps): members: members ?? [], getOptionIcon: (memberDetails) => ( ), ...operatorConfigs, From 60fb640203ec3b0f8966535d1cef45c2edd966b1 Mon Sep 17 00:00:00 2001 From: anmolsinghbhatia Date: Tue, 1 Sep 2026 16:29:02 +0530 Subject: [PATCH 2/2] refactor: use Propel Avatar for AvatarGroup overflow count Replace the custom CSS +N counter with a Propel Avatar fallback, matching the Avatar Group overflow pattern. Size still comes from the group context. --- .../common/avatar-group-overflow.tsx | 23 ++++--------------- 1 file changed, 5 insertions(+), 18 deletions(-) diff --git a/apps/web/core/components/common/avatar-group-overflow.tsx b/apps/web/core/components/common/avatar-group-overflow.tsx index 0c91a208391..368612521c3 100644 --- a/apps/web/core/components/common/avatar-group-overflow.tsx +++ b/apps/web/core/components/common/avatar-group-overflow.tsx @@ -6,14 +6,8 @@ import React from "react"; // plane imports +import { Avatar } from "@makeplane/propel/components/avatar"; import { AvatarGroup, type AvatarGroupSize } from "@makeplane/propel/components/avatar-group"; -import { cn } from "@plane/utils"; - -const OVERFLOW_COUNTER_SIZE: Record = { - "2xs": "size-4", - xs: "size-5", - sm: "size-6", -}; type Props = { children: React.ReactNode; @@ -33,7 +27,8 @@ type Props = { * An overlapping avatar stack that collapses the tail into a `+N` counter. * * Propel's `AvatarGroup` renders every child it is given, so the capping behaviour that - * `@plane/ui`'s `AvatarGroup` provided through `max` lives here as app chrome instead. + * `@plane/ui`'s `AvatarGroup` provided through `max` lives here as app chrome. The overflow + * indicator is a Propel `Avatar` with a `fallback`, matching the Avatar Group overflow pattern. */ export function AvatarGroupOverflow(props: Props) { const { children, size, max = 2 } = props; @@ -42,21 +37,13 @@ export function AvatarGroupOverflow(props: Props) { const totalAvatars = avatars.length; // If there is only one avatar past the limit, render it instead of a "+1" counter. const maxAvatarsToRender = totalAvatars <= max + 1 ? max + 1 : max; + const overflowCount = totalAvatars - max; return ( {avatars.slice(0, maxAvatarsToRender)} {maxAvatarsToRender < totalAvatars && ( -
- +{totalAvatars - max} -
+ )}
);