From f2e925de621395be81fb49d4a782c8cd2ae43e5a Mon Sep 17 00:00:00 2001 From: Johnpaul Chiwetelu <49923152+Myestery@users.noreply.github.com> Date: Fri, 26 Sep 2025 21:22:06 +0100 Subject: [PATCH] Right click vue nodes (#5790) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This pull request refactors and improves the "More Options" popover functionality for graph nodes in the UI. The main change is a rename and redesign of the menu component from `MoreOptions` to `NodeOptions`, introducing a global singleton pattern for popover control and enabling context menu support on node right-click. This results in better maintainability, more flexible triggering, and improved user experience. **Node Options popover refactor and global control:** * Renamed and refactored `MoreOptions.vue` to `NodeOptions.vue`, removing the embedded button and exposing imperative methods (`toggle`, `hide`, `isOpen`) for external control. The component now registers/unregisters itself globally via `registerNodeOptionsInstance`. [[1]](diffhunk://#diff-e0dbd5e37efd2c79e7317415455340b0dd150b758077b170a663f67d2453605eL2-R2) [[2]](diffhunk://#diff-e0dbd5e37efd2c79e7317415455340b0dd150b758077b170a663f67d2453605eL203-R197) [[3]](diffhunk://#diff-e0dbd5e37efd2c79e7317415455340b0dd150b758077b170a663f67d2453605eR294-R309) * Added `NodeOptionsButton.vue` as a dedicated button component for triggering the popover, decoupling the button UI from the popover logic. * Implemented a global singleton pattern in `useMoreOptionsMenu.ts` for controlling the `NodeOptions` popover from anywhere, with `toggleNodeOptions` and `registerNodeOptionsInstance` functions. [[1]](diffhunk://#diff-ae87bdb1e06725eb19b8d0fc82ec40a5f8ca831a6632767cc5d214fc903b89b6R35-R65) [[2]](diffhunk://#diff-ae87bdb1e06725eb19b8d0fc82ec40a5f8ca831a6632767cc5d214fc903b89b6L184-R216) **UI integration and event handling improvements:** * Updated `SelectionToolbox.vue` to use the new `NodeOptionsButton` instead of the previous embedded `MoreOptions` button, and added the `NodeOptions` popover to the main `GraphCanvas.vue` template for global accessibility. [[1]](diffhunk://#diff-05d80ee1e28e634dc758394ddf1bfaa8e5ec72a186a6ea2e2b6f5dfba867b264L41-R41) [[2]](diffhunk://#diff-05d80ee1e28e634dc758394ddf1bfaa8e5ec72a186a6ea2e2b6f5dfba867b264L71-R71) [[3]](diffhunk://#diff-aaf17c713f29c6db8ea03efe7fc3483a858982e818a324b23cff89859e71559cR65) [[4]](diffhunk://#diff-aaf17c713f29c6db8ea03efe7fc3483a858982e818a324b23cff89859e71559cR91) * Added right-click context menu support to `LGraphNode.vue`, triggering the node options popover at the cursor position and integrating with node selection logic. [[1]](diffhunk://#diff-a7744614cf842e54416047326db79ad81f7c7ab7bfb66ae2b46f5c73ac7d47f2R45) [[2]](diffhunk://#diff-a7744614cf842e54416047326db79ad81f7c7ab7bfb66ae2b46f5c73ac7d47f2R141) [[3]](diffhunk://#diff-a7744614cf842e54416047326db79ad81f7c7ab7bfb66ae2b46f5c73ac7d47f2L180-R187) [[4]](diffhunk://#diff-a7744614cf842e54416047326db79ad81f7c7ab7bfb66ae2b46f5c73ac7d47f2R249-R263) **Minor improvements and cleanup:** * Updated references and variable names throughout the codebase to reflect the new `NodeOptions` naming and logic. [[1]](diffhunk://#diff-e0dbd5e37efd2c79e7317415455340b0dd150b758077b170a663f67d2453605eL53) [[2]](diffhunk://#diff-e0dbd5e37efd2c79e7317415455340b0dd150b758077b170a663f67d2453605eR50) [[3]](diffhunk://#diff-e0dbd5e37efd2c79e7317415455340b0dd150b758077b170a663f67d2453605eL75-R60) [[4]](diffhunk://#diff-e0dbd5e37efd2c79e7317415455340b0dd150b758077b170a663f67d2453605eL91-L95) [[5]](diffhunk://#diff-e0dbd5e37efd2c79e7317415455340b0dd150b758077b170a663f67d2453605eL110-R90) [[6]](diffhunk://#diff-e0dbd5e37efd2c79e7317415455340b0dd150b758077b170a663f67d2453605eL133-R113) [[7]](diffhunk://#diff-e0dbd5e37efd2c79e7317415455340b0dd150b758077b170a663f67d2453605eL146-R126) [[8]](diffhunk://#diff-e0dbd5e37efd2c79e7317415455340b0dd150b758077b170a663f67d2453605eL157-R140) This refactor makes the node options menu more modular, easier to maintain, and more flexible for future UI improvements. https://github.com/user-attachments/assets/9c2f2556-4544-4e20-9f22-8f485b0ceadc ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-5790-Right-click-vue-nodes-27a6d73d365081a98263c88d2e09e629) by [Unito](https://www.unito.io) --- src/components/graph/GraphCanvas.vue | 2 + src/components/graph/SelectionToolbox.spec.ts | 7 -- src/components/graph/SelectionToolbox.vue | 4 +- .../{MoreOptions.vue => NodeOptions.vue} | 78 +++++++++++-------- .../selectionToolbox/NodeOptionsButton.vue | 33 ++++++++ src/composables/graph/useMoreOptionsMenu.ts | 46 ++++++++++- .../vueNodes/components/LGraphNode.vue | 25 +++++- 7 files changed, 149 insertions(+), 46 deletions(-) rename src/components/graph/selectionToolbox/{MoreOptions.vue => NodeOptions.vue} (86%) create mode 100644 src/components/graph/selectionToolbox/NodeOptionsButton.vue diff --git a/src/components/graph/GraphCanvas.vue b/src/components/graph/GraphCanvas.vue index f13b78d7f..260f4b9b6 100644 --- a/src/components/graph/GraphCanvas.vue +++ b/src/components/graph/GraphCanvas.vue @@ -62,6 +62,7 @@ @@ -87,6 +88,7 @@ import GraphCanvasMenu from '@/components/graph/GraphCanvasMenu.vue' import NodeTooltip from '@/components/graph/NodeTooltip.vue' import SelectionToolbox from '@/components/graph/SelectionToolbox.vue' import TitleEditor from '@/components/graph/TitleEditor.vue' +import NodeOptions from '@/components/graph/selectionToolbox/NodeOptions.vue' import NodeSearchboxPopover from '@/components/searchbox/NodeSearchBoxPopover.vue' import SideToolbar from '@/components/sidebar/SideToolbar.vue' import SecondRowWorkflowTabs from '@/components/topbar/SecondRowWorkflowTabs.vue' diff --git a/src/components/graph/SelectionToolbox.spec.ts b/src/components/graph/SelectionToolbox.spec.ts index 00ce74a51..e8e689bb2 100644 --- a/src/components/graph/SelectionToolbox.spec.ts +++ b/src/components/graph/SelectionToolbox.spec.ts @@ -480,13 +480,6 @@ describe('SelectionToolbox', () => { } as any) }) - it('should still show MoreOptions when no items selected', () => { - canvasStore.selectedItems = [] - const wrapper = mountComponent() - - expect(wrapper.find('.more-options').exists()).toBe(true) - }) - it('should hide most buttons when no items selected', () => { canvasStore.selectedItems = [] const wrapper = mountComponent() diff --git a/src/components/graph/SelectionToolbox.vue b/src/components/graph/SelectionToolbox.vue index 9970c0b47..d3622a515 100644 --- a/src/components/graph/SelectionToolbox.vue +++ b/src/components/graph/SelectionToolbox.vue @@ -38,7 +38,7 @@ :command="command" /> - + @@ -68,7 +68,7 @@ import { useExtensionService } from '@/services/extensionService' import { type ComfyCommandImpl, useCommandStore } from '@/stores/commandStore' import FrameNodes from './selectionToolbox/FrameNodes.vue' -import MoreOptions from './selectionToolbox/MoreOptions.vue' +import NodeOptionsButton from './selectionToolbox/NodeOptionsButton.vue' import VerticalDivider from './selectionToolbox/VerticalDivider.vue' const commandStore = useCommandStore() diff --git a/src/components/graph/selectionToolbox/MoreOptions.vue b/src/components/graph/selectionToolbox/NodeOptions.vue similarity index 86% rename from src/components/graph/selectionToolbox/MoreOptions.vue rename to src/components/graph/selectionToolbox/NodeOptions.vue index 32729719c..beda4e6ed 100644 --- a/src/components/graph/selectionToolbox/MoreOptions.vue +++ b/src/components/graph/selectionToolbox/NodeOptions.vue @@ -1,20 +1,5 @@