From e21f43f398bc0643c7eb2bc42736aea02756ec44 Mon Sep 17 00:00:00 2001 From: Johnpaul Chiwetelu <49923152+Myestery@users.noreply.github.com> Date: Wed, 17 Dec 2025 06:47:28 +0100 Subject: [PATCH] [feat] Replace NodeOptions with PrimeVue ContextMenu (#7114) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary - Add `NodeContextMenu.vue` using PrimeVue ContextMenu component with native submenu support - Rename `SubmenuPopover.vue` to `ColorPickerMenu.vue` (specialized for color picker) - Delete old components: `NodeOptions.vue`, `MenuOptionItem.vue`, `useSubmenuPositioning.ts` - Wire up context menu converter in `useMoreOptionsMenu.ts` - Update tests to use hover instead of click for submenus ## Dependencies **This PR depends on #7113** - the context menu converter infrastructure PR. It should be merged after that PR. ## Benefits - Native PrimeVue submenu support with proper keyboard navigation - Constrained menu dimensions with overflow scrolling (max-h-[80vh]) - Cleaner component architecture with ~280 fewer lines of code - Better separation: ColorPickerMenu handles only the custom color picker UI ## Test plan - [x] Typecheck passes - [x] Lint passes - [x] Knip passes - [ ] Browser tests for submenu interactions pass - [ ] Manual testing of node context menu ## Screenshots (Menu UI should look the same, with improved submenu behavior) ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-7114-feat-Replace-NodeOptions-with-PrimeVue-ContextMenu-2be6d73d365081fda576fd691175eacf) by [Unito](https://www.unito.io) --------- Co-authored-by: GitHub Action --- .../tests/selectionToolboxSubmenus.spec.ts | 13 +- src/components/graph/GraphCanvas.vue | 2 - src/components/graph/NodeContextMenu.vue | 272 +++++++++++++++ src/components/graph/SelectionToolbox.test.ts | 1 + src/components/graph/SelectionToolbox.vue | 2 + ...SubmenuPopover.vue => ColorPickerMenu.vue} | 25 +- .../graph/selectionToolbox/MenuOptionItem.vue | 62 ---- .../graph/selectionToolbox/NodeOptions.vue | 322 ------------------ .../selectionToolbox/NodeOptionsButton.vue | 10 +- .../canvas/useSelectionToolboxPosition.ts | 8 +- src/composables/graph/useMoreOptionsMenu.ts | 175 ++++++---- src/composables/graph/useNodeMenuOptions.ts | 3 +- .../graph/useSubmenuPositioning.ts | 163 --------- src/locales/en/main.json | 4 +- .../vueNodes/components/LGraphNode.vue | 5 +- 15 files changed, 410 insertions(+), 657 deletions(-) create mode 100644 src/components/graph/NodeContextMenu.vue rename src/components/graph/selectionToolbox/{SubmenuPopover.vue => ColorPickerMenu.vue} (84%) delete mode 100644 src/components/graph/selectionToolbox/MenuOptionItem.vue delete mode 100644 src/components/graph/selectionToolbox/NodeOptions.vue delete mode 100644 src/composables/graph/useSubmenuPositioning.ts diff --git a/browser_tests/tests/selectionToolboxSubmenus.spec.ts b/browser_tests/tests/selectionToolboxSubmenus.spec.ts index 5c7d380a5..f526b07e0 100644 --- a/browser_tests/tests/selectionToolboxSubmenus.spec.ts +++ b/browser_tests/tests/selectionToolboxSubmenus.spec.ts @@ -85,7 +85,7 @@ test.describe('Selection Toolbox - More Options Submenus', () => { const initialShape = await nodeRef.getProperty('shape') await openMoreOptions(comfyPage) - await comfyPage.page.getByText('Shape', { exact: true }).click() + await comfyPage.page.getByText('Shape', { exact: true }).hover() await expect(comfyPage.page.getByText('Box', { exact: true })).toBeVisible({ timeout: 5000 }) @@ -136,13 +136,18 @@ test.describe('Selection Toolbox - More Options Submenus', () => { comfyPage }) => { await openMoreOptions(comfyPage) - await expect( - comfyPage.page.getByText('Rename', { exact: true }) - ).toBeVisible({ timeout: 5000 }) + const renameItem = comfyPage.page.getByText('Rename', { exact: true }) + await expect(renameItem).toBeVisible({ timeout: 5000 }) + + // Wait for multiple frames to allow PrimeVue's outside click handler to initialize + for (let i = 0; i < 30; i++) { + await comfyPage.nextFrame() + } await comfyPage.page .locator('#graph-canvas') .click({ position: { x: 0, y: 50 }, force: true }) + await comfyPage.nextFrame() await expect( comfyPage.page.getByText('Rename', { exact: true }) diff --git a/src/components/graph/GraphCanvas.vue b/src/components/graph/GraphCanvas.vue index 06c46da35..48d82e44b 100644 --- a/src/components/graph/GraphCanvas.vue +++ b/src/components/graph/GraphCanvas.vue @@ -87,7 +87,6 @@ @@ -115,7 +114,6 @@ 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 NodePropertiesPanel from '@/components/rightSidePanel/RightSidePanel.vue' import NodeSearchboxPopover from '@/components/searchbox/NodeSearchBoxPopover.vue' import SideToolbar from '@/components/sidebar/SideToolbar.vue' diff --git a/src/components/graph/NodeContextMenu.vue b/src/components/graph/NodeContextMenu.vue new file mode 100644 index 000000000..632108274 --- /dev/null +++ b/src/components/graph/NodeContextMenu.vue @@ -0,0 +1,272 @@ + + + diff --git a/src/components/graph/SelectionToolbox.test.ts b/src/components/graph/SelectionToolbox.test.ts index e8e689bb2..0938a3fe3 100644 --- a/src/components/graph/SelectionToolbox.test.ts +++ b/src/components/graph/SelectionToolbox.test.ts @@ -136,6 +136,7 @@ describe('SelectionToolbox', () => { '
', props: ['pt', 'style', 'class'] }, + NodeContextMenu: { template: '
' }, InfoButton: { template: '
' }, ColorPickerButton: { template: diff --git a/src/components/graph/SelectionToolbox.vue b/src/components/graph/SelectionToolbox.vue index 06626ab1e..a56a82cf9 100644 --- a/src/components/graph/SelectionToolbox.vue +++ b/src/components/graph/SelectionToolbox.vue @@ -42,6 +42,7 @@
+ diff --git a/src/components/graph/selectionToolbox/NodeOptions.vue b/src/components/graph/selectionToolbox/NodeOptions.vue deleted file mode 100644 index 3a8461f05..000000000 --- a/src/components/graph/selectionToolbox/NodeOptions.vue +++ /dev/null @@ -1,322 +0,0 @@ - - - diff --git a/src/components/graph/selectionToolbox/NodeOptionsButton.vue b/src/components/graph/selectionToolbox/NodeOptionsButton.vue index 2b4e613c2..91c05d371 100644 --- a/src/components/graph/selectionToolbox/NodeOptionsButton.vue +++ b/src/components/graph/selectionToolbox/NodeOptionsButton.vue @@ -1,6 +1,5 @@