Commit Graph

99 Commits

Author SHA1 Message Date
Christian Byrne
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>
2025-09-28 18:48:29 -07:00
Christian Byrne
a30705161d [type] properly type Vue node tooltip config pt object (#5832)
## Summary

Changes `any` type to proper type per the documentation here
https://primevue.org/tooltip/#api.tooltip.interfaces.TooltipOptions.pt

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5832-type-properly-type-Vue-node-tooltip-config-pt-object-27c6d73d365081ea99c2c719d9ee6586)
by [Unito](https://www.unito.io)
2025-09-28 11:50:02 -07:00
Arjan Singh
a2c7db9dc2 [fix] add InputSlot and dot error state (#5813)
## Summary

Error states were not getting propagated down to the InputSlots from the
API Repsonse

I created a provider and injected error state. It seemed like a way
better idea than prop drilling or building a composable that only two
nodes (`InputSlot` and `OutputSlot`) would need.

## Changes

The follow are now error code red when an input node has errors:
1. There's a error round border around the dot.
2. The dot is error colored.
3. The input text is error colored.

This treatment was okay after feedback from design.

## Screenshots - Error State

<img width="749" height="616" alt="Screenshot 2025-09-26 at 9 02 58 PM"
src="https://github.com/user-attachments/assets/55c7edc9-081b-4a9d-9753-120465959b5d"
/>

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5813-fix-add-InputSlot-and-dot-error-state-27b6d73d36508151a955e485f00a2d05)
by [Unito](https://www.unito.io)

---------

Co-authored-by: github-actions <github-actions@github.com>
2025-09-27 20:14:13 -07:00
Christian Byrne
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>
2025-09-27 15:12:13 -07:00
Christian Byrne
e8b9f8f4bc enforce test file-naming rule (#5820)
## Summary

Enforced test file naming conventions with ESLint rules and renamed 26
test files from `.spec.ts` to `.test.ts`.

## Changes

- **What**: Added ESLint rules to enforce `.spec.ts` files only in
`browser_tests/tests/` and `.test.ts` files only in `src/`
- **What**: Renamed 26 component/unit test files from `.spec.ts` to
`.test.ts` to comply with new convention

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5820-enforce-test-file-naming-rule-27b6d73d365081269b32ddcc9d3a5048)
by [Unito](https://www.unito.io)
2025-09-27 13:53:25 -07:00
Christian Byrne
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>
2025-09-27 10:56:46 -07:00
Simula_r
992ba9d585 style: LOD color theme (#5812)
## Summary

light mode styles for lod system

## Screenshots (if applicable)

<img width="1353" height="751" alt="image"
src="https://github.com/user-attachments/assets/3caf2e7d-10c3-4ecb-bcd6-b605a643065b"
/>

<img width="1320" height="705" alt="image"
src="https://github.com/user-attachments/assets/cb4a2675-f644-4564-af57-aa9f3920fb05"
/>

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5812-style-LOD-color-theme-27b6d73d365081fe8cd2c8c5a52b2493)
by [Unito](https://www.unito.io)
2025-09-27 10:52:28 -07:00
Christian Byrne
4b9d448b6c fix style of Select COMBO Vue node widget (#5785)
## Summary

Fixed `WidgetSelect` component styling to match other Vue node widgets
by using shared base styles.

## Changes

- **What**: Replaced hardcoded color classes with `WidgetInputBaseClass`
for consistent styling across Vue node widgets

## Review Focus

Visual consistency with other input widgets in Vue nodes interface and
proper styling inheritance.

## Screenshots (if applicable)

*Before*:

<img width="1645" height="1436" alt="Screenshot from 2025-09-25
18-12-16"
src="https://github.com/user-attachments/assets/0b985616-0cf5-44e3-8459-739d194dec7a"
/>

*After*:

<img width="1645" height="1436" alt="Screenshot from 2025-09-25
18-12-07"
src="https://github.com/user-attachments/assets/235437cf-3e1f-4bc0-8822-26fb8606b437"
/>

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5785-fix-style-of-Select-COMBO-Vue-node-widget-27a6d73d3650811a959ef8a955274987)
by [Unito](https://www.unito.io)

---------

Co-authored-by: github-actions <github-actions@github.com>
2025-09-27 10:28:26 -07:00
Arjan Singh
45f5ec15c2 [fix] remove unnecessary afterEach (#5817)
## Summary

We didn't need the `afterEach` in this test.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5817-fix-remove-unnecessary-afterEach-27b6d73d3650814bb4f1c426c5b17a54)
by [Unito](https://www.unito.io)
2025-09-27 09:36:41 -07:00
Arjan Singh
fdb15e1296 [fix] remove unnecessary awaits (#5806)
## Summary

Cleans up
src/renderer/extensions/vueNodes/composables/useNodePointerInteractions.test.ts

1. Removes unnecessary ticks.
2. Cleans up `beforeEach`

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5806-fix-remove-unnecessary-awaits-27a6d73d36508103ae1ccb8199195905)
by [Unito](https://www.unito.io)
2025-09-27 09:17:23 -07:00
Christian Byrne
75d31f9d57 fix large integer precision handling in Vue int widgets (#5787)
## Summary

Fixed increment/decrement button lockup in number widgets when values
exceed JavaScript's safe integer limit (2^53 - 1).

## Changes

- **What**: Added precision-aware button disabling and user feedback to
`WidgetInputNumberInput` component using
[Number.isSafeInteger()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isSafeInteger)
- We still need to support values greater than 2^53 because they may be
in workflows.

## Review Focus

JavaScript floating-point precision behavior at scale - buttons hide
when arithmetic operations like `value + 1` would be unreliable due to
IEEE 754 limitations. Test coverage includes edge cases (NaN, Infinity)
and boundary conditions at MAX_SAFE_INTEGER.

```mermaid
graph TD
    A[User Input] --> B{Value > 2^53?}
    B -->|No| C[Show Buttons]
    B -->|Yes| D[Hide Buttons]
    D --> E[Show Tooltip]
    E --> F[User Can Still Type]
    
    style A fill:#f9f9f9,stroke:#333,color:#000
    style F fill:#f9f9f9,stroke:#333,color:#000
```

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5787-fix-large-integer-precision-handling-in-Vue-int-widgets-27a6d73d365081d9ae00e485740cfafb)
by [Unito](https://www.unito.io)
2025-09-26 18:11:41 -07:00
Johnpaul Chiwetelu
f2e925de62 Right click vue nodes (#5790)
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)
2025-09-26 13:22:06 -07:00
Arjan Singh
62441fa0f9 [fix] do not drag on right-click + fix refs (#5784)
## Summary

Fixes drag handling logic.

## Changes

Only check for drag on left-click.

Adds handler logic for following pointer events:
1. drag termination
2. context menu
3. pointer cancel

Adds tests.

Consolidates cleanup tasks.

## Screenshots

Fixed State:

Ignore first failed drag, browser window didn't have context.


https://github.com/user-attachments/assets/00ec685a-1ef7-4102-b19b-4cdb9b201d22

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5784-fix-do-not-drag-on-right-click-fix-refs-27a6d73d3650812ea797fccf14022568)
by [Unito](https://www.unito.io)
2025-09-26 12:05:36 -07:00
Rizumu Ayaka
c96f719f91 feat: dropdown widgets vue node ui (#5624)
- Load media dropdown widgets
- Load models dropdown widgets

I added a lot of feedback effects during interactions.
I tried my best to break the Dropdown into small components.
To make it more flexible, I provided many configurable props and
v-model.

<img width="1000" alt="CleanShot 2025-09-18 at 01 54 38"
src="https://github.com/user-attachments/assets/1a413078-1547-44b8-8b48-1ce8f8e764b5"
/>

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5624-feat-dropdown-widgets-vue-node-ui-2716d73d36508115a52bc1fb6d6376d0)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Christian Byrne <cbyrne@comfy.org>
2025-09-26 12:04:39 -07:00
Christian Byrne
a6600aa109 Use localized labels for Vue node slots and inputs/outputs (fallback to names) (#5773)
## Summary

Fixes https://github.com/Comfy-Org/ComfyUI_frontend/issues/5697 by
adding internationalization support for Vue node widget labels and
output slot names with fallback to original names.

## Changes

- **What**: Added `label` field to widget data structures and
`localized_name` support for output slots
- **Breaking**: None - all changes maintain backward compatibility with
fallback to original names

## Review Focus

Translation key resolution for node definitions and proper fallback
chain for widget labels and slot names.

## Screenshots (if applicable)

Observe that there is parity between Litegraph and Vue nodes w.r.t.
localization of labels/names.

<img width="3455" height="1417" alt="Screenshot from 2025-09-25
13-19-54"
src="https://github.com/user-attachments/assets/93ee8fae-3671-4175-a941-6462f942d0f1"
/>

<img width="3455" height="1417" alt="Screenshot from 2025-09-25
13-19-38"
src="https://github.com/user-attachments/assets/9573eb86-d74a-40ed-a0b5-e30afd3da6eb"
/>

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5773-Use-localized-labels-for-Vue-node-slots-and-inputs-outputs-fallback-to-names-2796d73d365081e08fb7d38464f4aa90)
by [Unito](https://www.unito.io)

---------

Co-authored-by: github-actions <github-actions@github.com>
Co-authored-by: Alexander Brown <drjkl@comfy.org>
2025-09-25 19:47:18 -07:00
Christian Byrne
c033e9e4d7 Add theme-aware styling for Vue node tooltips (#5786)
Adds light theme colors from the
[designs](https://www.figma.com/design/31uH3r4x3xbIctuRWYW6NM/V3---Nodes?node-id=6267-16837&m=dev).

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5786-Add-theme-aware-styling-for-Vue-node-tooltips-27a6d73d36508167979fe797efcbe3c0)
by [Unito](https://www.unito.io)
2025-09-25 19:08:22 -07:00
Christian Byrne
ac93a6ba3f Disable number grouping (thousands comma separators) by default in Vue node number widgets (#5776)
## Summary

Makes the
[useGrouping](https://primevue.org/inputnumber/#api.inputnumber.props.useGrouping)
prop for number widgets disabled by default, aligning with the old UI
(also requested via design). Node authors can still enable if they want
by setting prop explicitly.

## Changes

- **What**: Modified
[WidgetInputNumberInput](https://primevue.org/inputnumber/) to disable
`useGrouping` by default, requiring explicit opt-in via widget options
- **Testing**: Added component tests covering value binding, component
rendering, step calculations, and grouping behavior

## Review Focus

UX impact on existing nodes that may have relied on default grouping
behavior and test coverage for edge cases with precision calculations.

## Screenshots (if applicable)

*Before*:

<img width="1685" height="879" alt="Screenshot from 2025-09-25 11-34-34"
src="https://github.com/user-attachments/assets/432097ab-203d-4f86-8ca0-721b27ee33de"
/>

*After*:

<img width="1951" height="1175" alt="Screenshot from 2025-09-25
11-35-27"
src="https://github.com/user-attachments/assets/74d35b62-612e-4dbf-b6e2-0ac17af03ea1"
/>


┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5776-Disable-number-grouping-thousands-comma-separators-by-default-in-Vue-node-number-widget-2796d73d365081369ca6c155335d0d57)
by [Unito](https://www.unito.io)

---------

Co-authored-by: DrJKL <448862+DrJKL@users.noreply.github.com>
Co-authored-by: Alexander Brown <drjkl@comfy.org>
Co-authored-by: github-actions <github-actions@github.com>
2025-09-25 17:46:46 -07:00
Simula_r
703de3e669 Fix/vue nodes markdown (#5771)
## Summary

Improve markdown node by making the textarea match the rendered output
width and height.

## Screenshots (if applicable)


https://github.com/user-attachments/assets/4701f947-0a4f-40f3-83c0-94e53cd10106


┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5771-Fix-vue-nodes-markdown-2796d73d365081129428fe9c38178cc4)
by [Unito](https://www.unito.io)
2025-09-25 13:21:17 -07:00
Christian Byrne
415ebfd67b Add muted state to Vue nodes (#5770)
## Summary

Added mute state support to Vue nodes with visual feedback and keyboard
shortcut functionality.

## Changes

- **What**: Implemented mute state (mode 2) for Vue nodes with opacity
styling and `Ctrl+M` hotkey support

## Review Focus

Visual consistency between bypass and mute states, and keyboard shortcut
conflict detection with existing hotkeys.

## Test Coverage

- Single node mute/unmute with `Ctrl+M` hotkey
- Multi-selection mute/unmute operations
- Visual state verification with opacity changes

## Related

- https://github.com/Comfy-Org/ComfyUI_frontend/pull/5715

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5770-Add-muted-state-to-Vue-nodes-2796d73d36508143b3edfbcb782de7c1)
by [Unito](https://www.unito.io)
2025-09-25 13:07:29 -07:00
Arjan Singh
b96bf3871c Fixes nits for #5758 (#5763)
## Summary

1. Fixes nits for #5758
2. Adds some git ignores

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5763-Fixes-nits-for-5758-2796d73d36508192b3e6feecfcacf38b)
by [Unito](https://www.unito.io)

---------

Co-authored-by: filtered <176114999+webfiltered@users.noreply.github.com>
2025-09-24 20:45:33 -05:00
Arjan Singh
1749cfa678 [fix] properly show error states (#5758)
## Summary

I want to take a more general look at `comfyApp.graph.onTrigger` but
this is the cleanest fix I could come up with for #5694.

I will explore simplifying onTrigger in a separate PR.

## Changes

1. Create a `node:slot-errors:changed` trigger.
2. Trigger it if we find any of the node slots have errors.
3. Check each node to see if there is any error present.
4. Add an error class if there are.

## Screenshots (if applicable)

Working error states!

<img width="1049" height="987" alt="Screenshot 2025-09-23 at 8 40 04 PM"
src="https://github.com/user-attachments/assets/30e13283-129c-4d9c-b342-e7037582998a"
/>

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5758-fix-properly-show-error-states-2786d73d365081cbbf62c314c7f5f380)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Alexander Brown <drjkl@comfy.org>
2025-09-24 16:34:39 -07:00
Alexander Brown
0fea54c542 Typing: Slots in VueNodeData (#5759)
## Summary

Replace the unknown type with the interface in Litegraph.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5759-Typing-Slots-in-VueNodeData-2786d73d36508194b286fad172b13c51)
by [Unito](https://www.unito.io)
2025-09-24 14:35:14 -07:00
Simula_r
0919856a05 Feat/vue nodes preview (#5747)
## Summary

Create a LGraphNodePreview.vue component to use Vue Nodes for preview
when hovering over search results / sidebar tree list.

<!-- If this PR fixes an issue, uncomment and update the line below -->
<!-- Fixes #ISSUE_NUMBER -->

## Screenshots (if applicable)

<img width="3024" height="1642" alt="image"
src="https://github.com/user-attachments/assets/d102b08e-2970-407b-aff8-3fa6333d5e38"
/>
<img width="3024" height="1646" alt="image (1)"
src="https://github.com/user-attachments/assets/b5d378d5-3cf6-4cca-9fa1-741647e8d72c"
/>

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5747-Feat-vue-nodes-preview-2786d73d3650817dbf9af458bd5dda8c)
by [Unito](https://www.unito.io)

---------

Co-authored-by: JakeSchroeder <jake@axiom.co>
Co-authored-by: AustinMroz <AustinMroz@users.noreply.github.com>
2025-09-24 13:02:47 -07:00
Alexander Brown
6449d26cee cleanup: remove useCanvasTransformSync composables. (#5742)
No I am not proud of the new placeholder arguments.

## Summary

Small change to unify the two composables before updating the logic.
Edit: Now unifies them both into the **void**.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5742-cleanup-unify-useCanvasTransformSync-composables-2776d73d36508147ad39d11de8588b2e)
by [Unito](https://www.unito.io)
2025-09-23 21:36:29 -07:00
Arjan Singh
76dd935b35 [fix] use object-contain for image preview (#5739)
## Summary

Change css so preview images are fully contained within the image
preview component

## Screenshots (if applicable)

### Before

<img width="453" height="640" alt="Screenshot 2025-09-23 at 2 55 56 PM"
src="https://github.com/user-attachments/assets/892c7fd4-b9d9-4fdd-9846-d480c5aeb6be"
/>

### After

<img width="523" height="673" alt="Screenshot 2025-09-23 at 2 55 26 PM"
src="https://github.com/user-attachments/assets/ca3f4823-9d57-4bf4-93cc-492652ee9631"
/>

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5739-fix-use-object-contain-for-image-preview-2776d73d365081f3b77ce498bd8799ec)
by [Unito](https://www.unito.io)
2025-09-23 16:04:54 -07:00
Simula_r
e4022c455a fix: add LODFallback to markdown widget (#5734)
## Summary

Add LOD fallback to markdown widget

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5734-fix-add-LODFallback-to-markdown-widget-2776d73d36508128b923d45beab50f03)
by [Unito](https://www.unito.io)

---------

Co-authored-by: JakeSchroeder <jake@axiom.co>
2025-09-23 13:05:15 -07:00
Simula_r
cec1de0147 feat: vue nodes LOD system (#5631)
## Summary

Replaced reactive (Vue-based) widget LOD with CSS visibility control.
Performance doesn't dramatically improve, but we avoid the mount/unmount
overhead during zoom/pan operations. This PR implements the visual
component of LOD—complex widgets that need lifecycle management will be
addressed separately.

### Problem & Solution
Problem: we want LOD to improve rendering performance and visual
feedback but discovered using reactivity in the current setup for it
meant mounting/unmounting caused worse lag than the performance it aimed
to fix. Switching to render all the details all the time but using css
visibility proved to be the best solution. However, it doesn't improve
rendering performance by much because the GPU texture size is the
bottleneck (from TransformPane.vue CSS transforms) and not
rasterization.

Solution: Keep all nodes/widgets mounted, use CSS visibility: hidden for
LOD. Trade memory for performance stability during zoom/pan/drag
operations.

### Technical Decision
We chose Performance > Memory:

- CSS transforms create a single GPU texture whose size depends on node
count, not widget complexity
- Mounting/unmounting hundreds of widgets during zoom = noticeable lag
from Vue VDOM diffing (since all components are mounted all the time
because of viewport culling challenge/trade off see
https://github.com/Comfy-Org/ComfyUI_frontend/pull/5510.)
- CSS visibility changes = no reactivity overhead, smooth interactions
- Result: Similar performance, but without interaction stutters

This is the visual layer only. If we want a hook into the LOD state per
node / widget that would be the next follow up system to implement.

### Next Steps (maybe)
- Chunked (split up single Transform Pane transform layer) when
rendering 1000+ nodes (maybe)
- ~~Selective unmounting API for widgets that register as "expensive"~~
- ~~Client bound hydration system~~

## Screenshots (if applicable)

<!-- Add screenshots or video recording to help explain your changes -->

<img width="1355" height="960" alt="image"
src="https://github.com/user-attachments/assets/41474d1b-9dbe-4240-a8cf-f4c9ff51d8e0"
/>
<img width="1354" height="963" alt="image"
src="https://github.com/user-attachments/assets/9f55edaa-5858-41b9-b6a8-c2d37e1649bd"
/>


┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5631-feat-vue-nodes-LOD-system-2726d73d365081c6a6c4e14aa634f19c)
by [Unito](https://www.unito.io)

---------

Co-authored-by: github-actions <github-actions@github.com>
2025-09-22 20:05:13 -07:00
Alexander Brown
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)
2025-09-22 18:47:26 -07:00
Alexander Brown
e5d4d07d32 Refactor: More state management simplification (#5721)
## Summary

Remove more procedural synchronization in favor of using reactive
references.

> Note: Also includes some fixes for issues caused during HMR.

## Review Focus

In testing it seems to work the same, but let me know if I missed
something.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5721-Refactor-More-state-management-simplification-2766d73d3650819b8d7ddc047c460f2b)
by [Unito](https://www.unito.io)
2025-09-22 13:15:33 -07:00
Christian Byrne
da0d51311b fix Vue node being dragged when interacting with widgets (e.g., resizing textarea) (#5719)
## Summary

Applying changes in
https://github.com/Comfy-Org/ComfyUI_frontend/pull/5516 to entire widget
wrapper.
 
## Changes

- **What**: Added `.stop` modifier to pointer events in NodeWidgets
component to prevent [event
propagation](https://developer.mozilla.org/en-US/docs/Web/API/Event/stopPropagation)

## Review Focus

Verify widget interactions remain functional while ensuring parent node
drag/selection behavior is properly isolated.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5719-fix-Vue-node-being-dragged-when-interacting-with-widgets-e-g-resizing-textarea-2766d73d3650815091adcd1d65197c7b)
by [Unito](https://www.unito.io)
2025-09-21 21:56:03 -07:00
Christian Byrne
95baf8d2f1 [style] update Vue node tooltip style (#5717)
## Summary

Change Vue node tooltips to align with
[design](https://www.figma.com/design/31uH3r4x3xbIctuRWYW6NM/V3---Nodes?node-id=6267-16837&m=dev)

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5717-style-update-Vue-node-tooltip-style-2766d73d365081bdb095faef17f6aeb6)
by [Unito](https://www.unito.io)
2025-09-21 20:01:33 -07:00
Christian Byrne
023e466dba fix using shift modifier to (de-)select Vue nodes (#5714)
## Summary

Fixes https://github.com/Comfy-Org/ComfyUI_frontend/issues/5688 by
adding shift modifier support for multi-selecting Vue nodes, enabling
standard shift+click selection behavior alongside existing
ctrl/cmd+click.

## Changes

- **What**: Updated Vue node event handlers to include `event.shiftKey`
in multi-select logic
- **Testing**: Added browser tests for both ctrl and shift modifier
selection behaviors

## Review Focus

Multi-select behavior consistency across different input modifiers and
platform compatibility (Windows/Mac/Linux shift key handling).

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5714-fix-using-shift-modifier-to-de-select-Vue-nodes-2756d73d365081bcb5e0fe80eacdb2f0)
by [Unito](https://www.unito.io)
2025-09-21 14:39:40 -07:00
Christian Byrne
abd6823744 [refactor] Remove redundant module comment (#5711)
Removes a comment added in initial Vue Nodes commit. The comment is
interpolated between import statements which is stylistically awkward
and it is almost totally redundant with the doc comment on the
composable:


c1d4709e96/src/renderer/extensions/vueNodes/layout/useNodeLayout.ts (L10-L14)

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5711-refactor-Remove-redundant-module-comment-2756d73d365081ef9bffe0257b3670f1)
by [Unito](https://www.unito.io)
2025-09-21 14:30:58 -07:00
Alexander Brown
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>
2025-09-20 22:14:30 -07:00
Alexander Brown
8133bd4b7b Refactor: Composable disentangling (#5695)
## Summary

Prerequisite refactor/cleanup to use a global store instead of having
nodes throw up events to a parent component that stores a reference to a
singleton service that itself bootstraps and synchronizes with a
separate service to maintain a partially reactive but not fully reactive
set of states that describe some but not all aspects of the nodes on
either the litegraph, the vue side, or both.

## Changes

- **What**: Refactoring, the behavior should not change.
- **Dependencies**: A type utility to help with Vue component props

## Review Focus

Is there something about the current structure that this could affect
that would not be caught by our tests or using the application?

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5695-Refactor-Composable-disentangling-2746d73d365081e6938ce656932f3e36)
by [Unito](https://www.unito.io)
2025-09-20 13:06:42 -07:00
Arjan Singh
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>
2025-09-20 11:44:18 -07:00
Christian Byrne
0801778f60 feat: Add Vue node subgraph title button and fix subgraph navigation with vue nodes (#5572)
## Summary
- Adds subgraph title button to Vue node headers (matching LiteGraph
behavior)
- Fixes Vue node lifecycle issues during subgraph navigation and tab
switching
- Extracts reusable `useSubgraphNavigation` composable with
callback-based API
- Adds comprehensive tests for subgraph functionality
- Ensures proper graph context restoration during tab switches



https://github.com/user-attachments/assets/fd4ff16a-4071-4da6-903f-b2be8dd6e672



┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5572-feat-Add-Vue-node-subgraph-title-button-with-lifecycle-management-26f6d73d365081bfbd9cfd7d2775e1ef)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: DrJKL <DrJKL@users.noreply.github.com>
2025-09-19 14:19:06 -07:00
Johnpaul Chiwetelu
8ffe63f54e Layoutstore Minimap calculation (#5547)
This pull request refactors the minimap rendering system to use a
unified, extensible data source abstraction for all minimap operations.
By introducing a data source interface and factory, the minimap can now
seamlessly support multiple sources of node layout (such as the
`LayoutStore` or the underlying `LiteGraph`), improving maintainability
and future extensibility. Rendering logic and change detection
throughout the minimap have been updated to use this new abstraction,
resulting in cleaner code and easier support for new data models.

**Core architecture improvements:**

* Introduced a new `IMinimapDataSource` interface and related data types
(`MinimapNodeData`, `MinimapLinkData`, `MinimapGroupData`) to
standardize node, link, and group data for minimap rendering.
* Added an abstract base class `AbstractMinimapDataSource` that provides
shared logic for bounds and group/link extraction, and implemented two
concrete data sources: `LiteGraphDataSource` (for classic graph data)
and `LayoutStoreDataSource` (for layout store data).
[[1]](diffhunk://#diff-ea46218fc9ffced84168a5ff975e4a30e43f7bf134ee8f02ed2eae66efbb729dR1-R95)
[[2]](diffhunk://#diff-9a6b7c6be25b4dbeb358fea18f3a21e78797058ccc86c818ed1e5f69c7355273R1-R30)
[[3]](diffhunk://#diff-f200ba9495a03157198abff808ed6c3761746071404a52adbad98f6a9d01249bR1-R42)
* Created a `MinimapDataSourceFactory` that selects the appropriate data
source based on the presence of layout store data, enabling seamless
switching between data models.

**Minimap rendering and logic refactoring:**

* Updated all minimap rendering functions (`renderGroups`,
`renderNodes`, `renderConnections`) and the main `renderMinimapToCanvas`
entry point to use the unified data source interface, significantly
simplifying the rendering code and decoupling it from the underlying
graph structure.
[[1]](diffhunk://#diff-3670f99330b2e24aca3cffeeac6600adf8abadd6dd585f596d60fde1dd093121L1-R11)
[[2]](diffhunk://#diff-3670f99330b2e24aca3cffeeac6600adf8abadd6dd585f596d60fde1dd093121R33-R75)
[[3]](diffhunk://#diff-3670f99330b2e24aca3cffeeac6600adf8abadd6dd585f596d60fde1dd093121L66-R124)
[[4]](diffhunk://#diff-3670f99330b2e24aca3cffeeac6600adf8abadd6dd585f596d60fde1dd093121L134-R161)
[[5]](diffhunk://#diff-3670f99330b2e24aca3cffeeac6600adf8abadd6dd585f596d60fde1dd093121L153-R187)
[[6]](diffhunk://#diff-3670f99330b2e24aca3cffeeac6600adf8abadd6dd585f596d60fde1dd093121L187-L188)
[[7]](diffhunk://#diff-3670f99330b2e24aca3cffeeac6600adf8abadd6dd585f596d60fde1dd093121R227-R231)
[[8]](diffhunk://#diff-3670f99330b2e24aca3cffeeac6600adf8abadd6dd585f596d60fde1dd093121L230-R248)
* Refactored minimap viewport and graph change detection logic to use
the data source abstraction for bounds, node, and link change detection,
and to respond to layout store version changes.
[[1]](diffhunk://#diff-d92e448dee5e30782a66b9e66d8c8b05626dffd0b2ff1032f2612b9a9b9c51f6L2-R10)
[[2]](diffhunk://#diff-d92e448dee5e30782a66b9e66d8c8b05626dffd0b2ff1032f2612b9a9b9c51f6R33-R35)
[[3]](diffhunk://#diff-d92e448dee5e30782a66b9e66d8c8b05626dffd0b2ff1032f2612b9a9b9c51f6L99-R141)
[[4]](diffhunk://#diff-d92e448dee5e30782a66b9e66d8c8b05626dffd0b2ff1032f2612b9a9b9c51f6R157-R160)
[[5]](diffhunk://#diff-338d14c67dabffaf6f68fbf09b16e8d67bead2b9df340e46601b2fbd57331521L8-R11)
[[6]](diffhunk://#diff-338d14c67dabffaf6f68fbf09b16e8d67bead2b9df340e46601b2fbd57331521L56-R64)

These changes make the minimap codebase more modular and robust, and lay
the groundwork for supporting additional node layout strategies in the
future.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5547-Layoutstore-Minimap-calculation-26e6d73d3650813e9457c051dff41ca1)
by [Unito](https://www.unito.io)
2025-09-19 13:52:57 -07:00
Christian Byrne
a975e50f1b [feat] Add tooltip support for Vue nodes (#5577)
## Summary

Added tooltip support for Vue node components using PrimeVue's v-tooltip
directive with proper data integration and container scoping.


https://github.com/user-attachments/assets/d1af31e6-ef6a-4df8-8de4-5098aa4490a1

## Changes

- **What**: Implemented tooltip functionality for Vue node headers,
input/output slots, and widgets using [PrimeVue
v-tooltip](https://primevue.org/tooltip/) directive
- **Dependencies**: Leverages existing PrimeVue tooltip system, no new
dependencies

## Review Focus

Container scoping implementation via provide/inject pattern for tooltip
positioning, proper TypeScript interfaces eliminating `as any` casts,
and integration with existing settings store for tooltip delays and
enable/disable functionality.

```mermaid
graph TD
    A[LGraphNode Container] --> B[provide tooltipContainer]
    B --> C[NodeHeader inject]
    B --> D[InputSlot inject]
    B --> E[OutputSlot inject]
    B --> F[NodeWidgets inject]

    G[useNodeTooltips composable] --> H[NodeDefStore lookup]
    G --> I[Settings integration]
    G --> J[i18n fallback]

    C --> G
    D --> G
    E --> G
    F --> G

    style A fill:#f9f9f9,stroke:#333,color:#000
    style G fill:#e8f4fd,stroke:#0066cc,color:#000
```

---------

Co-authored-by: DrJKL <DrJKL@users.noreply.github.com>
Co-authored-by: GitHub Action <action@github.com>
2025-09-19 01:07:50 -07:00
Christian Byrne
5e625a5002 [test] add Vue FormSelectButton widget component tests (#5576)
## Summary

Added comprehensive component tests for FormSelectButton widget with 497
test cases covering all interaction patterns and edge cases.

## Changes

- **What**: Created test suite for
[FormSelectButton.vue](https://vuejs.org/guide/scaling-up/testing.html)
component with full coverage of string/number/object options, PrimeVue
compatibility, disabled states, and visual styling
- **Dependencies**: No new dependencies (uses existing vitest,
@vue/test-utils)

## Review Focus

Test completeness covering edge cases like unicode characters, duplicate
values, and objects with missing properties. Verify test helper
functions correctly simulate user interactions.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5576-Add-Vue-FormSelectButton-widget-component-tests-26f6d73d36508171ae08ee74d0605db2)
by [Unito](https://www.unito.io)

---------

Co-authored-by: DrJKL <DrJKL@users.noreply.github.com>
2025-09-19 00:12:25 -07:00
Benjamin Lu
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>
2025-09-18 19:35:15 -07:00
Christian Byrne
bc85d4e87b Make Vue nodes read-only when in panning mode (#5574)
## Summary

Integrated Vue node components with canvas panning mode to prevent UI
interference during navigation.

## Changes

- **What**: Added
[canCapturePointerEvents](https://docs.comfy.org/guide/vue-nodes)
computed property to `useCanvasInteractions` composable that checks
canvas read-only state
- **What**: Modified Vue node components (LGraphNode, NodeWidgets) to
conditionally handle pointer events based on canvas navigation mode
- **What**: Updated node event handlers to respect panning mode and
forward events to canvas when appropriate

## Review Focus

Event forwarding logic in panning mode and pointer event capture state
management across Vue node hierarchy.

```mermaid
graph TD
    A[User Interaction] --> B{Canvas in Panning Mode?}
    B -->|Yes| C[Forward to Canvas]
    B -->|No| D[Handle in Vue Component]
    C --> E[Canvas Navigation]
    D --> F[Node Selection/Widget Interaction]

    G[canCapturePointerEvents] --> H{read_only === false}
    H -->|Yes| I[Allow Vue Events]
    H -->|No| J[Block Vue Events]

    style A fill:#f9f9f9,stroke:#333,color:#000
    style E fill:#f9f9f9,stroke:#333,color:#000
    style F fill:#f9f9f9,stroke:#333,color:#000
    style I fill:#e1f5fe,stroke:#01579b,color:#000
    style J fill:#ffebee,stroke:#c62828,color:#000
```

## Screenshots




https://github.com/user-attachments/assets/00dc5e4a-2b56-43be-b92e-eaf511e52542

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5574-Make-Vue-nodes-read-only-when-in-panning-mode-26f6d73d3650818c951cd82c8fe58972)
by [Unito](https://www.unito.io)

---------

Co-authored-by: GitHub Action <action@github.com>
2025-09-18 15:43:35 -07:00
Christian Byrne
37975e4eac [test] Add component test for image compare widget (#5549)
## Summary

Added comprehensive component test suite for WidgetImageCompare widget
with 410 test assertions covering display, edge cases, and integration
scenarios.

## Changes

- **What**: Created [Vue Test Utils](https://vue-test-utils.vuejs.org/)
test suite for [WidgetImageCompare
component](src/renderer/extensions/vueNodes/widgets/components/WidgetImageCompare.vue)
using [Vitest](https://vitest.dev/) testing framework

## Review Focus

Test coverage completeness for string vs object value handling,
accessibility attribute propagation, and edge case robustness including
malformed URLs and empty states.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5549-test-Add-component-test-for-image-compare-widget-26e6d73d365081189fe0d010f87d1eec)
by [Unito](https://www.unito.io)

---------

Co-authored-by: DrJKL <DrJKL@users.noreply.github.com>
2025-09-18 13:44:21 -07:00
Johnpaul Chiwetelu
4789d86fe8 Line Selection toolbox up with Vue Nodes (#5601)
This pull request improves the selection toolbox behavior during node
dragging by ensuring that it correctly responds to both LiteGraph and
Vue node drag events. The main changes introduce a reactive drag state
for Vue nodes in the layout store and update the selection toolbox
composable and Vue node component to use this state.

**Selection toolbox behavior improvements:**

* Added a helper function and separate watchers in
`useSelectionToolboxPosition.ts` to hide the selection toolbox when
either LiteGraph or Vue nodes are being dragged. This ensures consistent
UI feedback regardless of node type.
[[1]](diffhunk://#diff-57a51ac5e656e64ae7fd276d71b115058631621755de33b1eb8e8a4731d48713L171-R172)
[[2]](diffhunk://#diff-57a51ac5e656e64ae7fd276d71b115058631621755de33b1eb8e8a4731d48713R212-R224)

**Vue node drag state management:**

* Added a reactive `isDraggingVueNodes` property to the
`LayoutStoreImpl` class, along with getter and setter methods to manage
Vue node drag state. This allows other components to reactively track
when Vue nodes are being dragged.
[[1]](diffhunk://#diff-80d32fe0fb72730c16cf7259adef8b20732ff214df240b1d39ae516737beaf3bR133-R135)
[[2]](diffhunk://#diff-80d32fe0fb72730c16cf7259adef8b20732ff214df240b1d39ae516737beaf3bR354-R367)
* Updated `LGraphNode.vue` to set and clear the Vue node dragging state
in the layout store during pointer down and up events, ensuring the
selection toolbox is hidden while dragging Vue nodes.
[[1]](diffhunk://#diff-a7744614cf842e54416047326db79ad81f7c7ab7bfb66ae2b46f5c73ac7d47f2R357-R360)
[[2]](diffhunk://#diff-a7744614cf842e54416047326db79ad81f7c7ab7bfb66ae2b46f5c73ac7d47f2R376-R378)

**Dependency updates:**

* Imported the `layoutStore` in `LGraphNode.vue` to access the new drag
state management methods.
* Added missing `ref` import in `layoutStore.ts` to support the new
reactive property.



https://github.com/user-attachments/assets/d6e9c15e-63b5-4de2-9688-ebbc6a3be545

---------

Co-authored-by: GitHub Action <action@github.com>
2025-09-18 11:17:14 -07:00
Alexander Brown
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
2025-09-16 22:03:41 -07:00
Benjamin Lu
ff5d0923ca Refactor vue slot tracking (#5463)
* add dom element resize observer registry for vue node components

* Update src/renderer/extensions/vueNodes/composables/useVueNodeResizeTracking.ts

Co-authored-by: AustinMroz <austin@comfy.org>

* refactor(vue-nodes): typed TransformState InjectionKey, safer ResizeObserver sizing, centralized slot tracking, and small readability updates

* chore: make TransformState interface non-exported to satisfy knip pre-push

* Revert "chore: make TransformState interface non-exported to satisfy knip pre-push"

This reverts commit 110ecf31da.

* Revert "refactor(vue-nodes): typed TransformState InjectionKey, safer ResizeObserver sizing, centralized slot tracking, and small readability updates"

This reverts commit 428752619c.

* [refactor] Improve resize tracking composable documentation and test utilities

- Rename parameters in useVueElementTracking for clarity (appIdentifier, trackingType)
- Add comprehensive docstring with examples to prevent DOM attribute confusion
- Extract mountLGraphNode test utility to eliminate repetitive mock setup
- Add technical implementation notes documenting optimization decisions

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* remove typo comment

* convert to functional bounds collection

* remove inline import

* add interfaces for bounds mutations

* remove change log

* fix bounds collection when vue nodes turned off

* fix title offset on y

* move from resize observer to selection toolbox bounds

* refactor(vue-nodes): typed TransformState InjectionKey, safer ResizeObserver sizing, centralized slot tracking, and small readability updates

* Fix conversion

* Readd padding

* revert churn reducings from layoutStore.ts

* Rely on RO for resize, and batch

* Improve churn

* Cache canvas offset

* rename from measure

* remove unused

* address review comments

* Update legacy injection

* nit

* Split into store

* nit

* perf improvement

---------

Co-authored-by: bymyself <cbyrne@comfy.org>
Co-authored-by: AustinMroz <austin@comfy.org>
Co-authored-by: Claude <noreply@anthropic.com>
2025-09-16 19:28:04 -07:00
Alexander Brown
6b59f839e0 Devex: Faster linting (#5611)
* devex: Keep the presubmit from wiping the lint cache

* devex: typescript for eslint config

* devex: upgrade lint plugins and dedupe lockfile

* lint: Fix autofixable rules with updated vue linter

* lint: Remove default for required prop

* lint: temporarily disable warnings for missing defaults

* deps: Update vue-tsc

* lint: use the config convenience utility, switch to using projectService

* lint: Fix redundant eslint config blocks and misplaced parser

* lint: Split up parsing options for typescript vs vue files
2025-09-16 19:23:03 -07:00
Christian Byrne
0483630f82 Show sampling previews on Vue nodes (#5579)
* refactor: simplify preview state provider

- Remove unnecessary event listeners and manual syncing
- Use computed() to directly reference app.nodePreviewImages
- Eliminate data duplication and any types
- Rely on Vue's reactivity for automatic updates
- Follow established patterns from execution state provider

* feat: optimize Vue node preview image display with reactive store

- Move preview display logic from inline ternaries to computed properties
- Add useNodePreviewState composable for preview state management
- Implement reactive store approach using Pinia storeToRefs
- Use VueUse useTimeoutFn for modern timeout management instead of window.setTimeout
- Add v-memo optimization for preview image template rendering
- Maintain proper sync between app.nodePreviewImages and reactive store state

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* fix: update props usage for Vue 3.5 destructured props syntax

* [refactor] improve code style and architecture based on review feedback

- Replace inject pattern with direct store access in useNodePreviewState
- Use optional chaining for more concise conditional checks
- Use modern Array.at(-1) for accessing last element
- Remove provide/inject for nodePreviewImages in favor of direct store refs
- Update preview image styling: remove rounded borders, use flexible height
- Simplify scheduleRevoke function with optional chaining

Co-authored-by: DrJKL <DrJKL@users.noreply.github.com>

* [cleanup] remove unused NodePreviewImagesKey injection key

Addresses knip unused export warning after switching from provide/inject
to direct store access pattern.

* [test] add mock for useNodePreviewState in LGraphNode test

Fixes test failure after adding preview functionality to LGraphNode component.

* [fix] update workflowStore import path after rebase

Updates import to new location: @/platform/workflow/management/stores/workflowStore

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: DrJKL <DrJKL@users.noreply.github.com>
2025-09-16 17:34:04 -07:00
Alexander Brown
15cffe9d9e style: Flip the shade direction for charoal to go from light to dark (#5609) 2025-09-16 16:31:13 -07:00
Christian Byrne
f5b949762d [test] Add Vue node markdown widget component test (#5575)
* add markdown widget test

* [fix] correct test comments from 'is exposed' to 'is not exposed' - addresses review feedback

The TypeScript suppression comments incorrectly stated that properties
were exposed when they should indicate they are not exposed, since
@ts-expect-error is used to access private properties.

Co-authored-by: christian-byrne <christian-byrne@users.noreply.github.com>

---------

Co-authored-by: christian-byrne <christian-byrne@users.noreply.github.com>
2025-09-16 16:06:33 -07:00