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 && ( + + )}