UI - МЕЖПРОЕКТНАЯ КОММУНИКАЦИЯ: горизонтальное меню карточек без изменения сетки канбана

This commit is contained in:
DCCONSTRUCTIONS
2026-04-29 16:42:52 +03:00
parent 4dbb7b500c
commit 5f9d9c418e
4 changed files with 94 additions and 17 deletions
@@ -96,7 +96,7 @@ export const InternalContourKanbanCard = observer(function InternalContourKanban
};
const menuContentBefore = ({ closeDropdown }: { closeDropdown: () => void }) => (
<>
<div className="space-y-1">
<div className="nodedc-work-item-action-section space-y-1">
<div className="px-2 text-[10px] font-semibold tracking-[0.16em] text-tertiary uppercase">Приоритет</div>
{priorityOptions.map((priority) => (
<button
@@ -115,7 +115,7 @@ export const InternalContourKanbanCard = observer(function InternalContourKanban
))}
</div>
<div className="space-y-1 border-t border-white/8 pt-2">
<div className="nodedc-work-item-action-section space-y-1">
<div className="px-2 text-[10px] font-semibold tracking-[0.16em] text-tertiary uppercase">Статус</div>
{stateOptions.map((state) => (
<button
@@ -138,12 +138,6 @@ export const InternalContourKanbanCard = observer(function InternalContourKanban
</button>
))}
</div>
<div className="border-t border-white/8 pt-2">
<div className="px-2 text-[10px] font-semibold tracking-[0.16em] text-tertiary uppercase">
Быстрые действия
</div>
</div>
</>
);
const dateButton = (
@@ -214,7 +208,7 @@ export const InternalContourKanbanCard = observer(function InternalContourKanban
issue,
parentRef: cardRef,
customActionButton,
menuClassName: "min-w-[18rem]",
menuClassName: "nodedc-work-item-action-menu",
menuContentBefore,
placement: "bottom-end",
})}
@@ -12,7 +12,8 @@ import { useParams } from "next/navigation";
import { ARCHIVABLE_STATE_GROUPS, EUserPermissions, EUserPermissionsLevel } from "@plane/constants";
import type { TIssue } from "@plane/types";
import { EIssuesStoreType } from "@plane/types";
import { ActionDropdown, ContextMenu } from "@plane/ui";
import { ActionDropdown, ContextMenu, type TContextMenuItem } from "@plane/ui";
import { cn } from "@plane/utils";
// hooks
import { useIssues } from "@/hooks/store/use-issues";
import { useProject } from "@/hooks/store/use-project";
@@ -102,6 +103,56 @@ export const ProjectIssueQuickActions = observer(function ProjectIssueQuickActio
};
const MENU_ITEMS = useProjectIssueMenuItems(menuItemProps);
const shouldUseNodedcActionGrid = menuClassName?.includes("nodedc-work-item-action-menu") ?? false;
const DROPDOWN_MENU_ITEMS = shouldUseNodedcActionGrid
? MENU_ITEMS.filter((item) => item.key !== "open-in-new-tab")
: MENU_ITEMS;
const renderNodedcMenuItem = (item: TContextMenuItem, closeDropdown: () => void) => {
if (item.shouldRender === false) return null;
const Icon = item.icon;
return (
<button
key={item.key}
type="button"
className={cn(
"flex w-full items-center gap-2 rounded-[0.9rem] px-2.5 py-2 text-left text-12 text-secondary transition-colors",
{
"cursor-not-allowed text-placeholder": item.disabled,
"hover:bg-white/6": !item.disabled,
},
item.className
)}
disabled={item.disabled}
onClick={(event) => {
event.preventDefault();
event.stopPropagation();
if (item.disabled) return;
item.action();
closeDropdown();
}}
>
{Icon && <Icon className={cn("h-3.5 w-3.5 shrink-0", item.iconClassName)} />}
<span className="min-w-0 truncate">{item.title}</span>
</button>
);
};
const renderNodedcMenuContent = ({ closeDropdown }: { closeDropdown: () => void }) => (
<div className="nodedc-work-item-action-grid">
{typeof menuContentBefore === "function" ? menuContentBefore({ closeDropdown }) : menuContentBefore}
<div className="nodedc-work-item-action-section space-y-1">
<div className="px-2 text-[10px] font-semibold tracking-[0.16em] text-tertiary uppercase">
Быстрые действия
</div>
{DROPDOWN_MENU_ITEMS.map((item) => renderNodedcMenuItem(item, closeDropdown))}
</div>
</div>
);
const CONTEXT_MENU_ITEMS = MENU_ITEMS.map(function CONTEXT_MENU_ITEMS(item) {
return {
@@ -153,9 +204,10 @@ export const ProjectIssueQuickActions = observer(function ProjectIssueQuickActio
<ContextMenu parentRef={parentRef} items={CONTEXT_MENU_ITEMS} />
<ActionDropdown
button={customActionButton}
items={MENU_ITEMS}
items={shouldUseNodedcActionGrid ? [] : MENU_ITEMS}
menuClassName={menuClassName}
menuContentBefore={menuContentBefore}
menuContent={shouldUseNodedcActionGrid ? renderNodedcMenuContent : undefined}
menuContentBefore={shouldUseNodedcActionGrid ? undefined : menuContentBefore}
placement={placements}
portalElement={portalElement}
/>