Update imports for VueUse v14 compatibility:
- `toValue` → import from `vue` (dropped from VueUse v14)
- `MaybeRef` type → import from `vue` (dropped from VueUse v14)
These APIs were deprecated in VueUse v12 and removed in v14 in favor of
Vue's native exports.
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8550-fix-update-imports-for-VueUse-v14-compatibility-2fb6d73d365081b0bac1d01d4092c176)
by [Unito](https://www.unito.io)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Chores**
* Updated VueUse dependencies to newer versions for improved
compatibility
* Minor package entry reorganization (no functional changes)
* **Refactor**
* Consolidated imports to use native Vue utilities where applicable
* **Tests**
* Updated unit tests: improved outside-click simulation and cleanup;
migrated tests to use the real store setup for more realistic test
behavior
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: Amp <amp@ampcode.com>
## Summary
Fixes a bug where socket map data was not properly removed when sockets
are dynamically added/removed via DynamicCombo widgets in Vue mode
(Nodes 2.0).
## Problem
When DynamicCombo widgets (e.g., `should_remesh` on Meshy nodes) change
their selection, inputs are dynamically added/removed. The Vue `v-for`
loop in `NodeSlots.vue` was using array index as the `:key`, causing Vue
to **reuse** slot components instead of properly unmounting them.
This led to:
- Socket map entries leaking (never cleaned up)
- Socket positions becoming desynced
- Stale cached offset data
## Solution
1. **Use slot `name` as Vue key** instead of array index in
`NodeSlots.vue`
- Slot names are unique per node (enforced by ComfyUI backend)
- When a slot is removed, Vue sees the key disappear and properly
unmounts the component
- `onUnmounted` cleanup in `useSlotElementTracking` now runs correctly
2. **Add defensive cleanup** in `useSlotElementTracking.ts`
- Before registering a new slot, check if a stale entry exists with the
same key
- Clean up stale entry to handle any edge cases
## Related
- Fixes COM-12970
- Related to #7837 (fixed LiteGraph version of this bug, but not Vue
mode)
## Testing
- Quality checks pass (typecheck, lint, format)
- Manual testing with DynamicCombo nodes (Meshy, nodes_logic)
recommended
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8469-fix-Vue-mode-socket-map-data-not-cleaned-up-on-dynamic-input-changes-2f86d73d365081e599eadca4f15e6b6e)
by [Unito](https://www.unito.io)
---------
Co-authored-by: Subagent 5 <subagent@example.com>
Co-authored-by: Amp <amp@ampcode.com>
## Summary
This PR removes unsafe type assertions ("as unknown as Type") from test
files and improves type safety across the codebase.
### Key Changes
#### Type Safety Improvements
- Removed all instances of "as unknown as" patterns from test files
- Used proper factory functions from litegraphTestUtils instead of
custom mocks
- Made incomplete mocks explicit using Partial<T> types
- Fixed DialogStore mocking with proper interface exports
- Improved type safety with satisfies operator where applicable
#### App Parameter Removal
- **Removed the unused `app` parameter from all ComfyExtension interface
methods**
- The app parameter was always undefined at runtime as it was never
passed from invokeExtensions
- Affected methods: init, setup, addCustomNodeDefs,
beforeRegisterNodeDef, beforeRegisterVueAppNodeDefs,
registerCustomNodes, loadedGraphNode, nodeCreated, beforeConfigureGraph,
afterConfigureGraph
##### Breaking Change Analysis
Verified via Sourcegraph that this is NOT a breaking change:
- Searched all 10 affected methods across GitHub repositories
- Only one external repository
([drawthingsai/draw-things-comfyui](https://github.com/drawthingsai/draw-things-comfyui))
declares the app parameter in their extension methods
- That repository never actually uses the app parameter (just declares
it in the function signature)
- All other repositories already omit the app parameter
- Search queries used:
- [init method
search](https://sourcegraph.com/search?q=context:global+repo:%5Egithub%5C.com/.*+lang:typescript+%22init%28app%22+-repo:Comfy-Org/ComfyUI_frontend&patternType=standard)
- [setup method
search](https://sourcegraph.com/search?q=context:global+repo:%5Egithub%5C.com/.*+lang:typescript+%22setup%28app%22+-repo:Comfy-Org/ComfyUI_frontend&patternType=standard)
- Similar searches for all 10 methods confirmed no usage
### Files Changed
Test files:
-
src/components/settings/widgets/__tests__/WidgetInputNumberInput.test.ts
- src/services/keybindingService.escape.test.ts
- src/services/keybindingService.forwarding.test.ts
- src/utils/__tests__/newUserService.test.ts →
src/utils/__tests__/useNewUserService.test.ts
- src/services/jobOutputCache.test.ts
-
src/renderer/extensions/vueNodes/widgets/composables/useRemoteWidget.test.ts
-
src/renderer/extensions/vueNodes/widgets/composables/useIntWidget.test.ts
-
src/renderer/extensions/vueNodes/widgets/composables/useFloatWidget.test.ts
Source files:
- src/types/comfy.ts - Removed app parameter from ComfyExtension
interface
- src/services/extensionService.ts - Improved type safety with
FunctionPropertyNames helper
- src/scripts/metadata/isobmff.ts - Fixed extractJson return type per
review
- src/extensions/core/*.ts - Updated extension implementations
- src/scripts/app.ts - Updated app initialization
### Testing
- All existing tests pass
- Type checking passes
- ESLint/oxlint checks pass
- No breaking changes for external repositories
Part of the "Road to No Explicit Any" initiative.
### Previous PRs in this series:
- Part 2: #7401
- Part 3: #7935
- Part 4: #7970
- Part 5: #8064
- Part 6: #8083
- Part 7: #8092
- Part 8 Group 1: #8253
- Part 8 Group 2: #8258
- Part 8 Group 3: #8304
- Part 8 Group 4: #8314
- Part 8 Group 5: #8329
- Part 8 Group 6: #8344 (this PR)
## Summary
Increases the resize handle size on Vue nodes to improve usability,
especially when nodes are selected.
## Changes
- **What**: Increased resize handle from 12px to 20px and offset it
slightly outside the node boundary to avoid overlap with selection
outline
## Review Focus
The resize handle was too small and became harder to grab when the node
was selected (the 2px outline rendered outside the box, visually
obscuring the corner). This fix increases the hit area and positions it
to extend beyond the node edge.
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8391-fix-increase-Vue-node-resize-handle-size-for-better-usability-2f76d73d36508136b2aac51bc0d53551)
by [Unito](https://www.unito.io)
---------
Co-authored-by: Subagent 5 <subagent@example.com>
Co-authored-by: Amp <amp@ampcode.com>
Co-authored-by: GitHub Action <action@github.com>
## Summary
Backend part: https://github.com/Comfy-Org/ComfyUI/pull/11582
- Move API node pricing definitions from hardcoded frontend functions to
backend-defined JSONata expressions
- Add `price_badge` field to node definition schema containing JSONata
expression and dependency declarations
- Implement async JSONata evaluation with signature-based caching for
efficient reactive updates
- Show one decimal in credit badges when meaningful (e.g., 1.5 credits
instead of 2 credits)
## 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-7816-Move-price-badges-to-python-nodes-2da6d73d365081ec815ef61f7e3c65f7)
by [Unito](https://www.unito.io)
- Fix deserialization of matchtype inputs spawned by autogrow.
- Rotate multitype slot indicators to align with design changes.
- Fix several instance of incorrect group matching
- MatchType reactively updates input type in vue
- Support the "hollow circle" optional input indicator in vue
- Custom combo sends index of selection to backend
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8026-Further-dynamic-input-fixes-2e76d73d3650819680fef327a94f4294)
by [Unito](https://www.unito.io)
## Summary
This PR improves keyboard event handling consistency and fixes an issue
where pressing Escape in nested input components would unintentionally
close parent modals/dialogs.
## Changes
### Keyboard Event Fixes
**TagsInput Escape Key Handling**
- Added `@keydown.escape.stop` handler to `TagsInputInput.vue` to
prevent Escape from bubbling up and closing parent modals
- The handler blurs the input and exits editing mode without propagating
the event
**EditableText keyup → keydown Migration**
- Changed `@keyup.enter` to `@keydown.enter` and `@keyup.escape` to
`@keydown.escape`
- Using `keydown` is more consistent with how other UI frameworks handle
these events and provides more responsive feedback
- Updated corresponding unit tests to use `keydown` triggers
### Why keydown over keyup?
- `keydown` fires immediately when the key is pressed, providing faster
perceived response
- Better consistency with browser/OS conventions for action triggers
- Prevents default behaviors (like form submission) more reliably when
needed
- Aligns with other keyboard handlers in the codebase
## Testing
- Updated `EditableText.test.ts` to use `keydown` events
- Updated `NodeHeader.test.ts` to use `keydown.enter`
- Manual testing: Escape in TagsInput no longer closes parent modal
## Checklist
- [x] Unit tests updated
- [x] Keyboard event handlers consistent
- [x] No breaking changes to component API
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8204-fix-Consistent-keydown-handling-for-EditableText-and-TagsInput-escape-key-2ef6d73d365081f0ac6bed8bcae57657)
by [Unito](https://www.unito.io)
In vue mode, the VHS Load Audio (Upload) node had 2 audio previews. This
occurred because the native AudioPreview widget was being applied to any
combo widget with the name `audio`. This native preview does not support
the advanced preview functions VHS provides like seeking to specific
start time, trimming to a target duration, or converting from formats
the browser may not support.
This is fixed through a fairly involved cleanup to instead display the
litegraph AudioUI widget as an AudioPreview widget when in vue mode.
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8206-Fix-doubled-player-on-VHS-LoadAudio-in-vue-2ef6d73d365081ce8907dca2706214a1)
by [Unito](https://www.unito.io)
---------
Co-authored-by: github-actions <github-actions@github.com>
Co-authored-by: Alexander Brown <drjkl@comfy.org>
Extends the existing 'Show Advanced' button (previously subgraph-only)
to also appear on regular nodes that have widgets marked with
`options.advanced = true`.
## Changes
- Updates `showAdvancedInputsButton` computed to check for advanced
widgets on regular nodes
- Updates `handleShowAdvancedInputs` to set `node.showAdvanced = true`
and trigger canvas redraw for regular nodes
## Related
- Backend PR that adds `advanced` flag: comfyanonymous/ComfyUI#11939
- Canvas hide PR: feat/advanced-widgets-canvas-hide (this PR provides
the toggle for that)
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8148-feat-canvas-show-Show-Advanced-button-on-nodes-with-advanced-widgets-2ec6d73d36508155a8adfa0a8ec84d46)
by [Unito](https://www.unito.io)
A major, full rewrite of linear mode, now under the name "Simple Mode".
- Fixes widget styling
- Adds a new simplified history
- Adds support for non-image outputs
- Supports right sidebar
- Allows and panning on the output image preview
- Provides support for drag and drop zones
- Moves workflow notes into a popover.
- Allows scrolling through outputs with Ctrl+scroll or arrow keys
The primary means of accessing Simple Mode is a toggle button on the
bottom right. This button is only shown if a feature flag is enabled, or
the user has already seen linear mode during the current session. Simple
Mode can also be accessed by
- Using the toggle linear mode keybind
- Loading a workflow that that was saved in Simple Mode workflow
- Loading a template url with appropriate parameter
<img width="1790" height="1387" alt="image"
src="https://github.com/user-attachments/assets/d86a4a41-dfbf-41e7-a6d9-146473005606"
/>
Known issues:
- Outputs on cloud are not filtered to those produced by the current
workflow.
- Output filtering has been globally disabled for consistency
- Outputs will load more items on scroll, but does not unload
- Performance may be reduced on weak devices with very large histories.
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7734-linear-v2-2d16d73d3650819b8a10f150ff12ea22)
by [Unito](https://www.unito.io)
Most of the features in this pull request are completed and can be
reviewed and merged.
## TODO
- [x] no selection panel
- [x] group selected panel
- [x] tabs
- [x] favorites tab
- [x] global settings tab
- [x] nodes tab
- [x] widget actions menu
- [x] [Bug]: style bugs
- [x] button zoom to the node on canvas.
- [x] rename widgets on widget actions
- [ ] [Bug]: the canvas has not been updated after renaming.
- [x] global settings
- [ ] setting item: "show advanced parameters"
- blocked by other things. skip for now.
- [x] setting item: show toolbox on selection
- [x] setting item: nodes 2.0
- [ ] setting item: "background color"
- blocked by other things. skip for now.
- [x] setting item: grid spacing
- [x] setting item: snap nodes to grid
- [x] setting item: link shape
- [x] setting item: show connected links
- [x] form style reuses the form style of node widgets
- [x] group node cases
- [x] group node settings
- [x] show all nodes in group
- [x] show frame name on nodes when multiple selections are made
- [x] group multiple selections
- [x] [Bug]: nodes without widgets cannot display the location and their
group
- [x] [Bug]: labels layout
- [x] favorites
- [x] the indicator on widgets
- [x] favorite and unfavorite buttons on widgets
- [x] [Bug]: show node name in favorite widgets + improve labels layout
- [ ] [Bug]: After canceling the like, the like list will not be updated
immediately.
- [x] [Bug]: The favorite function does not work for the project on
Subgraph.
- [x] subgraph
- [x] add the node name from where this parameter comes from when node
is subgraph
- [x] show and hide directly on Inputs
- [x] some bugs need to be fixed.
- [x] advanced widgets
- [x] button: show advanced inputs
- Clicking button expands the "Advanced Inputs" section on the right
side panel, regardless of whether the panel is open or not
- [x] [Bug]: style bugs
- [x] advanced inputs section when node is subgraph
- [x] inputs tab rearranging
- [x] favorited inputs rearranging
- [x] subgraph inputs rearranging
- [ ] review and reconstruction to improve complexity and architecture
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7812-feat-right-side-panel-favorites-no-selection-state-and-more-2da6d73d36508134b503d676f9b3d248)
by [Unito](https://www.unito.io)
---------
Co-authored-by: GitHub Action <action@github.com>
Co-authored-by: github-actions <github-actions@github.com>
Co-authored-by: bymyself <cbyrne@comfy.org>
## Summary
Migrates all unit tests from `tests-ui/` to colocate with their source
files in `src/`, improving discoverability and maintainability.
## Changes
- **What**: Relocated all unit tests to be adjacent to the code they
test, following the `<source>.test.ts` naming convention
- **Config**: Updated `vitest.config.ts` to remove `tests-ui` include
pattern and `@tests-ui` alias
- **Docs**: Moved testing documentation to `docs/testing/` with updated
paths and patterns
## Review Focus
- Migration patterns documented in
`temp/plans/migrate-tests-ui-to-src.md`
- Tests use `@/` path aliases instead of relative imports
- Shared fixtures placed in `__fixtures__/` directories
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7811-chore-migrate-tests-from-tests-ui-to-colocate-with-source-files-2da6d73d36508147a4cce85365dee614)
by [Unito](https://www.unito.io)
---------
Co-authored-by: Amp <amp@ampcode.com>
Co-authored-by: GitHub Action <action@github.com>
## Summary
Refactor: remove FF for subscription tier, remove legacy code for non
subscription tier logic.
## Review Focus
Preexisting cloud functionality impact.
<!-- 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-7596-refactor-start-on-removing-FF-for-subscription-tiers-2cc6d73d3650816bac3aef893e4f37cd)
by [Unito](https://www.unito.io)
## Summary
- Fixed issue where right-clicking on one Vue node then another would
close the context menu instead of repositioning it
- Added `showNodeOptions` function that always shows the menu at the new
position (used for contextmenu events)
- Kept `toggleNodeOptions` for the "More Options" button where toggle
behavior is expected
## Test plan
- [ ] Right-click on a Vue node to open context menu
- [ ] Right-click on a different Vue node - menu should immediately show
for the new node
- [ ] Click "More Options" button when menu is open - should close the
menu
- [ ] Click "More Options" button when menu is closed - should open the
menu
https://github.com/user-attachments/assets/bb31c2e4-12b4-4786-96ac-23b1e2b4daa0
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7644-fix-context-menu-not-opening-when-right-clicking-different-Vue-nodes-2ce6d73d36508145bc30fe6947b6808a)
by [Unito](https://www.unito.io)
## 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 <action@github.com>
Hide the QueueOverlayHeader more-options (…) menu when running in Cloud
distribution
This is being hidden instead of fixed because it deletes all user assets
on cloud, will be touched by /jobs, replaced by the second iteration of
design changes, along with changes to asset deletion happening soon. It
would be too risky to have a proper fix for it in the cloud deploy
today.
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7571-Hide-queue-overlay-header-menu-on-cloud-2cb6d73d3650815a8faac8a8f0de91f0)
by [Unito](https://www.unito.io)
---------
Co-authored-by: GitHub Action <action@github.com>
## Summary
Remove keyDown provider on the LGraphNode, remove inject on widget.
## Changes
- **What**: LGraphNode.vue ImagePreview.vue
- **Breaking**: <!-- Any breaking changes (if none, remove this line)
-->
- **Dependencies**: <!-- New dependencies (if none, remove this line)
-->
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7421-refactor-stop-fighting-the-DOM-2c76d73d365081e6b5e9c99a61bbd883)
by [Unito](https://www.unito.io)
Prior to the release of subgraphs, there was a single graph accessed
through `app.graph`. Now that there's multiple graphs, there's a lot of
code that needs to be reviewed and potentially updated depending on if
it cares about nearby nodes, all nodes, or something else requiring
specific attention.
This was done by simply changing the type of `app.graph` to unknown so
the typechecker will complain about every place it's currently used.
References were then updated to `app.rootGraph` if the previous usage
was correct, or actually rewritten.
By not getting rid of `app.graph`, this change already ensures that
there's no loss of functionality for custom nodes, but the prior typing
of `app.graph` can always be restored if future dissuasion of
`app.graph` usage creates issues.
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7399-Cleanup-app-graph-usage-2c76d73d365081178743dfdcf07f44d0)
by [Unito](https://www.unito.io)
## Summary
Make image preview keyboard accessible, set the key listener on the node
itself for more robust and intuitive handling, also add better aria
labels.
Follow up PR: same on Video preview.
## Changes
- **What**: LGraphNode.vue, ImagePreview.vue
- **Breaking**: <!-- Any breaking changes (if none, remove this line)
-->
- **Dependencies**: <!-- New dependencies (if none, remove this line)
-->
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7252-fix-image-preview-a11y-2c46d73d3650815b9496f3d36a8942bf)
by [Unito](https://www.unito.io)
## Summary
To prevent the flash of "loading..." and "calculating dimensions" when
loading cached images only set loading set if longer than 250ms
## Changes
- **What**: ImagePreview.vue
- **Breaking**: <!-- Any breaking changes (if none, remove this line)
-->
- **Dependencies**: <!-- New dependencies (if none, remove this line)
-->
## Review Focus
<!-- Critical design decisions or edge cases that need attention -->
<!-- If this PR fixes an issue, uncomment and update the line below -->
<!-- Fixes #ISSUE_NUMBER -->
## Screenshots (if applicable)
The retrigger loading is because i have throttled 4g slow in the demo.
So cache takes time. Normally this doesn't happen.
https://github.com/user-attachments/assets/335ca7e4-4ce1-43dd-b7d0-9ee88e187069
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-7268-fix-loading-state-to-show-loader-only-if-it-takes-more-than-150ms-2c46d73d365081a6b311f78ba3e1cffd)
by [Unito](https://www.unito.io)