mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-02-04 07:00:23 +00:00
bfe083dcbad61965b0ef04cf91d06a9cddaca361
139 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
bfe083dcba |
Move subgraph badge into node title (#6115)
<img width="1350" height="691" alt="image" src="https://github.com/user-attachments/assets/4a1a909f-463e-4c77-8855-6fe0a177b659" /> Design docs show icon as being reversed in litegraph mode. If needed, fixing this is basically just removing a negative sign. LiteGraph implementation was not as clean as I hoped. I can spend some more time divining some non-magic constants, and mayybe resolve the svg data from css styles if desired. Resolves #4647 Resolves #6107 ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-6115-Move-subgraph-badge-into-node-title-2906d73d365081e4ba82d321fc27afed) by [Unito](https://www.unito.io) --------- Co-authored-by: GitHub Action <action@github.com> |
||
|
|
653cf64e01 |
[chore] Upgrade Prettier from 3.3.2 to 3.6.2 (#6089)
## Summary - Updated Prettier from 3.3.2 to 3.6.2 in pnpm-workspace.yaml - Ran `pnpm install` to update dependencies - Ran `pnpm format` to apply new formatting rules - Verified typecheck passes ## Test plan - [x] TypeScript typecheck passes - [x] Prettier formatting applied successfully 🤖 Generated with [Claude Code](https://claude.com/claude-code) ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-6089-chore-Upgrade-Prettier-from-3-3-2-to-3-6-2-28e6d73d3650816a888ff1129b14e0bc) by [Unito](https://www.unito.io) --------- Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Christian Byrne <cbyrne@comfy.org> |
||
|
|
15b1b91b16 |
Implement a legacy canvas widget for vue mode (#6011)
 ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-6011-Implement-a-legacy-canvas-widget-for-vue-mode-2896d73d36508127a5d1debcccb519a0) by [Unito](https://www.unito.io) --------- Co-authored-by: GitHub Action <action@github.com> |
||
|
|
e48e11e434 |
fix LiteGraph capturing node pointer events if Vue and LG node positions become desynced (#6058)
## Summary Added Vue mode guards to LiteGraph canvas to prevent dual event handling between Vue node components and LiteGraph node event handlers. Fixes a bug where the litegraph and vue positions become out of sync and then there are effectively dead spots on the canvas (the user should still be able to interact with the graph even if the positions desync - the only real downside of desync should just be mispositioned nodes in the serialized state). Returns early only in `processNodeClick` and the node-related (alt+click+drag node cloning) canvas handlers. In general, the LiteGraph canvas still owns some events/interactions - but the node interactions are fully owned by Vue when in Vue nodes mode. ## Changes - **What**: Added `LiteGraph.vueNodesMode` checks in [LGraphCanvas.ts](src/lib/litegraph/src/LGraphCanvas.ts) to skip native event processing when Vue components handle interactions - **Breaking**: This could have some side effects or break some extensions if anything was relying on these. However, prior to this change, things like `processNodeClick` should only have been getting the click events in de-sync scenarios anyway (described in [Summary](##Summary) section) ## Review Focus Any possible side-effects you can think of. ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-6058-fix-LiteGraph-capturing-node-pointer-events-if-Vue-and-LG-node-positions-become-desynced-28c6d73d365081f389f8c72299c31b0b) by [Unito](https://www.unito.io) |
||
|
|
984ebef416 |
Floating Menus - UI rework (#5980)
## Summary
Enhancing and further modernizing the UI, giving users more usable area
whilst keeping farmiliar positioning and feel of elements.
## Changes
- **What**: Significant restructure of the UI elements, changing
elements from large blocks to floating elements, updating:
- Side toolbar menu (floating style, supports small/normal mode,
combines to scroll on height overflow)
- Bottom tabs panel (floating style, tabs redesigned)
- Action bar (support for docking/undocking menu)
- Added login/user menu button to top right
- Restyled breadcrumbs (still collapse when overflows)
- Add litegraph support for fps info position (so it isn't covered by
the sidebar)
- **Breaking**:
- Removed various elements and added new ones, I have tested custom
sidebars, custom actions, etc but if scripts are inserting elements into
"other" elements they may have been (re)moved.
- Remove support for bottom menu
- Remove support for 2nd-row tabs
## Screenshots
<img width="1116" height="907" alt="ui"
src="https://github.com/user-attachments/assets/b040a215-67d3-4c88-8c4d-f402a16a34f6"
/>
https://github.com/user-attachments/assets/571dbda5-01ec-47e8-b235-ee1b88c93dd0
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5980-Floating-Menus-UI-rework-2866d73d3650810aac60cc1afe979b60)
by [Unito](https://www.unito.io)
---------
Co-authored-by: GitHub Action <action@github.com>
Co-authored-by: github-actions <github-actions@github.com>
|
||
|
|
d7796fcda4 |
Vuenodes/audio widgets (#5627)
This pull request introduces a new audio playback widget for node UIs and integrates it into the node widget system. The main changes include the implementation of the `WidgetAudioUI` component, its registration in the widget registry, and updates to pass node data to the new widget. Additionally, some logging was added for debugging purposes. **Audio Widget Implementation and Integration:** * Added a new `WidgetAudioUI.vue` component that provides audio playback controls (play/pause, progress slider, volume, options) and loads audio files from the server based on node data. * Registered the new `WidgetAudioUI` component in the widget registry by importing it and adding an entry for the `audioUI` type. [[1]](diffhunk://#diff-c2a60954f7fdf638716fa1f83e437774d5250e9c99f3aa83c84a1c0e9cc5769bR21) [[2]](diffhunk://#diff-c2a60954f7fdf638716fa1f83e437774d5250e9c99f3aa83c84a1c0e9cc5769bR112-R115) * Updated `NodeWidgets.vue` to pass `nodeInfo` as the `node-data` prop to widgets of type `audioUI`, enabling the widget to access node-specific audio file information. **Debugging and Logging:** * Added logging of `nodeData` in `LGraphNode.vue` and `WidgetAudioUI.vue` to help with debugging and understanding the data structure. [[1]](diffhunk://#diff-a7744614cf842e54416047326db79ad81f7c7ab7bfb66ae2b46f5c73ac7d47f2R188-R189) [[2]](diffhunk://#diff-71cce190d74c6b5359288857ab9917caededb8cdf1a7e6377578b78aa32be2fcR1-R284) ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-5627-Vuenodes-audio-widgets-2716d73d365081fbbc06c1e6cf4ebf4d) by [Unito](https://www.unito.io) --------- Co-authored-by: GitHub Action <action@github.com> Co-authored-by: Arjan Singh <1598641+arjansingh@users.noreply.github.com> Co-authored-by: filtered <176114999+webfiltered@users.noreply.github.com> Co-authored-by: Christian Byrne <cbyrne@comfy.org> Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Alexander Brown <drjkl@comfy.org> Co-authored-by: Jin Yi <jin12cc@gmail.com> Co-authored-by: DrJKL <DrJKL@users.noreply.github.com> Co-authored-by: Robin Huang <robin.j.huang@gmail.com> Co-authored-by: github-actions <github-actions@github.com> |
||
|
|
4404c0461d |
Implement drop-on-canvas + linkconnectoradapter consolidation (#5898)
Implements droponcanvas functionality and a linkconnectoradapter refactor. - Drop on canvas (Shift and default) integrated via LinkConnector ‘dropped-on-canvas’ with proper CanvasPointerEvent. - LinkConnector adapter: now wraps the live canvas linkConnector (no duplicate state); added dropOnCanvas() helper. - Tests: Playwright scenarios for Shift-drop context menu/searchbox, pinned endpoint, type prefilter, and post-selection auto-connect (browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts). There are some followup PRs that will fix/refactor some more noncritical things, like the terrible slotid, the number/string nodeid confusion, etc. https://github.com/Comfy-Org/ComfyUI_frontend/pull/5780 (snapping) <-- https://github.com/Comfy-Org/ComfyUI_frontend/pull/5898 (drop on canvas + linkconnectoradapter refactor) <-- https://github.com/Comfy-Org/ComfyUI_frontend/pull/5903 (fix reroute snapping) --------- Co-authored-by: github-actions <github-actions@github.com> Co-authored-by: Christian Byrne <cbyrne@comfy.org> Co-authored-by: GitHub Action <action@github.com> |
||
|
|
1455845a30 |
Fix/vue nodes snap to grid (#5973)
## Summary Enable node snap to grid in vue nodes mirroring the same behavior as litegraph. - Show node snap preview (semi transparent white box target behind node) - Resize snap to grid - Shift + drag / Auto snap - Multi select + group snap ## Changes - **What**: useNodeSnap.ts useShifyKeySync.ts setups the core hooks into both the vue node positioning/resizing system and the event forwarding technique for communicating to litegraph. ## Review Focus Both new composables and specifically the useNodeLayout modifications to batch the mutations when snapping. A key tradeoff/note is why we are using the useShifyKeySync.ts which dispatches a new shift event to the canvas layer. This approach is the cleaner / more declaritive method mimicking how other vue node -> litegraph realtime events are passed. <!-- If this PR fixes an issue, uncomment and update the line below --> <!-- Fixes #ISSUE_NUMBER --> ## Screenshots (if applicable) <!-- Add screenshots or video recording to help explain your changes --> ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-5973-Fix-vue-nodes-snap-to-grid-2866d73d365081c1a058d223c8c52576) by [Unito](https://www.unito.io) |
||
|
|
06b0eecfe4 |
fix Vue node widgets should be in disabled state if their slots are connected with a link (#5834)
## Summary Fixes https://github.com/Comfy-Org/ComfyUI_frontend/issues/5692 by making widget link connection status trigger on change so Vue widgets with connected links could properly switch to the `disabled` state when they are implicitly converted to inputs. ## Changes - **What**: Added `node:slot-links:changed` event tracking and reactive slot data synchronization for Vue widgets ```mermaid graph TD A[Widget Link Change] --> B[NodeInputSlot.link setter] B --> C{Is Widget Input?} C -->|Yes| D[Trigger slot-links:changed] C -->|No| E[End] D --> F[Graph Event Handler] F --> G[syncNodeSlotData] G --> H[Update Vue Reactive Data] H --> I[Widget Re-render] style A fill:#f9f9f9,stroke:#333,color:#000 style I fill:#f9f9f9,stroke:#333,color:#000 ``` ## Review Focus Widget reactivity performance with frequent link changes and event handler memory management in graph operations. ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-5834-fix-Vue-node-widgets-should-be-in-disabled-state-if-their-slots-are-connected-with-a-link-27c6d73d365081f6a6c3c1ddc3905c5e) by [Unito](https://www.unito.io) |
||
|
|
c9da8b200d |
Fix: Allow uncoloring Vue Nodes (#5991)
## Summary Fixes an issue where trying to uncolor a node broke the vue color syncing. ## Changes - **What**: Changes litegraph property removal from `delete` to `= undefined` ## Screenshots ### Before https://github.com/user-attachments/assets/81a1ad40-ba5d-4dec-8f90-5b61eb804a16 ### After https://github.com/user-attachments/assets/459d2d15-c728-49d2-abd9-6e255e5383e5 ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-5991-Fix-Allow-uncoloring-Vue-Nodes-2876d73d365081f4a74fc9fa423aae1c) by [Unito](https://www.unito.io) |
||
|
|
874ef3ba0c |
Lint: Add eslint import plugin (#5955)
## Summary Adds the linter, turns on the recommended and a few extra rules, fixes existing violations. Doesn't prohibit `../../...` imports yet, that'll be it's own PR. ## Changes - **What**: Consistent and fixable imports - **Dependencies**: The plugin and parser ## Review Focus How do you feel about the recommended rules? What about the extra ones? [Any more](https://github.com/un-ts/eslint-plugin-import-x?tab=readme-ov-file#rules) you'd want to turn on? ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-5955-Lint-Add-eslint-import-plugin-2856d73d3650819985c0fb9ca3fa94b0) by [Unito](https://www.unito.io) |
||
|
|
cd7310cb8c |
feat(vue-nodes): snap link preview; connect on drop (#5780)
## Summary Snap link preview to the nearest compatible slot while dragging in Vue Nodes mode, and complete the connection on drop using the snapped target. Mirrors LiteGraph’s first-compatible-slot logic for node-level snapping and reuses the computed candidate for performance. ## Changes - Snap preview end to compatible slot - slot under cursor via `data-slot-key` fast-path - node under cursor via `findInputByType` / `findOutputByType` - Render path - `slotLinkPreviewRenderer.ts` now renders to `state.candidate.layout.position` - Complete on drop - Prefer `state.candidate` (no re-hit-testing) - Fallbacks: DOM slot → node first-compatible → reroute - Disconnects moving input link when dropped on canvas ## Review Focus - UX feel of snapping and drop completion (both directions) - Performance on large graphs (mousemove path is O(1) with dataset + single validation) - Edge cases: reroutes, moving existing links, collapsed nodes ## Screenshots (if applicable) https://github.com/user-attachments/assets/fbed0ae2-2231-473b-a05a-9aaf68e3f820 https://github.com/Comfy-Org/ComfyUI_frontend/pull/5780 (snapping) <-- https://github.com/Comfy-Org/ComfyUI_frontend/pull/5898 (drop on canvas + linkconnectoradapter refactor) <-- https://github.com/Comfy-Org/ComfyUI_frontend/pull/5903 (fix reroute snapping) ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-5780-feat-vue-nodes-snap-link-preview-connect-on-drop-27a6d73d365081d89c8cf570e2049c89) by [Unito](https://www.unito.io) --------- Co-authored-by: github-actions <github-actions@github.com> |
||
|
|
84e6e99f17 |
Cleanup: Removing monkeypatches for litegraph logic (#5902)
## Summary Putting the litegraph specific pieces into litegraph itself, using the CanvasGraph and LiteGraphGlobal to coordinate options. This was one part of the Image Previews reloading/calculating with every canvas draw. ## Review Focus Is this keeping things decoupled enough? Is this the right place to put things? Are there assumptions about the options that I'm missing here? ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-5902-WIP-Removing-monkeypatches-for-litegraph-logic-2816d73d3650818b860ec73579b89b54) by [Unito](https://www.unito.io) --------- Co-authored-by: github-actions <github-actions@github.com> |
||
|
|
b994608506 |
Tests: Vitest configuration cleanup (#5888)
## Summary Simplify default scripts. Filtering is still available to users, we can revisit tagging or grouping later. This fixes the issue where we had tests that were in the codebase but never run because they weren't under `/src/components` Also deletes the duplicate litegraph tests and their associated vitest config file. ## Changes - **What**: Test cleanup ## Review Focus ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-5888-Tests-Vitest-configuration-cleanup-2806d73d36508197b800f68f0b028279) by [Unito](https://www.unito.io) |
||
|
|
2970692176 |
Move Frame Vue Nodes (#5886)
This pull request improves the selection and movement logic for groups and nodes on the LiteGraph canvas, especially when using Vue-based node rendering. The most notable changes are the addition of proper bounding box handling for groups and a new coordinated movement mechanism that updates both LiteGraph internals and the Vue layout store when dragging nodes and groups. **Selection and bounding box calculation:** * Added support for including `LGraphGroup` bounding rectangles when calculating the selection toolbox position, so groups are now properly considered in selection overlays. [[1]](diffhunk://#diff-57a51ac5e656e64ae7fd276d71b115058631621755de33b1eb8e8a4731d48713L8-R8) [[2]](diffhunk://#diff-57a51ac5e656e64ae7fd276d71b115058631621755de33b1eb8e8a4731d48713R95-R97) **Node and group movement synchronization (Vue nodes mode):** * Introduced a new movement logic in `LGraphCanvas` for Vue nodes mode: when dragging, groups and their child nodes are moved together, and all affected node positions are batch-updated in both LiteGraph and the Vue layout store via `moveNode`. This ensures canvas and UI stay in sync. * Added imports for layout mutation operations and types to support the above synchronization. These changes make group selection and movement more robust and ensure that UI and internal state remain consistent when using the Vue-based node system. https://github.com/user-attachments/assets/153792dc-08f2-4b53-b2bf-b0591ee76559 ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-5886-Move-Frame-Vue-Nodes-2806d73d365081e48b5ef96d6c6b6d6b) by [Unito](https://www.unito.io) |
||
|
|
4b1c165d43 |
Cleanup/Perf: Float32Array/Float64Array removal (#5877)
## Summary Redoing https://github.com/Comfy-Org/ComfyUI_frontend/pull/5567, without the link rendering changes. ## Changes - **What**: Standardizing the Point/Size/Rect logic around numeric tuples instead of typed arrays. ## Review Focus Cutting here and going to continue in a second PR. Do the simpler types make sense? Do we want to keep the behavior of Rectangle as it is now? ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-5877-WIP-Float32Array-Float64Array-removal-27f6d73d36508169a39eff1e4a87a61c) by [Unito](https://www.unito.io) --------- Co-authored-by: filtered <176114999+webfiltered@users.noreply.github.com> Co-authored-by: github-actions <github-actions@github.com> |
||
|
|
720de8cc8a |
Add UI code for configuring subgraphNode widgets (#5826)
The third PR for managing display of widgets on subgraph nodes. This is the one that actually makes the functionality usable and user visible. Adds - A right-side modal for configuring which widgets are promoted, accessed by right click or selection toolbar - This menu allows for re-arranging widget order by dragging and dropping. - Indicators inside the subgraph for which widgets have been promoted. - Context menu options for promoting or demoting widget inside of a subgraph. <img width="767" height="694" alt="image" src="https://github.com/user-attachments/assets/4f78645d-7b26-48ba-8c49-78f4807e89e8" /> <img width="784" height="435" alt="image" src="https://github.com/user-attachments/assets/7005c730-a732-481e-befb-57019a8a31a7" /> Known issues - Some preview widgets are not added to a node until a draw operation occurs. The code does not yet have a way of determining which nodes should have draw operations forced to facilitate initial widget creation. ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-5826-Add-UI-code-for-configuring-subgraphNode-widgets-27c6d73d36508146accbf395e5bcd36a) by [Unito](https://www.unito.io) |
||
|
|
c662c77305 |
Add Playwright composite action to reduce workflow duplication (#5754)
This PR introduces a reusable composite action for Playwright setup to reduce duplication across workflows. ## Changes - Created `.github/actions/setup-playwright/action.yml` composite action that: - Detects or uses provided Playwright version - Caches Playwright browsers with intelligent cache keys - Installs browsers only when cache miss occurs - Installs OS dependencies when cache hit occurs ## Technical Details - **Important:** The composite action requires `shell: bash` for all `run` steps as per [GitHub Actions requirements for composite actions](https://docs.github.com/en/actions/creating-actions/creating-a-composite-action#creating-an-action-metadata-file). This is a mandatory field for composite actions, unlike regular workflow steps. - Updated workflow paths to account for repository checkout locations (some workflows checkout to subdirectories like `ComfyUI_frontend/`) - Uses conditional caching to avoid redundant browser installations ## Benefits - Reduces code duplication across 6 workflow files - Centralizes Playwright caching logic - Consistent browser setup across all workflows - Easier maintenance and updates - Faster CI runs through intelligent caching ## Affected Workflows - `.github/workflows/test-ui.yaml` (2 uses) - `.github/workflows/i18n-custom-nodes.yaml` - `.github/workflows/i18n-node-defs.yaml` - `.github/workflows/i18n.yaml` - `.github/workflows/test-browser-exp.yaml` --------- Co-authored-by: GitHub Action <action@github.com> |
||
|
|
d0e81cdd33 |
fix(docs): correct typos in comments and strings found during code view (#5880)
Non-functional changes only: - Fixed minor spelling mistakes in comments - Corrected typos in user-facing strings - No variables, logic, or functional code was modified. Signed-off-by: Marcel Petrick <mail@marcelpetrick.it> ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-5880-fix-docs-correct-typos-in-comments-and-strings-found-during-code-view-27f6d73d3650815db62af6115991304a) by [Unito](https://www.unito.io) --------- Signed-off-by: Marcel Petrick <mail@marcelpetrick.it> Co-authored-by: Alexander Brown <DrJKL0424@gmail.com> Co-authored-by: Benjamin Lu <benjaminlu1107@gmail.com> |
||
|
|
01b3aeae68 |
Prune console.log() (#5867)
Introduce a no-console rule in ESLint configuration and remove existing console log statements throughout the codebase, replacing some with warnings or comments. ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-5867-Prune-console-log-27e6d73d365081bcbad8c36cfb5b258c) by [Unito](https://www.unito.io) |
||
|
|
5d0aee59a6 |
Increase vue slot/link functionality (#5710)
## Summary Increase functionality for slots and links, covered with playwright tests. ## Features - Allow for reroute anchors to work when dragging from input slot - Allow for dragging existing links from input slot - Allow for ctrl/command + alt to create new link from input slot - Allow shift to drag all connected links on output slot - Connect links with reroutes (only when dragged from vue slot) ## Tests Added ### Playwright - Dragging input to input drags existing link - Dropping an input link back on its slot restores the original connection - Ctrl+alt drag from an input starts a fresh link - Should reuse the existing origin when dragging an input link - Shift-dragging an output with multiple links should drag all links - Rerouted input drag preview remains anchored to reroute - Rerouted output shift-drag preview remains anchored to reroute ## Notes The double rendering system for links being dragged, it works right now, maybe they can be coalesced later. Edit: As in the adapter, can be removed in a followup PR Also, it's known that more features will arrive in smaller PRs, this PR actually should've been much smaller. The next ones coming up are drop on canvas support, snap to node, type compatibility highlighting, and working with subgraphs. ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-5710-Increase-vue-slot-link-functionality-2756d73d3650814f8995f7782244803b) by [Unito](https://www.unito.io) --------- Co-authored-by: github-actions <github-actions@github.com> |
||
|
|
bbd8d67f5f |
designate canvasOnly on runtime-generated virtual widgets so they are hidden in Vue renderer (#5831)
## Summary Added `canvasOnly` flag to runtime-generated widgets to prevent Vue renderer from displaying them while keeping canvas functionality intact. ## Changes - **What**: Added `canvasOnly` widget option to hide upload, webcam, and refresh widgets from Vue renderer In the Canvas (LiteGraph) system, there was a small set of widgets with strictly defined components. There, if we wanted some unique or relatively complex behavior (like an upload butotn), we needed to create a separate widget that would be coupled to the original widget at runtime (and would not be serialized). In the Vue renderer system, we can simply add flags to the inputSpec or widget options and conditionally render complex UI additions -- i.e., there is no need for the hard-to-maintain runtime widget associations. Expressing such things entirely in the view layer simplifies business logic related to graph state, as we no longer need to account for preserving the connections between runtime widgets and their special siblings -- we also do not need to worry about the implications for state serialization. ## Related - https://github.com/Comfy-Org/ComfyUI_frontend/pull/5798 ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-5831-designate-canvasOnly-on-runtime-generated-virtual-widgets-so-they-are-hidden-in-Vue-ren-27c6d73d365081fb8641feec010190df) by [Unito](https://www.unito.io) --------- Co-authored-by: github-actions <github-actions@github.com> |
||
|
|
840f7f04fa |
Cleanup: Litegraph/Vue synchronization work (#5789)
## Summary Cleanup and fixes to the existing syncing logic. ## Review Focus This is probably enough to review and test now. Main things that should still work: - moving nodes around - adding new ones - switching back and forth between Vue and Litegraph Let me know if you find any bugs that weren't already present there. ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-5789-WIP-Litegraph-Vue-synchronization-work-27a6d73d3650811682cacacb82367b9e) by [Unito](https://www.unito.io) |
||
|
|
a25d89881b |
Allow Vue nodes to have their colors changed from selection toolbox (#5720)
## Summary Fixes https://github.com/Comfy-Org/ComfyUI_frontend/issues/5680 by allowing Vue nodes to properly synchronize color changes with LiteGraph nodes, implementing header darkening and light theme adjustments. <img width="2496" height="1512" alt="Screenshot from 2025-09-21 20-00-36" src="https://github.com/user-attachments/assets/e3bdf645-1e0b-4d11-9ae5-9401f43e8e96" /> ## Changes - **What**: Implemented color property synchronization between LiteGraph and Vue node rendering systems - **Core Fix**: Added `nodeData.color` and `nodeData.bgcolor` to [v-memo dependencies](https://vuejs.org/api/built-in-directives.html#v-memo) to trigger re-renders on color changes - **Color Logic**: Added header darkening using [memoized color adjustments](https://github.com/Comfy-Org/ComfyUI_frontend/blob/main/src/utils/colorUtil.ts) to match LiteGraph's ColorOption system - **Event System**: Enhanced property change instrumentation in LGraphNode.setColorOption to emit color/bgcolor events ## Review Focus Vue component reactivity timing - the v-memo fix was critical for immediate color updates. Verify light theme color adjustments match the drawNode monkey patch behavior in app.ts. ## Technical Details ```mermaid graph TD A[User Sets Color] --> B[LGraphNode.setColorOption] B --> C[Sets node.color & node.bgcolor] C --> D[Triggers property:changed events] D --> E[Vue Node Manager Updates] E --> F[v-memo Detects Change] F --> G[NodeHeader Re-renders] G --> H[Header Darkening Applied] style A fill:#f9f9f9,stroke:#333,color:#000 style H fill:#f9f9f9,stroke:#333,color:#000 ``` ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-5720-Allow-Vue-nodes-to-have-their-colors-changed-from-selection-toolbox-2766d73d36508123b441d126a74a54b2) by [Unito](https://www.unito.io) --------- Co-authored-by: Myestery <Myestery@users.noreply.github.com> Co-authored-by: DrJKL <DrJKL@users.noreply.github.com> Co-authored-by: github-actions <github-actions@github.com> |
||
|
|
856eb446a5 |
Add node pinning functionality to Vue nodes (#5772)
## Summary Added pinning functionality to Vue nodes with hotkey support and visual indicators. ## Changes - **What**: Added node pinning feature with 'p' hotkey toggle and pin icon indicator - **Components**: Updated `LGraphNode.vue` and `NodeHeader.vue` with pin state tracking - **State Management**: Extended `useGraphNodeManager` to sync pinned flag with Vue components - **Tests**: Added E2E tests for single and multi-node pin toggling ## Review Focus Pin state persistence in graph serialization and visual indicator positioning in node header layout. Verify hotkey doesn't conflict with existing shortcuts. ## Technical Details - Pin state tracked via `flags.pinned` property in `LGraphNode` - Uses [Vue memoization](https://vuejs.org/api/reactivity-advanced.html#v-memo) for efficient header re-rendering - Integrates with existing node property change detection system - Visual indicator uses Lucide pin icon with theme-aware styling ## Screenshots (if applicable) <img width="875" height="977" alt="Screenshot from 2025-09-25 13-02-21" src="https://github.com/user-attachments/assets/51d46cea-08f0-44fb-8b07-56d1b939338f" /> <img width="875" height="977" alt="Screenshot from 2025-09-25 13-02-10" src="https://github.com/user-attachments/assets/ce247426-1e39-48c0-924b-658b65c24f52" /> ## Related - https://github.com/Comfy-Org/ComfyUI_frontend/pull/5715 ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-5772-Add-node-pinning-functionality-to-Vue-nodes-2796d73d36508195914bcfc986aa66b5) by [Unito](https://www.unito.io) --------- Co-authored-by: filtered <176114999+webfiltered@users.noreply.github.com> |
||
|
|
0ac1074a25 |
fix Vue nodes capturing wheel event when Ctrl+Shift+drag zooming (#5791)
## Summary Fixed canvas read-only state during Ctrl+Shift drag-to-zoom to prevent node interaction conflicts. This fix also benefits Litegraph nodes. ## Changes - **What**: Canvas becomes read-only during [Ctrl+Shift drag zoom](https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent) operations and restores original state when finished - **What**: Added browser test coverage for zoom interaction behavior ## Review Focus State restoration on zoom interruption and edge cases where drag zoom is cancelled mid-operation. ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-5791-fix-Vue-nodes-capturing-wheel-event-when-Ctrl-Shift-drag-zooming-27a6d73d3650817d888ee59f8f7fcb01) by [Unito](https://www.unito.io) --------- Co-authored-by: github-actions <github-actions@github.com> |
||
|
|
1611c7a224 |
Refactor: Further state management cleanup (#5727)
## Summary Going through the GraphNodeManager and VueNodeLifecycle one property at a time and removing the pieces that are not currently wired up or used by the rest of the application Fixes paste location by updating the layoutStore in LGraphCanvas (which already mutates layoutStore elsewhere) ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-5727-WIP-Refactor-Further-state-management-cleanup-2766d73d36508173b379c6009c194a5a) by [Unito](https://www.unito.io) |
||
|
|
687b9e659c |
Fix reroute ID 0 treated as invalid (#5723)
## Summary Fixes old logic bug from refactor https://github.com/Comfy-Org/litegraph.js/pull/602/files ## Changes - Fixes truthy refactor to explicitly check undefined ## Review Focus No expectation that this will impact prod, however it may impact extensions IF someone has explicitly been setting link parentId to 0. This would be very strange, as it would cause unexpected behaviour in other parts of the code (which all explicitly check `undefined`). ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-5723-Fix-reroute-ID-0-treated-as-invalid-2766d73d365081568124ce1f85cdf84e) by [Unito](https://www.unito.io) |
||
|
|
c4c0e52e64 |
Refactor: Let LGraphNode handle more events itself (#5709)
## Summary Don't route events up through GraphCanvas if the component itself can handle the changes ## Changes - **What**: Reduce the indirect access or action dispatch to composables/stores. ## Review Focus The behavior should be either equivalent or a little snappier than before. Also, the local state in LGraphNode has (almost) all been removed in favor of reacting to the nodeData prop. ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-5709-Refactor-Let-LGraphNode-handle-more-events-itself-2756d73d365081e6a88ce6241bceecc0) by [Unito](https://www.unito.io) --------- Co-authored-by: GitHub Action <action@github.com> |
||
|
|
fd12591756 |
[feat] integrate asset browser with widget system (#5629)
## Summary Add asset browser dialog integration for combo widgets with full animation support and proper state management. (Thank you Claude from saving me me from merge conflict hell on this one.) ## Changes - Widget integration: combo widgets now use AssetBrowserModal for eligible asset types - Dialog animations: added animateHide() for smooth close transitions - Async operations: proper sequencing of widget updates and dialog animations - Service layer: added getAssetsForNodeType() and getAssetDetails() methods - Type safety: comprehensive TypeScript types and error handling - Test coverage: unit tests for all new functionality - Bonus: fixed the hardcoded labels in AssetFilterBar Widget behavior: - Shows asset browser button for eligible widgets when asset API enabled - Handles asset selection with proper callback sequencing - Maintains widget value updates and litegraph notification ## Review Focus I will call out some stuff inline. ## Screenshots https://github.com/user-attachments/assets/9d3a72cf-d2b0-445f-8022-4c49daa04637 ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-5629-feat-integrate-asset-browser-with-widget-system-2726d73d365081a9a98be9a2307aee0b) by [Unito](https://www.unito.io) --------- Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: GitHub Action <action@github.com> |
||
|
|
2ff0d951ed |
Slot functionality for vue nodes (#5628)
Allows for simple slot functionality in vue nodes mode. Has: - Drag new link from slot - Connect new link from dropping on slot Now: - Tests After: - Drop on reroute - Correct link color on connect - Drop on node - Hover effects ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-5628-Slot-functionality-for-vue-nodes-2716d73d365081c59a3cef7c8a5e539e) by [Unito](https://www.unito.io) --------- Co-authored-by: bymyself <cbyrne@comfy.org> Co-authored-by: AustinMroz <austin@comfy.org> Co-authored-by: Claude <noreply@anthropic.com> |
||
|
|
eb664f47af |
Fix cyclic prototype errors with subgraphNodes (#5637)
#5024 added support for connecting primitive nodes to subgraph inputs. To accomplish this, it pulls WidgetLocator information from the node owning the widget. This `node` property does not exist on all IBaseWidget. `toConcrete` was used to instead have a BaseWidget which is guaranteed to have a node property. The issue that was missed, is that a widget which lacks this information (such as most implemented by custom nodes) sets the node value to the argument which was passed. Here that is the reference to the subgraph node. Sometimes, this `#setWidget` call is made multiple times, and when this occurs, the `input.widget` has itself set as the protoyep, throwing an error. This is resolved by instead taking an additional input which is unambiguous. For reference, this is a near minimal workflow using comfy_mtb that replicates the issue [cyclic.json](https://github.com/user-attachments/files/22412187/cyclic.json) Special thanks to @melMass for assistance discovering this issue. ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-5637-Fix-cyclic-prototype-errors-with-subgraphNodes-2726d73d365081fea356f5197e4c2b42) by [Unito](https://www.unito.io) |
||
|
|
08220d50d9 |
Lint: Turn on rules that should allow for verbatimModuleSyntax (#5616)
* lint: turn on type import rules setting up for verbatimModuleSyntax * lint: --fix for type imports |
||
|
|
6866e1277a |
new design for left click and wheel (#5566)
* new design for left click and wheel * update snap * fix import * fix test * default value * fix test * Update test expectations [skip ci] --------- Co-authored-by: github-actions <github-actions@github.com> |
||
|
|
6a01b08ebf |
Subgraph widget promotion - Part 1 (#5537)
* Prerequisite tweaks for subgraph widget promotion * Clean up DOMWidget tracking on graph change * Mark migrated CombOWidget functions private * Cleanup placeholder node cast |
||
|
|
4f8e820c51 |
feat: Let mode changes trigger a re-render for Vue nodes (#5599)
* feat: Let mode changes trigger a re-render for Vue nodes * Oops! |
||
|
|
2b57291756 |
Fix context menu creating nodes in wrong position (#5595)
* Fix context menu creating nodes in wrong position When nodes are created from the context menu, they previously had there position set immediately after the node itself was created. Under some circumstances, this new position would be overwritten by the layout store. This is solved by setting the position before node initialization. * nit: Move size fix to named variable Also remove ternary. The elements are always numberic, so checking if a number is truthy before multiplying by 0 is a little silly. * nit: Further variable extraction |
||
|
|
4ec6223189 |
fix: Add JSON import assertions for Node.js ESM compatibility (#5507)
Added `with { type: 'json' }` assertions to all JSON imports to ensure compatibility with Node.js ES modules and Playwright environments. This follows the current ESM specification where JSON imports require explicit type assertions.
Affected areas:
- Tailwind config
- i18n locale imports (36 files)
- Test fixtures and spec files
- API client feature flags
- Core color palettes
References:
- https://nodejs.org/api/esm.html
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import/with
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-authored-by: Claude <noreply@anthropic.com>
|
||
|
|
68845ce33a |
Fix Connection of Primitive nodes to Subgraph node (#5024)
* Fix connection of primitives to subgraphNodes * Fix loading and nested subgraphs with primitives Medium hackyness, but this saves ~100 lines. * Use improved type check * Remove requirement for type assertion * Add warning comment --------- Co-authored-by: filtered <176114999+webfiltered@users.noreply.github.com> |
||
|
|
3bc25b7aeb |
Add Asset Widget (#5475)
* [feat] carve out path to call asset browser in combo widget * Add Asset Widget * [feat] add fallback "Select model" label --------- Co-authored-by: Arjan Singh <arjan@comfy.org> |
||
|
|
aa7f8912a7 |
[refactor] Use getSlotPosition for Vue nodes in link rendering (#5400)
* Remove COMFY_VUE_NODE_DIMENSIONS * [refactor] Use getSlotPosition for Vue nodes in link rendering Replace direct node position calls with getSlotPosition utility when Vue nodes mode is enabled. This ensures consistent slot positioning across the canvas rendering system. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * Fix getSlotPosition readonly return value (#5433) * Update accordingly to new type * Fix canvas/screen conversion formulas in useTransformState (#5406) * Fix conversion formulas * update test expectations * Remove unused type import --------- Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: filtered <176114999+webfiltered@users.noreply.github.com> |
||
|
|
0e44a4a354 |
Remove COMFY_VUE_NODE_DIMENSIONS constant (#5398)
* Remove COMFY_VUE_NODE_DIMENSIONS * Update litegraph snapshot test |
||
|
|
76f21b9975 | Fix bypass slot check only works for precise types (#5431) | ||
|
|
f6405e9125 |
Knip: More Pruning (#5374)
* knip: Don't ignore exports that are only used within a given file * knip: More pruning after rebase * knip: Vite plugin config fix * knip: vitest plugin config * knip: Playwright config, remove unnecessary ignores. * knip: Simplify project file enumeration. * knip: simplify the config file patterns ?(.optional_segment) * knip: tailwind v4 fix * knip: A little more, explain some of the deps. Should be good for this PR. * knip: remove unused disabling of classMembers. It's opt-in, which we should probably do. * knip: floating comments We should probably delete _one_ of these parallell trees, right? * knip: Add additional entrypoints * knip: Restore UserData that's exposed via the types for now. * knip: Add as an entry file even though knip says it's not necessary. * knip: re-export functions used by nodes (h/t @christian-byrne) |
||
|
|
fc8d5621ac |
Implement subgraph publishing (#5139)
* Implement subgraph publishing * Add missing null check * Fix subgraph blueprint display in workflows tab * Fix demotion of subgraph blueprints on reload * Update locales [skip ci] * Update blueprint def on save, cleanup * Fix skipped tracking on subgraph publish When a subgraph is first published, it previously was not added to the subgraphCache. This would cause deletion to fail until a reload occurred. * Fix failing vite tests A couple of tests that were mocking classes broke SubgraphBlueprint inheritance. Since they aren't testing anythign related to subgraph blueprints, the subgraph store is mocked as well. * Make blueprint breadcrumb badge clickable * Add confirmation for overwrite on publish * Simplify blueprint badge naming * Swap to promise.allSettled when fetching subgraphs * Navigate into subgraph on blueprint edit * Revert mission of value in blueprint breadcrumb This was causing the blueprint badge to always display * Misc code quality fixes * Set subgraphNode title on blueprint add. When a subgraph blueprint is added to the graph, the title of the subgraphNode is now set to be the title of the blueprint. NOTE: The name of the subgraph node when a blueprint is edited is left unchanged. This may cause minor user confusion. * Add "Delete Blueprint" option to breadcrumb When editing a blueprint, the options provided for the root graph of the breadcrumb included a Delete Workflow option. This still functioned for deleting the current blueprint when selected, but didn't make sense. It has been updated to instead describe that it deletes the current blueprint * Extract subgraph load code as function * Fix subgraphs appearing in library after refresh Subgraph nodes were hidden from the node library and context menu by setting skip_list to true. Unfortunately, this causes them to be mistakenly be caught and registered as vue nodes when a refresh is performed. This is fixed by adding a check for skip_list. * Add delete button and confirmation for deletion * Use more specific warning for blueprint deletion * At success toast on subgraph publish Will return later to potentially add a node library link to the toast * Don't apply subgraph context menu to normal nodes Subgraph blueprints have a right click -> delete option in the node library. This was incorrectly being dislplayed on non blueprint nodes. * Remove hardcoded subgraphs path Rather happy with this change. Rather than trying to introduce a recursive import to pass a magic string, this solution is both sufficient AND allows potential future extensions with less breakage. * Fix nodeDef update on save Wait to update the node def cache until after a blueprint has been saved. Before, changes to links weren't actually being made visisble. * Fix SaveAs with subgraph blueprints * Remove ugly serialize/deserialize Thought I had already tested this, and found that the mere existence of proxies was causing issues, but simply adding a correct annotation is sufficient now. * Improve error specificity * Framework for user defined blueprint descriptions BlueprintDescription can be added to a workflows extra field to provide more useful information about a blueprint's purpose Actually hooking this up in a way that is user accessible is out of scope for right now, but this will simplify future implementation. * Cleanup breadcrumb dropdown options Removes Dupliate for blueprints, adds a publish subgraph option. The publish subgraph button currently routes through the save as logic. Unforunately, this results in the prompt for name referencing workflows. The cleanest way to resolve this is still being considered * Move blueprint renaming into blueprint load Blueprints should automatically set the name of the added node to the filename when added. This mostly worked, but created uglier edgecases: The subgraph itself wasn't renamed, and it would need to be reimplemented to apply when editing a blueprint. Instead, this is now applied when a subgraphBlueprint is first loaded. This keeps all the logic routed through a single point * Move saveAs prompt into workflow class Ensures that the correct publish text is displayed when editing blueprints without making an awful mess of imports * Fix tests by making subgraphBlueprint internal This has the added benefit of forcing better organization. Reverts the useWorkflowThumbnail patch as it is no longer required. * Add tests for subgraph blueprints * Rewrite confirmation dialog * Fix overwrite on publish new subgraph 1 is used as a placeholder size as -1 indicates the baking userFile is temporary, not persisted, and therefore, not able to overwrite when saved. * When editing blueprint, tint background blue * Fix blueprint tint at low LOD * Set node source for blueprints to Blueprint * Fix publish test Making subgraph blueprints non temporary on publish made it so the following load actually occurs. A mock has been added for this load. * Fix multiple nits * Further cleanup: error handling, and comments * Fixing failing test cases This also moves the bg tinting to a property of the workflow, which makes things more extensible in the future. * Fix temporary marking on publish. The prior fix to allow overwrite of an existing blueprint on publish was misguided. By marking a not-yet-loaded file as non-temporary, the load performed prior to saving was actually fetching the file off disk and discarding the existing changes. This additionally entirely prevented publishing when a blueprint did not already exist with the current name. To fix this, the blueprint is not marked as non-temporary until after the load occurs. Note that this load is still required as it initializes the change tracker state required for saving. * Block unloading subgraph blueprints Will need to be revisited if lazy loading is implemented, but this requires solving some ugly sync/async issues. --------- Co-authored-by: github-actions <github-actions@github.com> |
||
|
|
db37693688 |
Remove accidental onMouseDown handler (#5405)
* Remove accidental onMouseDown handler * Fix test snapshot * Add test that onMouseDown isn't overwritten |
||
|
|
c2eb4f03e9 |
fix: onNodeRemoved not called when loading new graph (and tearing down previous) (#5407)
* standardize graph cleanup * test: fix useCoreCommands tests and add regression test - Fix mocking to properly simulate app.clean() calling graph.clear() - Add intelligent subgraph detection in mock to match real implementation - Add regression test for Vue node cleanup bug to prevent future regressions - Ensures app.clean() properly triggers onNodeRemoved events through graph.clear() 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * fix unit tests * move beforeLoadNewGraph to before graph is cleaned --------- Co-authored-by: Claude <noreply@anthropic.com> |
||
|
|
f719ed941f |
When converting single group to subgraph, also convert children (#5217)
* On conversion of single group, convert children If convert to subgraph is called on a selection consisting of a single group, the groups children are also converted to subgraph. * Update locales [skip ci] * Create new set to avoid mutating passed argument --------- Co-authored-by: github-actions <github-actions@github.com> |
||
|
|
3fbcf4aa7e |
knip: YOLO pass, all the unused exports enabled, YAGNI for the rest (#5313)
* knip: Enable unusedBinaries, add two exceptions * knip: YOLO pass, all the unused exports enabled. Paired with @christian-byrne to allow for some special cases to remain with custom knip ignore tags. * knip: remove post-rebase |
||
|
|
006e6bd57c |
[feat] Vue-Based Rendering System for the ComfyUI Node Graph (#4263)
* [feat] Add core Vue widget infrastructure - SimplifiedWidget interface for Vue-based node widgets - widgetPropFilter utility with component-specific exclusion lists - Removes DOM manipulation and positioning concerns - Provides clean API for value binding and prop filtering * [feat] Add Vue widget registry system - Complete widget type enum with all 15 widget types - Component mapping registry for dynamic widget rendering - Helper function for type-safe widget component resolution * [feat] Add Vue input widgets - WidgetInputText: Single-line text input with InputText component - WidgetTextarea: Multi-line text input with Textarea component - WidgetSlider: Numeric range input with Slider component - WidgetToggleSwitch: Boolean toggle with ToggleSwitch component * [feat] Add Vue selection widgets - WidgetSelect: Dropdown selection with Select component - WidgetMultiSelect: Multiple selection with MultiSelect component - WidgetSelectButton: Button group selection with SelectButton component - WidgetTreeSelect: Hierarchical selection with TreeSelect component * [feat] Add Vue visual widgets - WidgetColorPicker: Color selection with ColorPicker component - WidgetImage: Single image display with Image component - WidgetImageCompare: Before/after comparison with ImageCompare component - WidgetGalleria: Image gallery/carousel with Galleria component - WidgetChart: Data visualization with Chart component * [feat] Add Vue action widgets - WidgetButton: Action button with Button component and callback handling - WidgetFileUpload: File upload interface with FileUpload component * [feat] TransformPane - Viewport synchronization layer for Vue nodes (#4304) Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Benjamin Lu <benceruleanlu@proton.me> Co-authored-by: github-actions <github-actions@github.com> * Update locales [skip ci] * Fix TransformPane pos/size (#4826) * Update locales [skip ci] * refactor(litegraph): decouple render-time state from models for reroutes and links\n\nIntroduce RenderedLinkSegment; compute reroute render params without mutating model; render into ephemeral segments instead of writing to Reroute/LLink. * Revert "refactor(litegraph): decouple render-time state from models for reroutes and links\n\nIntroduce RenderedLinkSegment; compute reroute render params without mutating model; render into ephemeral segments instead of writing to Reroute/LLink." This reverts commit |