From fdf9a49e2817da1769004caf09c790a164d7bf69 Mon Sep 17 00:00:00 2001
From: llamantino <213239228+llamantino@users.noreply.github.com>
Date: Wed, 30 Jul 2025 17:09:56 +0200
Subject: [PATCH] feat(frontend): improve conversation card context menu
(#9917)
---
.../context-menu/context-menu-icon-text.tsx | 22 +++++
.../context-menu/context-menu-list-item.tsx | 2 +-
.../features/context-menu/context-menu.tsx | 2 +-
.../conversation-card-context-menu.tsx | 92 ++++++++++++++-----
4 files changed, 95 insertions(+), 23 deletions(-)
create mode 100644 frontend/src/components/features/context-menu/context-menu-icon-text.tsx
diff --git a/frontend/src/components/features/context-menu/context-menu-icon-text.tsx b/frontend/src/components/features/context-menu/context-menu-icon-text.tsx
new file mode 100644
index 0000000000..896e4ac5dc
--- /dev/null
+++ b/frontend/src/components/features/context-menu/context-menu-icon-text.tsx
@@ -0,0 +1,22 @@
+import { cn } from "#/utils/utils";
+
+interface ContextMenuIconTextProps {
+ icon: React.ComponentType<{ className?: string }>;
+ text: string;
+ className?: string;
+ iconClassName?: string;
+}
+
+export function ContextMenuIconText({
+ icon: Icon,
+ text,
+ className,
+ iconClassName,
+}: ContextMenuIconTextProps) {
+ return (
+
+
+ {text}
+
+ );
+}
diff --git a/frontend/src/components/features/context-menu/context-menu-list-item.tsx b/frontend/src/components/features/context-menu/context-menu-list-item.tsx
index deb87e1240..a814606769 100644
--- a/frontend/src/components/features/context-menu/context-menu-list-item.tsx
+++ b/frontend/src/components/features/context-menu/context-menu-list-item.tsx
@@ -19,7 +19,7 @@ export function ContextMenuListItem({
onClick={onClick}
disabled={isDisabled}
className={cn(
- "text-sm px-4 py-2 w-full text-start hover:bg-white/10 first-of-type:rounded-t-md last-of-type:rounded-b-md",
+ "text-sm px-4 h-10 w-full text-start hover:bg-white/10 cursor-pointer",
"disabled:opacity-50 disabled:cursor-not-allowed disabled:hover:bg-transparent text-nowrap",
)}
>
diff --git a/frontend/src/components/features/context-menu/context-menu.tsx b/frontend/src/components/features/context-menu/context-menu.tsx
index 38a5cc0312..425d2ba3dc 100644
--- a/frontend/src/components/features/context-menu/context-menu.tsx
+++ b/frontend/src/components/features/context-menu/context-menu.tsx
@@ -18,7 +18,7 @@ export function ContextMenu({
diff --git a/frontend/src/components/features/conversation-panel/conversation-card-context-menu.tsx b/frontend/src/components/features/conversation-panel/conversation-card-context-menu.tsx
index 8eb6742bca..8298f008c0 100644
--- a/frontend/src/components/features/conversation-panel/conversation-card-context-menu.tsx
+++ b/frontend/src/components/features/conversation-panel/conversation-card-context-menu.tsx
@@ -1,9 +1,20 @@
+import {
+ Trash,
+ Power,
+ Pencil,
+ Download,
+ Wallet,
+ Wrench,
+ Bot,
+} from "lucide-react";
import { useTranslation } from "react-i18next";
import { useClickOutsideElement } from "#/hooks/use-click-outside-element";
import { cn } from "#/utils/utils";
import { ContextMenu } from "../context-menu/context-menu";
import { ContextMenuListItem } from "../context-menu/context-menu-list-item";
+import { ContextMenuSeparator } from "../context-menu/context-menu-separator";
import { I18nKey } from "#/i18n/declaration";
+import { ContextMenuIconText } from "../context-menu/context-menu-icon-text";
interface ConversationCardContextMenuProps {
onClose: () => void;
@@ -31,6 +42,12 @@ export function ConversationCardContextMenu({
const { t } = useTranslation();
const ref = useClickOutsideElement(onClose);
+ const hasEdit = Boolean(onEdit);
+ const hasDownload = Boolean(onDownloadViaVSCode);
+ const hasTools = Boolean(onShowAgentTools || onShowMicroagents);
+ const hasInfo = Boolean(onDisplayCost);
+ const hasControl = Boolean(onStop || onDelete);
+
return (
- {onDelete && (
-
- {t(I18nKey.BUTTON$DELETE)}
-
- )}
- {onStop && (
-
- {t(I18nKey.BUTTON$STOP)}
-
- )}
{onEdit && (
- {t(I18nKey.BUTTON$EDIT_TITLE)}
+
)}
+
+ {hasEdit && (hasDownload || hasTools || hasInfo || hasControl) && (
+
+ )}
+
{onDownloadViaVSCode && (
- {t(I18nKey.BUTTON$DOWNLOAD_VIA_VSCODE)}
+
)}
- {onDisplayCost && (
-
- {t(I18nKey.BUTTON$DISPLAY_COST)}
-
+
+ {hasDownload && (hasTools || hasInfo || hasControl) && (
+
)}
+
{onShowAgentTools && (
- {t(I18nKey.BUTTON$SHOW_AGENT_TOOLS_AND_METADATA)}
+
)}
+
{onShowMicroagents && (
- {t(I18nKey.CONVERSATION$SHOW_MICROAGENTS)}
+
+
+ )}
+
+ {hasTools && (hasInfo || hasControl) && }
+
+ {onDisplayCost && (
+
+
+
+ )}
+
+ {hasInfo && hasControl && }
+
+ {onStop && (
+
+
+
+ )}
+
+ {onDelete && (
+
+
)}