## Summary
Track template metadata in English for analytics regardless of user's
locale to enable consistent statistical analysis.
## Changes
- **What**: Load English [template
index](https://github.com/Comfy-Org/ComfyUI_frontend/tree/main/public/templates)
alongside localized version (cloud builds only)
- **What**: Added `getEnglishMetadata()` method to
`workflowTemplatesStore` that returns English versions of template tags,
category, useCase, models, and license
- **What**: Updated `MixpanelTelemetryProvider` to prefer English
metadata for analytics events, falling back to localized values
## Review Focus
English template fetch only triggers in cloud builds via `isCloud` flag.
Non-cloud builds see no bundle size impact. Method returns null when
English templates unavailable, with fallback to localized data ensuring
analytics continue working in edge cases.
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6292-translate-all-analytics-to-English-for-template-metadata-2986d73d365081fdbc21f372aa9bb41e)
by [Unito](https://www.unito.io)
---------
Co-authored-by: github-actions <github-actions@github.com>
## 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>
## Summary
Implements Ctrl+Alt+click batch disconnect functionality for Vue node
output slots to match LiteGraph behavior.
## Changes
- **Feature**: Add Ctrl+Alt+click handler in `useSlotLinkInteraction.ts`
to disconnect all links from output slots
- **Test**: Add test case in `linkInteraction.spec.ts` to verify batch
disconnect behavior
- Follows existing pattern from input slot disconnect implementation
## Implementation Details
The implementation:
- Checks for Ctrl+Alt+click on output slots with existing links
- Calls `resolvedNode.disconnectOutput(index)` to batch disconnect all
links
- Marks canvas as dirty and prevents event propagation
- Matches LiteGraph canvas behavior (`LGraphCanvas.ts:2727-2731`)
- Follows same pattern as existing input slot disconnect (lines 591-611)
Note: Test currently uses `dispatchEvent` for pointerdown with modifiers
and is failing. The feature implementation is correct and matches the
existing codebase patterns, but the test interaction needs debugging.
## Summary
Fixed Vue node opacity calculation to properly combine global opacity
setting with muted/bypassed state opacity.
**Root Cause**: When global opacity setting was added as inline style
(481aa8252), it began overriding CSS `opacity-50` classes due to higher
specificity.
**Solution**: Modified `nodeOpacity` computed property to calculate
effective opacity as `globalOpacity * 0.5` for muted/bypassed states,
removing conflicting CSS classes.
## Changes
- **What**: Fixed [CSS specificity
conflict](https://developer.mozilla.org/en-US/docs/Web/CSS/Specificity)
where inline `opacity` style overrode `opacity-50` classes for
muted/bypassed nodes
- **Breaking**: None - restores intended opacity behavior
## Review Focus
Multiplicative opacity calculation ensuring muted/bypassed nodes apply
0.5 opacity on top of global opacity setting rather than being
overridden by it.
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6022-fix-Vue-node-opacity-conditions-user-node-opacity-bypass-state-muted-state-2896d73d365081c290f1da37c195c2f5)
by [Unito](https://www.unito.io)
---------
Co-authored-by: github-actions <github-actions@github.com>
Makes the litegraph `node.widgets` array `shallowReactive` and makes the
`nodeData.widgets` a `reactiveComputed` derived from the litegraph
widget data.

Making changes to the structure of litegraph items is somewhat
dangerous, but code search verifies that there are no custom nodes using
`defineProperty` on `node.widgets`
This fixes display of promoted widgets on subgraph node and any custom
nodes that dynamically add or remove widgets.
TODO:
- Investigate occasional dropped widgets.
- Some of this was confusion with `canvasOnly` widgets and widgets not
implemented in vue. Will keep investigating, but I'm not terribly
concerned with actual test cases and it being an objective improvement.
Known Issue:
- Node does not grow/shrink to fit changed widgets
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6019-Make-nodeData-widgets-reactive-2896d73d3650815691b6ee370a86a22c)
by [Unito](https://www.unito.io)
## Summary
Fixes issue where node size changes are not serialized by routing
DOM-driven node bounds updates through a single CRDT operation so Vue
node geometry stays synchronized with LiteGraph.
## Changes
- **What**: Added `BatchUpdateBoundsOperation` to the layout store,
applied it via the existing Yjs pipeline, notified link sync to
recompute touched nodes, and covered the path with a regression test
## Review Focus
Correctness of the new batch operation when multiple nodes update
simultaneously, especially remote replay/undo scenarios and link
geometry recomputation.
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5939-fix-emit-layout-change-for-batch-node-bounds-2846d73d365081db8f8cca5bf7b85308)
by [Unito](https://www.unito.io)
---------
Co-authored-by: github-actions <github-actions@github.com>
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>
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>
This pull request refactors the node selection logic in the Vue nodes
event handler composable to simplify the function signature and improve
single vs. multi-selection behavior. The main change is the removal of
the `wasDragging` parameter from the `handleNodeSelect` function, with
selection logic now determined by the current selection state. Related
test code is updated to match the new function signature.
**Node selection logic improvements:**
* Refactored the `handleNodeSelect` function in
`useNodeEventHandlersIndividual` to remove the `wasDragging` parameter,
making the function signature simpler and relying on selection state to
handle single vs. multi-selection.
* Updated the selection logic to check if multiple nodes are already
selected using `isLGraphNode`, and only perform single selection if not.
**Code and test updates:**
* Updated all calls to `handleNodeSelect` in the composable to remove
the `wasDragging` argument, ensuring consistent usage throughout the
codebase.
[[1]](diffhunk://#diff-8d3820a1ca9c569bce00671fdd6290af81315ae11b8f3d6f29a5a9d30379d084L125-R123)
[[2]](diffhunk://#diff-8d3820a1ca9c569bce00671fdd6290af81315ae11b8f3d6f29a5a9d30379d084L146-R144)
[[3]](diffhunk://#diff-8d3820a1ca9c569bce00671fdd6290af81315ae11b8f3d6f29a5a9d30379d084L173-R171)
* Updated all related test cases to use the new `handleNodeSelect`
signature without the third parameter.
[[1]](diffhunk://#diff-89bfc2a05201c6ff7116578efa45f96097594eb346f18446c70aa7125ab1811aL105-R105)
[[2]](diffhunk://#diff-89bfc2a05201c6ff7116578efa45f96097594eb346f18446c70aa7125ab1811aL125-R125)
[[3]](diffhunk://#diff-89bfc2a05201c6ff7116578efa45f96097594eb346f18446c70aa7125ab1811aL144-R144)
[[4]](diffhunk://#diff-89bfc2a05201c6ff7116578efa45f96097594eb346f18446c70aa7125ab1811aL162-R162)
[[5]](diffhunk://#diff-89bfc2a05201c6ff7116578efa45f96097594eb346f18446c70aa7125ab1811aL174-R174)
[[6]](diffhunk://#diff-89bfc2a05201c6ff7116578efa45f96097594eb346f18446c70aa7125ab1811aL187-R187)
**Utility import:**
* Added an import for `isLGraphNode` from `@/utils/litegraphUtil` to
support the updated selection logic.## Summary
<!-- One sentence describing what changed and why. -->
## Screenshots (if applicable)
https://github.com/user-attachments/assets/71e856d3-afc2-497d-826e-5b485066e7fe
---------
Co-authored-by: github-actions <github-actions@github.com>
## 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)
## Summary
Replace color/dark-color pairs in components with design tokens to allow
for easy overriding.
<!-- Also standardizes the icon pattern to simplify the tailwind config.
-->
## Changes
- **What**: Token based colors, for now, mostly.
- **Breaking**: Got approval from Design to collapse some very similar
pairs of colors that seem to have diverged in implementations over time.
Some of the colors might be a little different, but we can tweak them
later.
## Review Focus
Still have quite a few places from which to remove `dark-theme`, but
this at least gets the theming much closer.
Need to decide if I want to keep going in here or cut this and do the
rest in a subsequent PR.
## 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-5908-WIP-Make-components-themeable-2816d73d365081ffbc05d189fe71084b)
by [Unito](https://www.unito.io)
---------
Co-authored-by: github-actions <github-actions@github.com>