diff --git a/plane-src/apps/web/core/components/common/selection-dropdown.tsx b/plane-src/apps/web/core/components/common/selection-dropdown.tsx
index 2bf0dff..acecfbc 100644
--- a/plane-src/apps/web/core/components/common/selection-dropdown.tsx
+++ b/plane-src/apps/web/core/components/common/selection-dropdown.tsx
@@ -21,7 +21,7 @@ export type TSelectionDropdownOption = {
type Props = {
disabled?: boolean;
- menuButton: ReactNode;
+ menuButton: ReactNode | ((props: { open: boolean }) => ReactNode);
menuButtonWrapperClassName?: string;
options: TSelectionDropdownOption[];
placement?: Placement;
diff --git a/plane-src/apps/web/core/components/core/description-versions/dropdown-item.tsx b/plane-src/apps/web/core/components/core/description-versions/dropdown-item.tsx
index b8abb5b..05d4913 100644
--- a/plane-src/apps/web/core/components/core/description-versions/dropdown-item.tsx
+++ b/plane-src/apps/web/core/components/core/description-versions/dropdown-item.tsx
@@ -8,7 +8,7 @@ import { observer } from "mobx-react";
// plane imports
import { useTranslation } from "@plane/i18n";
import type { TDescriptionVersion } from "@plane/types";
-import { Avatar, CustomMenu } from "@plane/ui";
+import { Avatar } from "@plane/ui";
import { calculateTimeAgo, getFileURL } from "@plane/utils";
// hooks
import { useMember } from "@/hooks/store/use-member";
@@ -28,7 +28,7 @@ export const DescriptionVersionsDropdownItem = observer(function DescriptionVers
const { t } = useTranslation();
return (
- onClick(version.id)}>
+
-
+
);
});
diff --git a/plane-src/apps/web/core/components/core/description-versions/dropdown.tsx b/plane-src/apps/web/core/components/core/description-versions/dropdown.tsx
index 7749066..99c3c41 100644
--- a/plane-src/apps/web/core/components/core/description-versions/dropdown.tsx
+++ b/plane-src/apps/web/core/components/core/description-versions/dropdown.tsx
@@ -9,12 +9,11 @@ import { History } from "lucide-react";
// plane imports
import { useTranslation } from "@plane/i18n";
import type { TDescriptionVersion } from "@plane/types";
-import { CustomMenu } from "@plane/ui";
-import { calculateTimeAgo } from "@plane/utils";
+import { Avatar } from "@plane/ui";
+import { calculateTimeAgo, cn, getFileURL } from "@plane/utils";
// hooks
import { useMember } from "@/hooks/store/use-member";
-// local imports
-import { DescriptionVersionsDropdownItem } from "./dropdown-item";
+import { SelectionDropdown } from "@/components/common/selection-dropdown";
import type { TDescriptionVersionEntityInformation } from "./root";
type Props = {
@@ -34,13 +33,21 @@ export const DescriptionVersionsDropdown = observer(function DescriptionVersions
const lastUpdatedByUserDisplayName = latestVersion?.owned_by
? getUserDetails(latestVersion?.owned_by)?.display_name
: entityInformation.createdByDisplayName;
+ const latestVersionId = latestVersion?.id;
// translation
const { t } = useTranslation();
return (
-
+ (
+
@@ -50,18 +57,32 @@ export const DescriptionVersionsDropdown = observer(function DescriptionVersions
{calculateTimeAgo(lastUpdatedAt)}
+ )}
+ menuButtonWrapperClassName="rounded-sm"
+ options={
+ versions?.map((version) => {
+ const versionCreator = version.owned_by ? getUserDetails(version.owned_by) : null;
+
+ return {
+ key: version.id,
+ isChecked: version.id === latestVersionId,
+ onClick: () => onVersionClick(version.id),
+ icon: (
+
+ ),
+ title: (
+
+ {versionCreator?.display_name ?? t("common.deactivated_user")}
+ {calculateTimeAgo(version.last_saved_at)}
+
+ ),
+ };
+ }) ?? []
}
- noBorder
- noChevron={disabled}
- placement="bottom-end"
- optionsClassName="w-[300px]"
- disabled={disabled}
- closeOnSelect
- >
- {t("description_versions.previously_edited_by")}
- {versions?.map((version) => (
-
- ))}
-
+ />
);
});
diff --git a/plane-src/apps/web/core/components/issues/issue-layouts/filters/header/helpers/dropdown.tsx b/plane-src/apps/web/core/components/issues/issue-layouts/filters/header/helpers/dropdown.tsx
index 1cf5207..99f90ad 100644
--- a/plane-src/apps/web/core/components/issues/issue-layouts/filters/header/helpers/dropdown.tsx
+++ b/plane-src/apps/web/core/components/issues/issue-layouts/filters/header/helpers/dropdown.tsx
@@ -20,7 +20,7 @@ type Props = {
placement?: Placement;
disabled?: boolean;
tabIndex?: number;
- menuButton?: React.ReactNode;
+ menuButton?: React.ReactNode | ((props: { open: boolean }) => React.ReactNode);
menuButtonWrapperClassName?: string;
isFiltersApplied?: boolean;
};
@@ -58,7 +58,7 @@ export function FiltersDropdown(props: Props) {
className={menuButtonWrapperClassName}
disabled={disabled}
>
- {menuButton}
+ {typeof menuButton === "function" ? menuButton({ open }) : menuButton}
) : (
diff --git a/plane-src/apps/web/core/components/labels/label-block/label-item-block.tsx b/plane-src/apps/web/core/components/labels/label-block/label-item-block.tsx
index 7f8bc07..d1cfaa8 100644
--- a/plane-src/apps/web/core/components/labels/label-block/label-item-block.tsx
+++ b/plane-src/apps/web/core/components/labels/label-block/label-item-block.tsx
@@ -5,17 +5,17 @@
*/
import type { MutableRefObject } from "react";
-import { useRef, useState } from "react";
+import { useState } from "react";
import type { LucideIcon } from "lucide-react";
// plane helpers
import { PROJECT_SETTINGS_TRACKER_ELEMENTS } from "@plane/constants";
-import { useOutsideClickDetector } from "@plane/hooks";
import type { ISvgIcons } from "@plane/propel/icons";
import { CloseIcon } from "@plane/propel/icons";
// types
import type { IIssueLabel } from "@plane/types";
// ui
-import { CustomMenu, DragHandle } from "@plane/ui";
+import type { TContextMenuItem } from "@plane/ui";
+import { ActionDropdown, DragHandle } from "@plane/ui";
// helpers
import { cn } from "@plane/utils";
// components
@@ -52,11 +52,20 @@ export function LabelItemBlock(props: ILabelItemBlock) {
draggable = true,
} = props;
// states
- const [isMenuActive, setIsMenuActive] = useState(true);
- // refs
- const actionSectionRef = useRef
(null);
+ const [isMenuActive, setIsMenuActive] = useState(false);
- useOutsideClickDetector(actionSectionRef, () => setIsMenuActive(false));
+ const actionMenuItems: TContextMenuItem[] = customMenuItems
+ .filter(({ isVisible }) => isVisible)
+ .map(({ onClick, CustomIcon, text, key }) => ({
+ key,
+ action: () => onClick(label),
+ customContent: (
+
+
+ {text}
+
+ ),
+ }));
return (
@@ -74,26 +83,13 @@ export function LabelItemBlock(props: ILabelItemBlock) {
{!disabled && (
-
setIsMenuActive(!isMenuActive)} useCaptureForOutsideClick>
- {customMenuItems.map(
- ({ isVisible, onClick, CustomIcon, text, key }) =>
- isVisible && (
- onClick(label)}>
-
-
- {text}
-
-
- )
- )}
-
+
{!isLabelGroup && (
{menuItems && (
-
- {menuItems.map((item) => (
- {
- e.preventDefault();
- e.stopPropagation();
- item.action();
- }}
- className={cn("flex w-full items-center gap-2", {
- "text-placeholder": item.disabled,
- })}
- disabled={item.disabled}
- >
- {item.icon && }
-
-
{item.title}
- {item.description && (
-
- {item.description}
-
- )}
-
-
- ))}
-
+
+
+
+ }
+ buttonClassName="grid place-items-center"
+ items={menuItems}
+ />
)}