## 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>

Did testing on about a dozen custom nodes. Most just work.
- Some custom nodes have copy/pasted the `addDOMWidget` call with types
like `customtext` and get converted to textareas -> Not feasible to fix
here. Can open PRs into custom nodes if complaints arise.
- Only the KJNodes spline editor had mouse issues -> Can
investigate/open PR into KJNodes later.
- Many nodes don't resize gracefully. Probably best handled in a future
PR.
- Some expect to be handled like textareas. These currently have minsize
and don't scale.
- Others, like VHS previews, scale self properly, but don't update
height inside a drag operation -> node height can be set to less than
fit.
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6006-Implement-DOMWidget-for-vue-2886d73d3650817ca497c15d87d70f4f)
by [Unito](https://www.unito.io)
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>
This pull request introduces a new extension API for context menu
customization, allowing extensions to contribute items to both canvas
and node right-click menus. It adds two collection methods to the
`ComfyApp` class to aggregate these menu items from all registered
extensions, and updates the extension interface accordingly.
Comprehensive unit tests are included to verify the correct aggregation
behavior and error handling.
**Extension API for Context Menus:**
* Added optional `getCanvasMenuItems` and `getNodeMenuItems` methods to
the `ComfyExtension` interface, enabling extensions to provide context
menu items for canvas and node right-click menus (`src/types/comfy.ts`).
* Updated type imports to support the new API, including
`IContextMenuValue`, `LGraphCanvas`, and `LGraphNode`
(`src/types/comfy.ts`, `src/scripts/app.ts`).
[[1]](diffhunk://#diff-c29886a1b0c982c6fff3545af0ca8ec269876c2cf3948f867d08c14032c04d66L1-R5)
[[2]](diffhunk://#diff-bde0dce9fe2403685d27b0e94a938c3d72824d02d01d1fd6167a0dddc6e585ddR10)
**Core Implementation:**
* Implemented `collectCanvasMenuItems` and `collectNodeMenuItems`
methods in the `ComfyApp` class to gather menu items from all
extensions, with robust error handling and logging for extension
failures (`src/scripts/app.ts`).
**Testing:**
* Added a comprehensive test suite for the new context menu extension
API, covering aggregation logic, error handling, and integration
scenarios (`tests-ui/tests/extensions/contextMenuExtension.test.ts`).
This is PR 1 of the 3 PRs in the Contextmenu standardizations.
-https://github.com/Comfy-Org/ComfyUI_frontend/pull/5992
-https://github.com/Comfy-Org/ComfyUI_frontend/pull/5993
## Problem
The `update-playwright-expectations.yaml` workflow was failing with:
```
error: argument --front-end-root: The path '../dist' does not exist.
```
This was happening because the workflow was trying to launch the ComfyUI
server with `--front-end-root ../dist` before building the frontend.
## Root Cause
The workflow was missing the frontend build step entirely. It went
directly from checkout → setup server with `launch_server: true` → run
tests, skipping the crucial frontend build.
## Solution
1. Remove `launch_server: true` from `setup-comfyui-server` action call
2. Add `setup-frontend` action with `include_build_step: true` to build
the frontend
3. Add separate "Launch ComfyUI Server" step that runs AFTER frontend is
built
This ensures the `dist/` directory exists before the server tries to use
it.
## Testing
This fixes errors seen on PR #5863 and any PR using the
`/update-playwright` comment trigger.
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6005-bugfix-Fix-update-playwright-expectations-workflow-missing-frontend-build-2876d73d36508182bb1af1123f3b2a87)
by [Unito](https://www.unito.io)
## Summary
This PR refactors the GitHub Actions workflow structure to improve
reusability, maintainability, and CI performance.
## Changes
### New Actions
- **setup-comfyui-server**: New composite action that handles ComfyUI
server setup and launch
- Checks out ComfyUI repository
- Installs ComfyUI_devtools custom node
- Sets up Python environment and dependencies
- Optionally launches the server with configurable parameters
### Refactored Actions
- **setup-frontend**: Simplified to focus only on frontend-specific
tasks
- Installs pnpm and Node.js
- Installs dependencies
- Optionally builds the frontend (can be skipped when using cached
builds)
- No longer handles server setup or checkout
### Workflow Improvements
#### tests-ci.yaml
- Introduced a setup job that builds once and caches the entire
workspace
- Test jobs now restore the cached workspace instead of rebuilding
- Eliminated redundant setup steps in each test shard
- Better separation between setup and test execution phases
- Significant performance improvement through workspace caching
#### Locale Update Workflows
- Updated `update-locales.yaml` to use the new action structure
- Updated `update-locales-for-given-custom-node-repository.yaml` with
proper custom node installation
- Updated `update-node-definitions-locales.yaml` to use new actions
- Removed `working-directory` references where appropriate
#### Other Workflows
- Updated `update-playwright-expectations.yaml` to use new action
structure
- Consistent action usage across all workflows
## Benefits
1. **Better Performance**: Workspace caching eliminates redundant builds
in CI, significantly reducing test execution time
2. **Improved Maintainability**: Clear separation of concerns makes
actions easier to understand and modify
3. **Enhanced Reusability**: Actions can be composed in different ways
for different workflows
4. **DRY Principle**: Eliminated code duplication across workflows
5. **Easier Debugging**: Smaller, focused actions make it easier to
identify and fix issues
## Testing
- [ ] Verify tests-ci workflow runs successfully
- [ ] Verify locale update workflows function correctly
- [ ] Verify playwright expectations update workflow works
- [ ] Confirm cache/restore mechanism works as expected
## Related Issues
This refactoring addresses workflow complexity and reduces CI runtime by
leveraging GitHub Actions caching more effectively.
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5949-refactor-Reorganize-GitHub-Actions-for-better-reusability-2846d73d365081ae8e16f151423b5a88)
by [Unito](https://www.unito.io)
---------
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Alexander Brown <drjkl@comfy.org>
Co-authored-by: DrJKL <DrJKL0424@gmail.com>
## 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)
## Summary
Automatically removes the `New Browser Test Expectations` label after
the Playwright expectations update workflow completes.
## Changes
- Added a cleanup step to
`.github/workflows/update-playwright-expectations.yaml` that removes the
label using `gh pr edit --remove-label`
- Uses `if: always() && github.event_name == 'pull_request'` to ensure:
- The label is removed even if the workflow fails
- The label is only removed when triggered by the label event (not the
`/update-playwright` comment trigger)
## Benefits
- Cleaner PR label management
- Labels can be re-applied to trigger additional expectations updates
without manual cleanup
- Consistent with the claude-review workflow pattern
- Reduces noise in the PR interface
## Context
This is part of a broader effort to automatically clean up temporary
action-triggering labels across all workflows. The first PR in this
series (#5983) added the same functionality to the claude-review
workflow.
## Test Plan
- Apply the `New Browser Test Expectations` label to a PR to verify the
workflow removes it automatically after completion
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5998-feat-Auto-remove-New-Browser-Test-Expectations-label-after-workflow-completes-2876d73d365081e29fbbe6e3127ca973)
by [Unito](https://www.unito.io)
## 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
Fixes the Playwright update workflow broken by #5960. When triggered by
adding the "New Browser Test Expectations" label, the workflow was left
in a detached HEAD state, causing `git push` to fail.
## Changes
- **Restores branch checkout for label triggers**: Uses
`github.head_ref` to fetch and checkout the branch when triggered by
`pull_request` events
- **Preserves comment trigger functionality**: Keeps `gh pr checkout`
for `issue_comment` events using `github.event.issue.number`
- **Event-specific push logic**: Uses explicit `git push origin HEAD:${{
github.head_ref }}` for label triggers, plain `git push` for comment
triggers
## Root Cause
PR #5960 removed the original branch checkout logic:
```yaml
git fetch origin ${{ github.head_ref }}
git checkout -B ${{ github.head_ref }} origin/${{ github.head_ref }}
git push origin HEAD:${{ github.head_ref }}
```
This left the label-triggered workflow in detached HEAD after
`actions/checkout@v5`, breaking the push step.
## Testing
This fix properly uses `github.head_ref` only when it's available
(`pull_request` events) and `github.event.issue.number` only for
`issue_comment` events where `head_ref` isn't available.
Fixes#5960
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5985-ci-Fix-detached-HEAD-state-in-Playwright-update-workflow-2866d73d36508183b63bca03a40da4a8)
by [Unito](https://www.unito.io)
## Summary
Closes the zoom menu popup when clicking show/hide minimap to prevent
the menu from remaining open after toggling.
## Changes
- **What**: Adds `close` event emission from `ZoomControlsModal` when
minimap toggle is clicked, wired to `hideModal` in parent
`GraphCanvasMenu`
- **Tests**: Adds unit tests verifying close behavior for minimap toggle
vs other commands
## Review Focus
This fixes the immediate UX issue where the zoom popup remained open
after toggling minimap visibility. However, the minimap toggle's
placement within the zoom menu is **not** ideal—it's not intuitive to
look for minimap controls within zoom controls. This PR addresses the
current UX friction without tackling the broader discoverability issue.
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5974-Close-zoom-menu-when-toggling-minimap-visibility-2866d73d365081bdbb0bfeb0da4b8c2b)
by [Unito](https://www.unito.io)
---------
Co-authored-by: DrJKL <DrJKL0424@gmail.com>
## Summary
Automatically removes the `claude-review` label after the Claude PR
review workflow completes, regardless of success or failure.
## Changes
- Added a cleanup step to `.github/workflows/claude-pr-review.yml` that
removes the label using `gh pr edit --remove-label`
- Uses `if: always()` to ensure the label is removed even if the review
fails
- This prevents label accumulation and allows the label to be re-applied
for additional reviews
## Benefits
- Cleaner PR label management
- Labels can be re-applied to trigger additional reviews without manual
cleanup
- Reduces noise in the PR interface
## Test Plan
- Apply the `claude-review` label to this PR to verify the workflow
removes it automatically after completion
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5983-feat-Auto-remove-claude-review-label-after-CI-review-completes-2866d73d365081da929cd393996010e1)
by [Unito](https://www.unito.io)
This pull request introduces improvements to the workflow template
selector and search box components, focusing on better user experience
and more accurate terminology. The most significant changes include
adding debounced search input handling, updating sorting option labels,
and refining UI styling for consistency.
**Search functionality improvements:**
* Refactored `SearchBox.vue` to use an internal search query state and a
debounced update mechanism, reducing unnecessary parent updates and
improving responsiveness. The parent model is updated only after the
user stops typing for 300ms. (`src/components/input/SearchBox.vue`)
[[1]](diffhunk://#diff-08f3b0c51fbfe63171509b9944bf7558228f6c2596a1ef5338e88ab64585791bL6-R6)
[[2]](diffhunk://#diff-08f3b0c51fbfe63171509b9944bf7558228f6c2596a1ef5338e88ab64585791bR39-R62)
* Updated the search box in `WorkflowTemplateSelectorDialog.vue` to use
the new debounced search model and increased its size for better
visibility.
(`src/components/custom/widget/WorkflowTemplateSelectorDialog.vue`)
**Sorting and terminology updates:**
* Changed sorting option labels to use more precise terminology, such as
"VRAM Usage (Low to High)" and added new locale strings for sorting
options.
(`src/components/custom/widget/WorkflowTemplateSelectorDialog.vue`,
`src/locales/en/main.json`)
[[1]](diffhunk://#diff-2c860bdc48e907b1b85dbef846599d8376dd02cff90f49e490eebe61371fecedL623-R623)
[[2]](diffhunk://#diff-bbf3da78aeff5b4d868a17a6960d109cb0627316cda2f9b5fa7c08e9abd93be6L1032-R1035)
**UI and styling adjustments:**
* Adjusted the width of the sorting dropdown for better alignment and
consistency.
(`src/components/custom/widget/WorkflowTemplateSelectorDialog.vue`)
* Updated active navigation item background color for improved visual
clarity. (`src/components/widget/nav/NavItem.vue`)
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5975-Workflow-templates-review-2866d73d365081419257f9df2bab9c5b)
by [Unito](https://www.unito.io)
https://github.com/user-attachments/assets/4f72d515-f114-4cd4-8a76-6abbe906e5bb
## Problem
Our CI tests were experiencing non-reproducible results where:
- Tests would pass on a PR initially
- The same PR would fail later when main HEAD changed
- Screenshot comparisons showed excessive differences between expected
vs actual
- Blake identified: *"tests are not reproducible inside a branch - they
change every time main HEAD changes"*
## Root Cause
The issue was caused by **explicit `repository` parameters** in our
`actions/checkout` steps:
```yaml
- name: Checkout ComfyUI_frontend
uses: actions/checkout@v5
with:
repository: 'Comfy-Org/ComfyUI_frontend' # ← This was the problem!
path: 'ComfyUI_frontend'
```
According to GitHub Actions documentation:
> **When checking out the repository that triggered a workflow, `ref`
defaults to the reference or SHA for that event. Otherwise, uses the
default branch.**
When you specify an explicit `repository` parameter (even if it's the
same repo), GitHub Actions treats it as "otherwise" and defaults to the
**main branch** instead of using the **PR context**.
## The Fix
Remove the explicit `repository` parameter when checking out the same
repository:
```yaml
- name: Checkout ComfyUI_frontend
uses: actions/checkout@v5
with:
path: 'ComfyUI_frontend' # No repository parameter = uses PR context
```
## Changes Made
- ✅ Removed `repository: 'Comfy-Org/ComfyUI_frontend'` from setup job
checkout
- ✅ Removed `repository: 'Comfy-Org/ComfyUI_frontend'` from
merge-reports job checkout
- ✅ Updated setup-frontend action to use `actions/checkout@v5` for
consistency
- ✅ Simplified workflow by removing unnecessary `ref` and `fetch-depth`
parameters
## How This Fixes the Problem
**Before:**
- Setup job checked out main branch (due to explicit repository)
- Tests ran PR code against main branch snapshots
- Results varied based on what was in main at the time
**After:**
- Setup job checks out PR merge commit (natural PR context)
- Tests run PR code against PR snapshots
- Results are consistent and reproducible
## Why It Worked Before (Sometimes)
The explicit `repository` parameter has been there for a long time, but
the issue became more apparent recently due to:
1. GitHub Actions behavior changes over time
2. Increased frequency of main branch updates
3. More sensitive screenshot comparison tests
4. Complex cache/restore workflow where timing mattered
The fix ensures deterministic behavior regardless of GitHub's internal
changes.
## Testing
This change makes the CI behavior explicit and predictable:
- ✅ PR tests will always use PR context
- ✅ Push tests will always use pushed commit
- ✅ No dependency on GitHub's default behavior interpretation
- ✅ Simplified workflow with fewer moving parts
Resolves the issues described in `.github/workflows/problem.log`.
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5950-Fix-CI-Remove-explicit-repository-parameter-causing-non-reproducible-test-results-2846d73d36508159a848c4a2e14a0fb1)
by [Unito](https://www.unito.io)
Co-authored-by: Alexander Brown <drjkl@comfy.org>
## Summary
Currently, the "What's Changed" popup toast in bottom left appears after
updating if three conditions are true:
1. Using Desktop app
2. Don't have notifications disabled in settings
3. Have not seen/dismissed the notification before
Then the fourth condition is
4. At least 1 of the last 2 notifications is medium or high priority
However, we only ever show the most recent notification, so this logic
is flawed. In addition, it presents issues:
- When the changelog is first generated by AI, it is marked as "low"
priority until human review. But if the changelog _prior_ to that is
"medium" or "high", the AI-generated one might get shown anyway - which
frustrates the intended process.
There's also a bug fixed here concidentally where if the server only
returns a single entry, it is never shown (due to `slice(0, -1)` syntax
when checking priorities).
## Changes
- **What**: Updated Pinia release store to read `attention` from the
newest release only and expanded unit coverage for toast visibility
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5959-fix-what-s-changed-release-toast-attention-level-logic-2856d73d36508141b9b2d8d3b11153b2)
by [Unito](https://www.unito.io)
## Problem
The `update-locales` workflow was failing with the error:
```
Can't find 'action.yml', 'action.yaml' or 'Dockerfile' under '/home/runner/work/ComfyUI_frontend/ComfyUI_frontend/.github/actions/setup-frontend'.
Did you forget to run actions/checkout before running your local action?
```
Ref:
https://github.com/Comfy-Org/ComfyUI_frontend/actions/runs/18270266173/job/52011427608
## Solution
Added a checkout step using `actions/checkout@v5` before the "Setup
Frontend" step. This ensures the repository code (including the local
action definition) is available before GitHub Actions tries to use it.
## Changes
- Added checkout step to `.github/workflows/update-locales.yaml`
- Uses `actions/checkout@v5` to checkout the repository before
referencing the local custom action
This is a minimal fix that follows GitHub Actions best practices.
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5938-fix-Add-checkout-step-before-using-local-action-in-update-locales-workflow-2846d73d365081cfb720ffaa528ce26e)
by [Unito](https://www.unito.io)
---------
Co-authored-by: github-actions <github-actions@github.com>
## 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>
- Fixes automatic promotion of image previews by ~~more correctly
handling a usage of `requestAnimationFrame` and~~ introducing a means to
perform actions upon successful load of preview.
- When workflows contain an old proxyWidget property in string form,
parse it instead of throwing an error.
- Do not overlay the `label` of promoted widgets. Further consideration
is needed, but this resolves the primary annoyance and prevents
untranslated widget names
See #5914
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5911-Subgraph-widget-promotion-fixes-2826d73d365081838ffeeea4b8d7068c)
by [Unito](https://www.unito.io)
## Summary
Restricts Vite's dependency optimization scanning entry points to the
root `index.html`, preventing excessive error messages from scanning
unintended files in other packages.
## Changes
- **What**: Adds `entries: ['index.html']` to `optimizeDeps` in
vite.config.mts
- **Breaking**: None
## Review Focus
May require additional entries or inversion - exclude-based approach
instead of include-based - if possible.
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5934-Restrict-Vite-entry-point-to-index-html-2846d73d3650816fbf45fa29493891ae)
by [Unito](https://www.unito.io)
## Summary
Adds [stylelint](https://stylelint.io/) configuration and tooling to
enforce CSS/SCSS code quality and consistency across Vue components.
Starts with 21 focused rules for linting CSS in Vue SFC files and
standalone stylesheets. Configuration uses postcss-html to parse Vue
`<style>` blocks and includes whitelists for Tailwind v4 at-rules
(`@reference`, `@plugin`, `@custom-variant`, `@utility`) and
Electron-specific CSS properties (`speak: none`, `app-region`). Rules
emphasize modern CSS syntax (numeric font weights, modern color
functions, double-colon pseudo-elements) while avoiding overly
opinionated rules like hex color length enforcement (for now).
Currently finds 113 issues (79% auto-fixable). This PR only adds the
tooling via `pnpm stylelint` and `pnpm stylelint:fix` scripts - no
pre-commit hooks or CI integration yet. A follow-up PR will auto-fix the
fixable issues and optionally add enforcement to the commit workflow.
## Changes
- **What**: Integrated [stylelint](https://stylelint.io/) with Vue.js
support via postcss-html parser
- **Dependencies**: Added `stylelint@16.24.0`, `postcss-html@1.8.0`
## Review Focus
CSS rule strictness and Tailwind CSS compatibility - particularly the
`no-descending-specificity` rule and Tailwind-specific function ignores.
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5926-ci-add-stylelint-dependency-and-minimal-config-2836d73d3650813ea7b7eb714ba7748a)
by [Unito](https://www.unito.io)
## Summary
Adds automated npm publishing for @comfyorg/desktop-ui package with
version management and release workflows.
- Ref: #5912
## Changes
- **What**: Three GitHub Actions workflows for desktop-ui npm publishing
automation
### Two functions
1. Bump action - Just creates a version bump PR for `desktop-ui`
2. Publish action - Can be run manually - essentially a function with
params / void return
### One automation
- Watches for matching commits, then calls the Publish action with
pre-filled details
## Review Focus
Security hardening and workflow correctness.
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5915-Add-Desktop-UI-npm-publishing-workflows-2826d73d365081d9b7f8d7f752536ceb)
by [Unito](https://www.unito.io)
## Summary
Extracts desktop UI into apps/desktop-ui package with minimal changes.
## Changes
- **What**:
- Separates desktop-specific code into standalone package with
independent Vite config, router, and i18n
- Drastically simplifies the main app router by removing all desktop
routes
- Adds a some code duplication, most due to the existing design
- Some duplication can be refactored to be *simpler* on either side - no
need to split things by `isElectron()`
- Rudimentary storybook support has been added
- **Breaking**: Stacked PR for publishing must be merged before this PR
makes it to stable core (but publishing _could_ be done manually)
- #5915
- **Dependencies**: Takes full advantage of pnpm catalog. No additional
dependencies added.
## Review Focus
- Should be no changes to normal frontend operation
- Scripts added to root package.json are acceptable
- The duplication in this PR is copied as is, wherever possible. Any
corrections or fix-ups beyond the scope of simply migrating the
functionality as-is, can be addressed in later PRs. That said, if any
changes are made, it instantly becomes more difficult to separate the
duplicated code out into a shared utility.
- Tracking issue to address concerns: #5925
### i18n
Fixing i18n is out of scope for this PR. It is a larger task that we
should consider carefully and implement properly. Attempting to isolate
the desktop i18n and duplicate the _current_ localisation scripts would
be wasted energy.
## 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>
Summary
- Adds playwright.config.ts and playwright.i18n.config.ts to
typescript-eslint projectService.allowDefaultProject in
eslint.config.ts.
Why
- Pre-commit runs lint-staged, which lints staged TypeScript files
including Playwright config files.
- These configs are not included in any tsconfig, so typescript-eslint’s
project service can’t find a project and fails with:
"Parsing error: .../playwright.config.ts was not found by the project
service. Consider either including it in the tsconfig.json or including
it in allowDefaultProject".
What this changes
- Whitelists the two Playwright config files to use the default project
(isolated file parsing) so ESLint can parse and lint them without being
part of a tsconfig.
- Does not affect application code linting, which remains fully
type-aware via existing tsconfigs.
Alternatives considered
- Include these configs in a dedicated ESLint tsconfig (e.g.,
tsconfig.eslint.json) and point ESLint to it.
- Exclude Playwright config files from lint-staged (would reduce lint
coverage for them).
- Keep as TypeScript but non-type-aware: current approach is minimal and
avoids touching tsconfig scopes.
Verification
- Reproduced pre-commit failure when changing playwright.config.ts.
- After this change, `pnpm exec eslint --cache --fix
playwright.config.ts` succeeds.
- `pnpm typecheck` passes.
Notes
- No changes to Playwright runtime behavior. This only affects linting.
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5901-chore-eslint-allow-default-project-for-Playwright-configs-to-fix-pre-commit-linting-2816d73d36508156b94dfeff79a91c7f)
by [Unito](https://www.unito.io)
## 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)
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)
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)
## Summary
Converts 81 package dependencies to use pnpm catalog references for
centralized version management.
## Changes
- **What**: All dependencies matching catalog versions now use
`catalog:` references
- **Dependencies**: axios catalog entry corrected from ^1.11.0 to ^1.8.2
- Also removes a redundant knip config line
### Some things that shouldn't matter
- TypeScript was updated from ^5.4.5 to catalog reference (^5.9.2), but
the project was already resolving to 5.9.2 so this has no practical
impact.
- axios catalog version was corrected from ^1.11.0 back to ^1.8.2 to
match the main package version.
- Autoformatted LGraphNode.ts from another PR by running pnpm lint.
Oops.
## Summary
Hide Google/GitHub SSO login options when the UI is accessed from
**non‑local** addresses.
This PR also adds a **static whitelist** (editable in code) so we can
allow additional hosts if needed.
Default whitelisted addresses:
1. `localhost` and any subdomain: `*.localhost`
2. IPv4 loopback `127.0.0.0/8` (e.g., `127.x.y.z`)
4. IPv6 loopback `::1` (including equivalent textual forms such as
`::0001`)
## Changes
- **What**:
* Add `src/utils/hostWhitelist.ts` with `normalizeHost` and
`isHostWhitelisted` helpers.
* Update `SignInContent.vue` to **hide** SSO options when
`isHostWhitelisted(normalizeHost(window.location.hostname))` returns
`false`.
- **Breaking**:
* Users accessing from Runpod or other previously allowed **non‑local**
hosts will **lose** SSO login options.
If we need to keep SSO there, we should add those hosts to the whitelist
in `hostWhitelist.ts`.
## Review Focus
1. Verify that logging in from local addresses (`localhost`,
`*.localhost`, `127.0.0.1`, `::1`) **does not change** the current
behavior: SSO is visible.
2. Verify that from a **non‑local** address, SSO options are **not**
displayed.
## Screenshots (if applicable)
UI opened from `192.168.2.109` address:
<img width="500" height="990" alt="Screenshot From 2025-09-27 13-22-15"
src="https://github.com/user-attachments/assets/c97b10a1-b069-43e4-a26b-a71eeb228a51"
/>
UI opened from default `127.0.0.1` address(nothing changed):
<img width="462" height="955" alt="Screenshot From 2025-09-27 13-35-27"
src="https://github.com/user-attachments/assets/bb2bf21c-dc8d-49cb-b48e-8fc6e408023c"
/>
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5815-feat-auth-Allow-SSO-login-only-for-whitelisted-addresses-localhost-27b6d73d365081ccbe84c034cf8e416d)
by [Unito](https://www.unito.io)
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>
Currently the claude review action will be skipped if any tests have
failed. This is not really necessary, it will be more efficient to allow
claude to review while still waiting for tests.
This accounts for scenario where there is an expected visual baseline
change, but the PR author doesn't want to regenerate baselines until
everything is approved and ready to merge (as generating right away
before you know whether changes will be requested can be a hassle).
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5882-ci-allow-Claude-review-even-when-Playwright-and-Vitest-checks-have-failed-27f6d73d365081ccbcdaff7104edc2fd)
by [Unito](https://www.unito.io)
By default, in this case the checkout action will checkout to github's
temporary merge base ref, which may include changes from the base branch
when the base branch moves.
This happened in this review:
https://github.com/Comfy-Org/ComfyUI_frontend/pull/5866#pullrequestreview-3287366541
To prevent this, the PR's HEAD SHA was specified to be used
specifically, keeping claude's reviews only looking at that PR's branch.
## Summary
Adds pnpm catalog to centralize dependency versions across the monorepo.
## Changes
- **What**: Consolidates dependencies into single default catalog with
[`prefer` mode](https://pnpm.io/catalogs#catalog-mode)
- **Dependencies**: No new dependencies - reorganizes existing version
management
## Review Focus
The catalog uses `prefer` mode which automatically uses catalog versions
for packages already in the catalog, falling back to direct versions for
packages not yet cataloged.
### Example Usage
When adding a dependency already in the catalog:
```bash
pnpm add vue
```
This automatically uses `"vue": "catalog:"` in `package.json` instead of
a direct version.
## Summary
Fixes two errors with subgraph progress states:
1. Nodes inside subgraphs were not having progress state shown
2. Subgraph nodes (outer representation) themselves did not have a
visible progress state
1 is fixed by using locator IDs instead of local node IDs.
2 is fixed by ensuring the subgraph title button does not wrap to a
newline and thus block the progress bar under the node header.
## Changes
- **What**: Updated `useNodeExecutionState` composable to use
`nodeLocatorId` for tracking execution state across subgraph boundaries
- **What**: Modified NodeHeader layout to fix subgraph enter button
positioning with proper flexbox gap
## Review Focus
Execution state tracking accuracy for nested subgraph nodes and
NodeHeader layout consistency across different node types.
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5842-fix-progress-state-on-Vue-nodes-in-subgraphs-27c6d73d365081cb8335c8bb5dbd74f7)
by [Unito](https://www.unito.io)
---------
Co-authored-by: github-actions <github-actions@github.com>
## Summary
- Upgrades all GitHub Actions workflows to use `actions/checkout@v5`
- Updates 33 instances across 17 workflow files
- Ensures we're using the latest version with security patches and
improvements
## Changes
Updated the following workflow files from `actions/checkout@v4` to
`actions/checkout@v5`:
- `.github/workflows/backport.yaml`
- `.github/workflows/chromatic.yaml`
- `.github/workflows/claude-pr-review.yml`
- `.github/workflows/create-release-candidate-branch.yaml`
- `.github/workflows/dev-release.yaml`
- `.github/workflows/devtools-python.yaml`
- `.github/workflows/i18n-custom-nodes.yaml`
- `.github/workflows/json-validate.yaml`
- `.github/workflows/lint-and-format.yaml`
- `.github/workflows/pr-playwright-deploy.yaml`
- `.github/workflows/pr-storybook-deploy.yaml`
- `.github/workflows/test-ui.yaml`
- `.github/workflows/update-electron-types.yaml`
- `.github/workflows/update-manager-types.yaml`
- `.github/workflows/update-registry-types.yaml`
- `.github/workflows/version-bump.yaml`
- `.github/workflows/vitest.yaml`
Note: `.github/workflows/publish-frontend-types.yaml` and
`.github/workflows/release.yaml` were already using v5.
## Test plan
- [ ] CI workflows should continue to run successfully
- [ ] No functional changes - this is a dependency version upgrade only
🤖 Generated with [Claude Code](https://claude.ai/code)
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5859-ci-Upgrade-actions-checkout-from-v4-to-v5-27e6d73d3650815488adee20c74c0464)
by [Unito](https://www.unito.io)
Co-authored-by: Claude <noreply@anthropic.com>
## Summary
- Removed the optional `ref: master` parameter from the ComfyUI checkout
step in the setup-frontend action
- The ref parameter defaults to the repository's default branch when
omitted
## Details
The `ref: master` specification in
`.github/actions/setup-frontend/action.yml` is unnecessary since GitHub
Actions will automatically use the repository's default branch when the
ref parameter is not provided.
This simplifies the configuration and makes it more maintainable, as the
action will automatically follow any future changes to the default
branch name.
## Test plan
- [ ] Verify that GitHub Actions workflows using this composite action
still work correctly
- [ ] Confirm ComfyUI is checked out properly in CI/CD pipelines
Generated with [Claude Code](https://claude.ai/code)
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5858-Remove-optional-ref-master-from-setup-frontend-action-27e6d73d365081aeb632f2d0e76f267d)
by [Unito](https://www.unito.io)
Co-authored-by: Claude <noreply@anthropic.com>
## Summary
- Adds a local composite action at `.github/actions/setup-frontend` to
replace the external `Comfy-Org/ComfyUI_frontend_setup_action`
- Follows the same pattern as PR #5754 (sno-playwright-composite-action)
for consistency
- Updates workflows to use the new local composite action
## Motivation
Similar to the Playwright composite action, this change:
- Reduces external dependencies on separate action repositories
- Provides better control over versioning and updates
- Maintains consistency with other composite actions in the repository
- Simplifies maintenance by keeping all CI/CD logic in one place
## Changes
### New composite action: `.github/actions/setup-frontend/action.yml`
Direct mirror of the external action with the same 2 inputs:
- `extra_server_params`: Additional parameters to pass to ComfyUI server
- `devtools_ref`: Reference to use for ComfyUI_devtools
The action:
1. Checks out ComfyUI, ComfyUI_frontend, and ComfyUI_devtools
2. Sets up pnpm, Node.js (LTS), and Python (3.10)
3. Installs all dependencies (Python packages, npm packages)
4. Builds the frontend
5. Starts the ComfyUI server with the built frontend
### Updated workflows:
- `.github/workflows/i18n.yaml`
- `.github/workflows/i18n-node-defs.yaml`
- `.github/workflows/test-browser-exp.yaml`
All workflows now use the local composite action instead of
`Comfy-Org/ComfyUI_frontend_setup_action@v3`
## Test plan
- [ ] Verify all updated workflows pass CI tests
- [ ] Confirm the composite action works in all scenarios
- [ ] Check that build and server startup work as expected
## Related PRs
- #5754 - Similar approach for Playwright composite action
🤖 Generated with [Claude Code](https://claude.ai/code)
## Summary
- Improves Storybook deployment and PR comment workflow similar to the
Playwright improvements in #5425
- Creates unified deployment and commenting system for better
maintainability
- Adds Cloudflare Pages deployment for Storybook previews
## Deployment Cases Matrix
| Case | PR Type | Branch | Deployment | Features |
|------|---------|--------|------------|----------|
| **1** | Non-forked PR | `version-bump-*` | ✅ Chromatic | • Visual diff
testing<br>• Chromatic build URL<br>• Chromatic Storybook URL<br>• Shows
visual changes |
| **2** | Non-forked PR | All branches | ✅ Cloudflare Pages | • Live
Storybook preview<br>• pages.dev URL<br>• No visual diff |
| **3** | Forked PR | Any branch | ✅ Cloudflare Pages | • Live Storybook
preview<br>• pages.dev URL<br>• No visual diff<br>• Runs via separate
workflow to avoid permission problems |
### Key Points:
- **Chromatic** (paid service): Only for `version-bump-*` branches to
track visual changes between releases
- **Cloudflare Pages** (free): For all other PRs to provide Storybook
preview without visual diff
- **Security**: Forked PRs use a separate workflow with limited
permissions
## Changes
### New Features
- 🚀 **Cloudflare Pages Deployment**: Storybook builds are now deployed
to Cloudflare Pages for easy preview
- 🔄 **Unified Script**: Single reusable shell script handles both
deployment and PR comments
- 🔒 **Better Security**: Separate workflows for fork vs non-fork PRs
### Improvements
- ♻️ **Retry Logic**: Automatic retry (3 attempts) for failed
deployments
- 📝 **Better Comments**: Clearer PR comments with deployment links and
status
- 🎯 **Simplified Logic**: Workflow logic moved to reusable script for
easier maintenance
- ⚡ **Better Error Handling**: Proper handling of different workflow
conclusions
- 🐛 **Fixed Comment Output**: Deployment logs now properly redirected to
stderr
### Files Changed
- `scripts/cicd/pr-storybook-deploy-and-comment.sh` - New unified
deployment script
- `.github/workflows/chromatic.yaml` - Updated to use new script and add
deployment
- `.github/workflows/pr-storybook-deploy.yaml` - New workflow for forked
PRs
- `.github/workflows/pr-storybook-comment.yaml` - Removed (replaced by
new system)
## ⚠️ Required Setup
The Cloudflare Pages project `comfyui-storybook` needs to be created
under the organization's Cloudflare account:
```bash
# Using the account ID from GitHub secrets
export CLOUDFLARE_ACCOUNT_ID=5ae914d9b87bcf6bbe1ada5798f92a5f
export CLOUDFLARE_API_TOKEN=<org-token>
wrangler pages project create comfyui-storybook --production-branch main
```
**Note**: The project must be created under the same Cloudflare account
that's configured in the GitHub secrets.
## Test Plan
- [x] Create Cloudflare Pages project `comfyui-storybook`
- [x] Workflow runs successfully on all PRs
- [x] PR comments are posted correctly at start and completion
- [x] Storybook deploys to Cloudflare Pages with correct URL
- [ ] Fork PRs are handled by separate workflow
- [ ] Non-fork PRs get inline deployment
- [ ] version-bump-* branches show Chromatic info
## References
- Similar improvements for Playwright: #5459
- Based on pattern from sno-fix-playwright-comment-2 branch
🤖 Generated with [Claude Code](https://claude.ai/code)
---------
Co-authored-by: Claude <noreply@anthropic.com>
## Summary
Extracts shared formatting and network utilities into dedicated
workspace package.
## Changes
- **What**: Created `@comfyorg/shared-frontend-utils` package containing
formatUtil and networkUtil
- **Breaking**: None - utilities remain accessible via path aliases in
`tsconfig`
Split `createAnnotatedPath` and `electronMirrorCheck` out and left in
frontend, due to their tightly-coupled nature. See [discussion on this
PR](https://github.com/Comfy-Org/ComfyUI_frontend/pull/5843#issuecomment-3344724727).
## 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>
## 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>
## Summary
Extracts ComfyUI registry types into a dedicated workspace package for
better modularity.
## Changes
- **What**: Created `@comfyorg/registry-types` package to house
generated type definitions
- **Breaking**: None - maintains backward compatibility through
re-exports at original path
- **Dependencies**: Added `@comfyorg/registry-types` as workspace
dependency
## Review Focus
Is this the right granularity for package extraction, or should registry
types be part of a larger shared package?
PR split into two tiny diffs:
- [Part
one](f8d3d2fa01)
- [Part
two](f8d3d2fa01..c48ca84336)
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5840-Extract-registry-types-into-workspace-package-27c6d73d365081dbb824d680ce739316)
by [Unito](https://www.unito.io)
## Summary
Added CI workflow and npm script for Python syntax validation in
devtools directory.
## Changes
- **What**: Added GitHub Actions workflow for Python syntax checking
with `python3 -m compileall`
- **Dependencies**: Added `python3` binary to knip ignore list
## Review Focus
Workflow triggers correctly on devtools path changes and Python syntax
validation covers all relevant files.
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5841-ci-add-Python-syntax-checking-workflow-on-changes-to-devtools-27c6d73d365081b8963dd4600a233852)
by [Unito](https://www.unito.io)
## Summary
Added GitHub Actions workflow and shell script to validate JSON syntax
in repository files, as in the past we have committed locales files with
invalid JSON.
## Changes
- **What**: Added CI workflow for JSON validation with `jq` syntax
checking
- **Dependencies**: CI workflow requires `jq` (pre-installed on
ubuntu-latest runners)
## Review Focus
Script exclusion patterns for TSConfig files and environment variable
override mechanism (`JSON_LINT_EXCLUDES`).
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5837-ci-add-JSON-validation-CI-workflow-27c6d73d365081a199b1d9ae9e4edfa4)
by [Unito](https://www.unito.io)
## Summary
Updates AGENTS.md to be more universal and contributor-friendly by
removing user-specific preferences.
## Changes
- **What**: Refined AGENTS.md to remove individual preferences, one-time
setup tasks, and conflicting i18n instructions
## Review Focus
These updates make agent instructions work better for all contributors
by:
- Removing individual coding preferences in favor of project-wide
standards
- Eliminating one-time environment setup that clutters agent context
- Removing i18n instructions that caused agents to make unwanted changes
- Improving PR link formatting for better GitHub rendering
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5836-Generalize-AGENTS-md-for-all-contributors-27c6d73d365081e7acf6f37d9f8ceeaf)
by [Unito](https://www.unito.io)
## 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>
## 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)
## Summary
Refactored Vue node browser tests by organizing them into behavioral
categories, better reflecting the nature of browser tests as behind
user-action/behavior specifications.
- **What**: Reorganized Playwright browser tests into logical behavioral
folders (`interactions/`, `nodeStates/`)
- **Structure**: Created subdirectories for canvas interactions, link
interactions, node interactions, and node states
## Review Focus
Test file path changes and associated snapshot relocations ensure all
browser tests continue to run correctly in the new structure.
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5823-refactor-reorganize-Vue-node-browser-tests-into-subfolder-based-on-behaviors-and-states-27b6d73d365081aaa6f9e3a388165258)
by [Unito](https://www.unito.io)
## 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)
## Summary
Added Playwright E2E tests for Vue multiline string widget functionality
to ensure text input and persistence work correctly.
## Changes
- **What**: Created browser tests for multiline string widget in Vue
nodes implementation, covering text input, multiline text input, and
focus change behavior.
## Review Focus
Test coverage for text input persistence across focus changes and
multiline content handling in the CLIP Text Encode widget.
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5819-test-add-browser-tests-for-Vue-node-multiline-string-widgets-27b6d73d365081e2916ae663e2d44899)
by [Unito](https://www.unito.io)
## Summary
After the `pnpm`/`Nx` monorepo migration, `knip` emitted configuration
hints like “Remove or move unused top-level entry…/project…” because it
discovered multiple workspaces but our config still declared global
`entry`/`project` patterns:
```
> knip --cache
Configuration hints (4)
Remove or move unused top-level entry to one of workspaces: [{build,scripts}/**/*.{js,ts}, …]
Remove or move unused top-level project to one of workspaces: [**/*.{js,ts,vue}, …]
Remove from ignoreBinaries: only-allow
Remove from ignoreBinaries: openapi-typescript
```
Rewriting `knip.config.ts` to define those patterns inside the
`workspaces` map for `'.'`, `packages/tailwind-utils`, and
`packages/design-system` matches Knip’s documented workspace schema
(root key `'.'` plus per-package overrides) and aligns each package’s
source with the files it actually exposes.
Follow-up: trim `packages/design-system` entries to the real public
surface, add a wildcard workspace default for future packages, and
capture this expectation somewhere in the repo's docs.
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5809-Use-workspace-in-knip-config-27b6d73d365081b8ace9c82aee78b1db)
by [Unito](https://www.unito.io)
## Summary
Implemented fit-to-view functionality for Vue nodes with bounds
calculation and viewport animation support.
https://github.com/user-attachments/assets/2ec221f1-9194-4564-95f9-ad4da80f190a
## Changes
- **What**: Added Vue nodes support to fit-to-view command with [bounds
calculation](https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect)
and LiteGraph integration
- **Dependencies**: Added dependency on `layoutStore` and
`selectionBounds` utility
## Review Focus
Bounds calculation accuracy for complex node layouts and animation
performance with large node selections. Verify proper fallback to legacy
LiteGraph behavior when Vue nodes disabled.
```mermaid
graph TD
A[Fit to View Command] --> B{Vue Nodes Enabled?}
B -->|Yes| C[Get Selected Nodes]
B -->|No| D[Legacy LiteGraph Method]
C --> E{Nodes Selected?}
E -->|Yes| F[Calculate Selected Bounds]
E -->|No| G[Calculate All Nodes Bounds]
F --> H[Convert to LiteGraph Format]
G --> H
H --> I[Animate to Bounds]
D --> J[Canvas fitViewToSelectionAnimated]
style A fill:#f9f9f9,stroke:#333,color:#333
style I fill:#f9f9f9,stroke:#333,color:#333
style J fill:#f9f9f9,stroke:#333,color:#333
```
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5782-Implement-fit-to-view-for-Vue-nodes-27a6d73d365081cb822cd93f557e77b2)
by [Unito](https://www.unito.io)
---------
Co-authored-by: filtered <176114999+webfiltered@users.noreply.github.com>
This pull request enhances the responsiveness of the `CommandMenubar`
component by introducing a "compact" mode for screens with limited
vertical space. When the window height is less than 700px, the menubar
adapts its submenu positioning and styling to improve usability on
smaller displays. The most important changes are grouped below:
**Responsive Behavior and State Management:**
* Added a reactive `windowHeight` reference and a computed
`isCompactHeight` property to detect when the window height is below
700px, enabling "compact" mode for the menubar. Event listeners for
window resize are now managed using `onMounted` and `onUnmounted`
lifecycle hooks to keep the state updated.
[[1]](diffhunk://#diff-10ee0e60e600a168bdd45e0b9f05a148f5b9ee48f54e6c7dee737ebe7b6192e6R314-R326)
[[2]](diffhunk://#diff-10ee0e60e600a168bdd45e0b9f05a148f5b9ee48f54e6c7dee737ebe7b6192e6L103-R104)
**Dynamic Styling and Class Application:**
* Updated the root element's class bindings to apply the
`comfy-command-menu-compact` class when `isCompactHeight` is true,
enabling conditional styling for compact mode.
**Compact Mode Styling:**
* Introduced new CSS rules for `.comfy-command-menu-compact` to force
submenus to open to the right and align with the top of the menu
container, ensuring better usability on short screens. Adjustments
include submenu positioning, alignment for nested menus, and ensuring
the submenu container uses the full available height.
*
/fix #5289https://github.com/user-attachments/assets/e7908b57-3f07-4fc4-a119-66f2b7e398c5
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5323-Add-compact-menu-style-for-smaller-window-heights-2636d73d3650816cb5aaf4ac76c39739)
by [Unito](https://www.unito.io)
## 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)
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)
## Summary
Consolidates Tailwind configuration and styles into a shared
`@comfyorg/design-system` package for reuse across monorepo apps.
The goal was not to make changes to how the design system works; merely
to separate it cleanly. I _would_ strongly recommend some drastic
sweeping changes, however I believe that should be done after the
migration.
## Changes
- **What**: Migrates CSS files, Tailwind config, and custom icons to
design-system package
- **Dependencies**: Moves `@iconify-json/lucide` and `@iconify/tailwind`
to design-system package
This pull request refactors and simplifies the template workflow card
components and related UI in the codebase. The main changes focus on
removing unused or redundant components, improving visual and
interaction consistency, and enhancing error handling for images. Below
are the most important changes grouped by theme:
**Template Workflow Card Refactor and Cleanup**
* Removed the `TemplateWorkflowCard.vue` component and its associated
test file `TemplateWorkflowCard.spec.ts`, as well as the
`TemplateWorkflowCardSkeleton.vue` and `TemplateWorkflowList.vue`
components, indicating a shift away from the previous card-based
template workflow UI.
[[1]](diffhunk://#diff-49569af0404058e8257f3cc0716b066517ce7397dd58744b02aa0d0c61f2a815L1-L139)
[[2]](diffhunk://#diff-9fa6fc1470371f0b520d4deda4129fb313b1bea69888a376556f4bd824f9d751L1-L263)
[[3]](diffhunk://#diff-bc35b6f77d1cee6e86b05d0da80b7bd40013c7a6a97a89706d3bc52573e1c574L1-L30)
[[4]](diffhunk://#diff-48171f792b22022526fca411d3c3a366d48b675dab77943a20846ae079cbaf3bL1-L68)
* Removed the `TemplateSearchBar.vue` component, suggesting a redesign
or replacement of the search/filter UI for templates.
**UI and Interaction Improvements**
* Improved the `CardBottom.vue` component by making its height
configurable via a `fullHeight` prop, enhancing layout flexibility.
* Updated the `CardContainer.vue` component to add hover effects
(background, border, shadow, and padding) and support a new `none`
aspect ratio for more flexible card layouts.
**Image and Input Enhancements**
* Enhanced the `LazyImage.vue` component to display a default
placeholder image when an image fails to load, improving error handling
and user experience.
* Improved the `SearchBox.vue` component by making the input focusable
when clicking anywhere on the wrapper, and added a template ref for
better accessibility and usability.
[[1]](diffhunk://#diff-08f3b0c51fbfe63171509b9944bf7558228f6c2596a1ef5338e88ab64585791bL2-R5)
[[2]](diffhunk://#diff-08f3b0c51fbfe63171509b9944bf7558228f6c2596a1ef5338e88ab64585791bL16-R17)
[[3]](diffhunk://#diff-08f3b0c51fbfe63171509b9944bf7558228f6c2596a1ef5338e88ab64585791bR33-R39)
**Minor UI Tweaks**
* Adjusted label styling in `SingleSelect.vue` to remove unnecessary
overflow handling, simplifying the visual layout.
---------
Co-authored-by: Benjamin Lu <benceruleanlu@proton.me>
Co-authored-by: Alexander Brown <drjkl@comfy.org>
Co-authored-by: github-actions <github-actions@github.com>
Co-authored-by: Christian Byrne <cbyrne@comfy.org>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: snomiao <snomiao@gmail.com>
Co-authored-by: GitHub Action <action@github.com>
Co-authored-by: filtered <176114999+webfiltered@users.noreply.github.com>
Co-authored-by: Comfy Org PR Bot <snomiao+comfy-pr@gmail.com>
Co-authored-by: Jin Yi <jin12cc@gmail.com>
## Summary
- Migrated all `npx` commands to `pnpx` to align with the pnpm ecosystem
- Updated all occurrences across the codebase for consistency
## Changes
- **Package.json scripts**: Updated test:browser, preinstall, and
collect-i18n scripts
- **GitHub Actions workflows**: Updated all workflow files that use npx
(test-ui, i18n, update-manager-types, etc.)
- **Documentation**: Updated browser_tests/README.md and
docs/extensions/development.md
- **Husky pre-commit hook**: Updated lint-staged and tsx commands
- **MCP configuration**: Updated .mcp.json to use pnpx
## Test Plan
- [ ] CI tests pass
- [ ] Local development commands work with pnpx
- [ ] GitHub Actions workflows execute successfully
🤖 Generated with Claude Code
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5329-chore-Replace-npx-with-pnpx-across-the-codebase-2646d73d36508127bd43d14b8364aeb1)
by [Unito](https://www.unito.io)
This pull request updates event handling in the selection toolbox
components to ensure that mouse wheel events are properly forwarded to
the canvas, improving interaction consistency across the UI.
**Event handling improvements:**
* Changed the wheel event handler in `SelectionToolbox.vue` to use
`canvasInteractions.forwardEventToCanvas` instead of
`canvasInteractions.handleWheel`, ensuring wheel events are consistently
forwarded to the canvas.
* Added the wheel event handler to the `MoreOptions.vue` popover,
forwarding wheel events to the canvas for submenu interactions.
**Code organization updates:**
* Imported `useCanvasInteractions` in `MoreOptions.vue` to access the
new event forwarding method.
* Instantiated `canvasInteractions` in `MoreOptions.vue` for use in
event handling.## Summary
https://github.com/user-attachments/assets/46046086-35e8-4cd1-a11a-365705beb9cd
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5781-Wheel-Selection-Toolbox-and-Popover-27a6d73d3650812c9c4fe8440ff7dd1d)
by [Unito](https://www.unito.io)
## Refactor conflict detection system and move to manager extension
### Description
This PR refactors the conflict detection system, moving it from the
global composables to the manager extension folder for better code
organization. Additionally, it improves test type safety and adds
comprehensive test coverage for utility functions.
### Main Changes
#### 📦 Code Organization
- **Moved conflict detection to manager extension** - Relocated all
conflict detection related composables, stores, and utilities from
global scope to `/workbench/extensions/manager/` for better modularity
(https://github.com/Comfy-Org/ComfyUI_frontend/pull/5722)
- **Moved from** `src/composables/useConflictDetection.ts` **to**
`src/workbench/extensions/manager/composables/useConflictDetection.ts`
- Moved related stores and composables to maintain cohesive module
structure
#### ♻️ Refactoring
- **Extracted utility functions** - Split conflict detection logic into
separate utility modules:
- `conflictUtils.ts` - Conflict consolidation and summary generation
- `systemCompatibility.ts` - OS and accelerator compatibility checking
- `versionUtil.ts` - Version compatibility checking
- **Removed duplicate state management** - Cleaned up redundant state
and unused functions
- **Improved naming conventions** - Renamed functions for better clarity
- **Removed unused system environment code** - Cleaned up deprecated
code
#### 🔧 Test Improvements
- **Fixed TypeScript errors** in all test files - removed all `any` type
usage
- **Added comprehensive test coverage**:
- `conflictUtils.test.ts` - 299 lines of tests for conflict utilities
- `systemCompatibility.test.ts` - 270 lines of tests for compatibility
checking
- `versionUtil.test.ts` - 342 lines of tests for version utilities
- **Updated mock objects** to match actual implementations
- **Aligned with backend changes** - Updated SystemStats structure to
include `pytorch_version`, `embedded_python`,
`required_frontend_version`
#### 🐛 Bug Fixes
- **Fixed OS detection bug** - Resolved issue where 'darwin' was
incorrectly matched as 'Windows' due to containing 'win' substring
- **Fixed import paths** - Updated all import paths after moving to
manager extension
- **Fixed unused exports** - Removed all unused function exports
- **Fixed lint errors** - Resolved all ESLint and Prettier issues
### File Structure Changes
```
Before:
src/
├── composables/
│ └── useConflictDetection.ts (1374 lines)
└── types/
After:
src/
├── utils/
│ ├── conflictUtils.ts (114 lines)
│ ├── systemCompatibility.ts (125 lines)
│ └── versionUtil.ts (enhanced)
└── workbench/extensions/manager/
├── composables/
│ ├── useConflictDetection.ts (758 lines)
│ └── [other composables]
└── stores/
└── conflictDetectionStore.ts
```
### Testing
All tests pass successfully:
- ✅ **155 test files passed**
- ✅ **2209 tests passed**
- ⏩ 19 skipped (intentionally skipped subgraph-related tests)
### Impact
- **Better code organization** - Manager-specific code is now properly
isolated
- **Improved maintainability** - Smaller, focused utility functions are
easier to test and maintain
- **Enhanced type safety** - No more `any` types in tests
- **Comprehensive test coverage** - All utility functions are thoroughly
tested
### Commits in this PR
1. OS detection bug fix and refactor
2. Remove unused system environment code
3. Improve function naming
4. Refactor conflict detection
5. Remove duplicate state and unused functions
6. Fix unused function exports
7. Move manager features to workbench extension folder
8. Fix import paths
9. Rename systemCompatibility file
10. Improve test type safety
11. Apply ESLint and Prettier fixes
## Screenshots (if applicable)
[screen-capture.webm](https://github.com/user-attachments/assets/b4595604-3761-4d98-ae8e-5693cd0c95bd)
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5436-Manager-refactor-conflict-detect-2686d73d36508186ba06f57dae3656e5)
by [Unito](https://www.unito.io)
---------
Co-authored-by: Claude <noreply@anthropic.com>
## Summary
Fixed Vue node output restoration by consolidating state management
through the node output store.
## Changes
- **What**: Refactored node output cleanup and restoration logic in
`ChangeTracker` and `ComfyApp` to use centralized store methods
- **Breaking**: Removed direct manipulation of `app.nodeOutputs` in
favor of store-managed state
## Review Focus
State synchronization between `app.nodeOutputs` and `nodeOutputs.value`
during restore/reset operations, ensuring Vue reactivity is maintained.
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5788-fix-restoring-outputs-in-Vue-nodes-persisting-node-outputs-when-switching-between-workfl-27a6d73d365081b39411fed7479d8ac5)
by [Unito](https://www.unito.io)
## Summary
Split tailwind utils out to a shared package within the monorepo.
## Changes
- Creates `@comfyorg/tailwind-utils` package
- Does not require export, publishing, etc
- Uses `export` to ensure this change does not impact other PRs (many
imports to update)
- If we _want_ to update all imports, there are two commits ready to be
re-applied
- e.g. `git revert 80960c2a82c0d1ac06eee1bb83ac333216b2b376`
## Review Focus
- Is this pattern desirable?
- Should we just include this in a broader design-system split? I kind
of vote yes, but also it's a good small, first step.
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5777-Split-Tailwind-utility-functions-out-to-a-shared-package-2796d73d3650815f976fc73b4fb86ef3)
by [Unito](https://www.unito.io)
## 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)
## Summary
UseNewMenu has been defaulted to Top in the app for over a year;
Playwright’s test default lagged behind. This PR aligns the test default
with reality and keeps legacy specs stable.
## Changes
- tests(e2e): default to 'Top' via fixture; specs that previously relied
on the old implicit default now explicitly set 'Comfy.UseNewMenu' to
'Disabled'.
- docs(browser-tests): remove outdated README note suggesting tests set
'Top' manually.
## Review Focus
- Intentional uses of 'Top' and 'Bottom' remain unchanged.
- Confirm ComfyPage default remains 'Top' (see
browser_tests/fixtures/ComfyPage.ts).
## Screenshots (if applicable)
N/A
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5746-test-e2e-align-test-default-menu-to-Top-make-legacy-specs-explicit-2786d73d365081218d06c1346f3ae18e)
by [Unito](https://www.unito.io)
---------
Co-authored-by: github-actions <github-actions@github.com>
## 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>
## Summary
This PR fixes a flaky test in the load audio widget spec that was
causing intermittent failures in CI.
## Problem
The test was attempting to trigger a file chooser event before the
widget's upload button was fully rendered and ready for interaction,
leading to race conditions.
## Solution
Added an explicit wait for the widget element to be visible before
triggering the file chooser, ensuring the DOM is ready for interaction.
## Changes
- Added `waitFor` to verify widget visibility before file upload
- Ensures proper synchronization between DOM updates and test actions
## Test plan
- [x] Browser tests pass locally
- [x] Typecheck passes
- [ ] CI tests pass
🤖 Generated with [Claude Code](https://claude.ai/code)
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5755-bugfix-Stabilize-flaky-load-audio-widget-test-2786d73d365081cebaefdc6470333c5d)
by [Unito](https://www.unito.io)
---------
Co-authored-by: Claude <noreply@anthropic.com>
## Summary
- Added missing directories and files to tsconfig.json to ensure
complete TypeScript type checking coverage
- Expanded config file patterns to include all .mts configuration files
- Verified all 908 TypeScript files in the project are now properly
covered
## Changes
- Added `scripts/**/*.ts` to cover all TypeScript files in scripts
directory (i18n collection, CI/CD scripts)
- Added `build/**/*.ts` to cover customIconCollection.ts and future
build scripts
- Changed `vite.config.mts` to `*.config.mts` to include all vite config
files (vite.electron.config.mts, vite.types.config.mts)
## Test plan
- [x] Run `pnpm typecheck` to verify no TypeScript errors
- [x] Verified all TypeScript files are covered by tsconfig patterns
- [x] browser_tests/ directory confirmed to have its own extending
tsconfig
🤖 Generated with [Claude Code](https://claude.ai/code)
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5655-chore-tsconfig-ensure-complete-TypeScript-coverage-for-all-project-files-2736d73d36508103acbadc53ca2b2913)
by [Unito](https://www.unito.io)
---------
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Alexander Brown <drjkl@comfy.org>
Co-authored-by: filtered <176114999+webfiltered@users.noreply.github.com>
## Summary
Merges ComfyUI devtools components into the ComfyUI frontend monorepo to
consolidate development tools.
## Changes
- Added devtools components from ComfyUI repository
- Integrated development nodes and utilities
- Consolidated fake model assets for testing
## Related Issues
Fixes#4683
## Testing
- Devtools components are now available within the frontend monorepo
- Development workflow remains consistent
Co-authored-by: Claude <noreply@anthropic.com>
## 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>
## Summary
This reverts PR #5614 which moved VueFire persistence configuration to
initialization.
## Reason for Revert
It breaks Google SSO login with error:
```
useErrorHandling.ts:12 FirebaseError: Firebase: Error (auth/argument-error).
at createErrorInternal (index-c92d61ad.js:506:41)
at _assert (index-c92d61ad.js:512:15)
at _withDefaultResolver (index-c92d61ad.js:9237:5)
at signInWithPopup (index-c92d61ad.js:9457:30)
at executeAuthAction.createCustomer (firebaseAuthStore.ts:263:25)
at executeAuthAction (firebaseAuthStore.ts:223:28)
at Proxy.loginWithGoogle (firebaseAuthStore.ts:262:5)
at Proxy.wrappedAction (pinia.mjs:1405:26)
at useFirebaseAuthActions.ts:104:28
at Object.signInWithGoogle (useErrorHandling.ts:39:22)
```
## Changes
- Reverts commit ea4e57b60 "Move VueFire persistence configuration to
initialization (#5614)"
- Restores previous Firebase auth persistence behavior
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5729-Revert-Move-VueFire-persistence-configuration-to-initialization-5614-2776d73d3650814c9b80d9c67c852874)
by [Unito](https://www.unito.io)
## Summary
Refactored `onUserResolved` function in auth composable to use VueUse
`whenever` utility instead of manual watch implementation and use
`immediate` option instead of invoking manually before creating watcher.
## Changes
- **What**: Replaced manual watch + immediate check pattern with [VueUse
whenever](https://vueuse.org/shared/whenever/) utility in
`useCurrentUser.ts:37`
## Review Focus
Behavioral equivalence verification - `whenever` with `immediate: true`
should maintain identical callback timing and cleanup semantics.
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5718-refactor-Simplify-current-user-resolved-hook-implementation-2766d73d365081008b6de156dd78f940)
by [Unito](https://www.unito.io)
## Summary
Fixed Vue node keybinding target element ID to enable
bypass/pin/collapse hotkeys in both LiteGraph and Vue rendering modes.
Also fixed a bug when starting in litegraph mode => switching to Vue
nodes without reloading => `graph.onTrigger` is set to `undefined` which
interferes with proper setup of node data instrumentation, among other
things.
## Changes
- **What**: Updated keybinding `targetElementId` from `graph-canvas` to
`graph-canvas-container` for node manipulation commands (parent of both
the canvas and transform pane -- vue nodes container).
- **What**: Added conditional `onTrigger` handler restoration in slot
layout sync to prevent Vue node manager conflicts
## Review Focus
Event handler precedence between Vue nodes and LiteGraph systems during
mode switching, ensuring hotkeys work consistently across rendering
modes.
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5715-fix-bypass-hotkey-in-vue-nodes-and-fix-node-data-instrumentation-setup-issue-when-switchi-2756d73d3650815c8ec8d5e4d06232e3)
by [Unito](https://www.unito.io)
## 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)
## 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>
## 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)
## 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>
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)
## Summary
- Replace custom `compareVersions()` with `semver.compare()`
- Replace custom `isSemVer()` with `semver.valid()`
- Remove deprecated version comparison functions from `formatUtil.ts`
- Update all version comparison logic across components and stores
- Fix tests to use semver mocking instead of formatUtil mocking
## Benefits
- **Industry standard**: Uses well-maintained, battle-tested `semver`
package
- **Better reliability**: Handles edge cases more robustly than custom
implementation
- **Consistent behavior**: All version comparisons now use the same
underlying logic
- **Type safety**: Better TypeScript support with proper semver types
Fixes#4787
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5653-refactor-Replace-manual-semantic-version-utilities-functions-with-semver-package-2736d73d365081fb8498ee11cbcc10e2)
by [Unito](https://www.unito.io)
---------
Co-authored-by: DrJKL <DrJKL@users.noreply.github.com>
Co-authored-by: Claude <noreply@anthropic.com>
## Summary
Removed the informational "Use Legacy UI" tag from the ManagerHeader
component while preserving all underlying legacy manager functionality.
## Changes
- **What**: Removed Tag component displaying legacy UI information from
ManagerHeader
- **Breaking**: None - all legacy manager functionality remains intact
- **Dependencies**: None
## Review Focus
Visual cleanup only - the `--enable-manager-legacy-ui` CLI flag and all
related functionality continues to work normally. Only the informational
UI tag has been removed from the header.
## 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>
## 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>
## Summary
Reorganized custom nodes manager functionality from scattered technical
layers into a cohesive domain-focused module following [domain-driven
design](https://en.wikipedia.org/wiki/Domain-driven_design) principles.
## Changes
- **What**: Migrated all manager code from technical layers
(`src/components/`, `src/stores/`, etc.) to unified domain structure at
`src/workbench/extensions/manager/`
- **Breaking**: Import paths changed for all manager-related modules
(40+ files updated)
## Review Focus
Verify all import path updates are correct and no circular dependencies
introduced. Check that [Vue 3 composition
API](https://vuejs.org/guide/reusability/composables.html) patterns
remain consistent across relocated composables.
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5662-refactor-Migrate-manager-code-to-DDD-structure-2736d73d3650812c87faf6ed0fffb196)
by [Unito](https://www.unito.io)
## Summary
- Fixes Sentry issue CLOUD-FRONTEND-STAGING-29 (TypeError: nodes is not
iterable)
- Adds defensive guard to check if nodes is valid array before iteration
- Gracefully handles malformed workflow data by skipping node processing
## Root Cause
The `collectMissingNodesAndModels` function in `src/scripts/app.ts:1135`
was attempting to iterate over `nodes` without checking if it was a
valid iterable, causing crashes when workflow data was malformed or
missing the nodes property.
## Fix
Added null/undefined/array validation before the for-loop:
```typescript
if (\!nodes || \!Array.isArray(nodes)) {
console.warn('Workflow nodes data is missing or invalid, skipping node processing', { nodes, path })
return
}
```
Fixes CLOUD-FRONTEND-STAGING-29
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5660-fix-TypeError-nodes-is-not-iterable-when-loading-graph-2736d73d365081cfb828d27e59a4811c)
by [Unito](https://www.unito.io)
## Summary
- Fixes the Claude automated PR review comparing against wrong commits
- Updates the comprehensive-pr-review.md command to use `$BASE_SHA`
instead of `origin/$BASE_BRANCH`
- Resolves issue where Claude was reviewing unrelated changes from other
PRs
## Problem
As identified in #5651 (comment
https://github.com/Comfy-Org/ComfyUI_frontend/pull/5651#issuecomment-3310416767),
the Claude automated review was incorrectly analyzing changes that
weren't part of the PR being reviewed. The review was mentioning Turkish
language removal, linkRenderer changes, and other modifications that
weren't in the actual PR diff.
## Root Cause Analysis
### The Issue Explained (from Discord discussion)
When Christian Byrne noticed Claude was referencing things from previous
reviews on other PRs, we investigated and found:
1. **The backport branch was created from origin/main BEFORE Turkish
language support was merged**
- Branch state: `main.A`
- Backport changes committed: `main.A.Backport`
2. **Turkish language support was then merged into origin/main**
- Main branch updated to: `main.A.Turkish`
3. **Claude review workflow checked out `main.A.Backport` and ran git
diff against `origin/main`**
- This compared: `main.A.Backport <> main.A.Turkish`
- The diff showed: `+++Backport` changes and `---Turkish` removal
- Because the common parent of both branches was `main.A`
### Why This Happens
When using `origin/$BASE_BRANCH`, git resolves to the latest commit on
that branch. The diff includes:
1. The PR's actual changes (+++Backport)
2. The reverse of all commits merged to main since the PR was created
(---Turkish)
This causes Claude to review changes that appear as "removals" of code
from other merged PRs, leading to confusing comments about unrelated
code.
## Solution
Changed the git diff commands to use `$BASE_SHA` directly, which GitHub
Actions provides as the exact commit SHA that represents the merge base.
This ensures Claude only reviews the actual changes introduced by the
PR.
### Before (incorrect):
```bash
git diff --name-only "origin/$BASE_BRANCH" # Compares against latest main
git diff "origin/$BASE_BRANCH"
git diff --name-status "origin/$BASE_BRANCH"
```
### After (correct):
```bash
git diff --name-only "$BASE_SHA" # Compares against merge base
git diff "$BASE_SHA"
git diff --name-status "$BASE_SHA"
```
## Technical Details
### GitHub Actions Environment Variables
- `BASE_SHA`: The commit SHA of the merge base (where PR branched from
main)
- `BASE_BRANCH`: Not provided by GitHub Actions (this was the bug)
- Using `origin/$BASE_BRANCH` was falling back to comparing against the
latest main commit
### Alternative Approaches Considered
1. **Approach 1**: Rebase/update branch before running Claude review
- Downside: Changes the PR's commits, not always desirable
2. **Approach 2**: Use BASE_SHA to diff against the merge base ✅
- This is what GitHub's PR diff view does
- Shows only the changes introduced by the PR
## Testing
The BASE_SHA environment variable is already correctly set in the
claude-pr-review.yml workflow (line 88), so this change will work
immediately once merged.
## Impact
- Claude reviews will now be accurate and only analyze the actual PR
changes
- No false positives about "removed" code from other PRs
- More reliable automated PR review process
- Developers won't be confused by comments about code they didn't change
## Verification
You can verify this fix by:
1. Creating a PR from an older branch
2. Merging another PR to main
3. Triggering Claude review with the label
4. Claude should only review the PR's changes, not show removals from
the newly merged commits
## Credits
Thanks to @Christian-Byrne for reporting the issue and @snomiao for the
root cause analysis.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-authored-by: Claude <noreply@anthropic.com>
## Summary
- Enable `verbatimModuleSyntax` compiler option in TypeScript
configuration
- Update all type imports to use explicit `import type` syntax
- This change will Improve tree-shaking and bundler compatibility
## Motivation
The `verbatimModuleSyntax` option ensures that type-only imports are
explicitly marked with the `type` keyword. This:
- Makes import/export intentions clearer
- Improves tree-shaking by helping bundlers identify what can be safely
removed
- Ensures better compatibility with modern bundlers
- Follows TypeScript best practices for module syntax
## Changes
- Added `"verbatimModuleSyntax": true` to `tsconfig.json`
- Updated another 48+ files to use explicit `import type` syntax for
type-only imports
- No functional changes, only import/export syntax improvements
## Test Plan
- [x] TypeScript compilation passes
- [x] Build completes successfully
- [x] Tests pass
- [ ] No runtime behavior changes
🤖 Generated with [Claude Code](https://claude.ai/code)
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5533-feat-enable-verbatimModuleSyntax-in-TypeScript-config-26d6d73d36508190b424ef9b379b5130)
by [Unito](https://www.unito.io)
Enables manual backport triggering for scenarios where labels are added
after PR merge.
Adds workflow_dispatch trigger to the backport workflow with support
for:
- Specifying PR number to backport post-merge
- Force rerun option to override duplicate detection
- Proper handling of multi-version backport scenarios
Solves the issue where adding version labels (e.g., 1.27) after a PR is
already merged and backported (e.g., to 1.26) would not trigger
additional backports.
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5651-feat-add-manual-dispatch-to-backport-workflow-2736d73d365081b6ba00c7a43c9ba06b)
by [Unito](https://www.unito.io)
## Summary
- Added complete Turkish language translation for ComfyUI Frontend
- Integrated Turkish locale into the i18n system
- Added Turkish as a selectable language option in settings
## Implementation Details
- Added Turkish translation files provided by @naxci1:
- `src/locales/tr/main.json` - Main UI translations
- `src/locales/tr/commands.json` - Command translations
- `src/locales/tr/nodeDefs.json` - Node definitions translations
- `src/locales/tr/settings.json` - Settings translations
- Updated `src/i18n.ts` to import and register Turkish locale
- Added Turkish option to language selector in
`src/constants/coreSettings.ts`
## Test Plan
- [ ] Verify Turkish translations load correctly
- [ ] Test language switching to/from Turkish
- [ ] Check all UI elements display properly in Turkish
- [ ] Verify node descriptions and tooltips in Turkish
- [ ] Test command palette in Turkish
Fixes#5437🤖 Generated with [Claude Code](https://claude.ai/code)
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5438-feat-Add-Turkish-language-support-2686d73d36508184bbf2dc1e0cd15350)
by [Unito](https://www.unito.io)
Implementing subgraph blueprints (#5139) included changes to saving to
ensure that SaveAs generates a new workflow of the correct type. However
this code failed to utilize the pre-prepared state when performing the
actual save. This produced a couple of problems with both failing to
detach the workflow and failing to apply the correct state
This error is only encountered when using Save As from a non temporary
workflow (one loaded from the workflows sidebar tab).
As this state calculation code is only used in this code path, it has
been moved into the saveAs function of the workflowStore.
Resolves#5592
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5643-Fix-SaveAs-2726d73d3650818faa7af449d1f13c26)
by [Unito](https://www.unito.io)
#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)
## 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>
## Summary
Some users were authenticating successfully but their email addresses
weren't being extracted from the Firebase token. This happened because
we weren't explicitly requesting the email scope during OAuth
authentication.
While Firebase's default configuration includes basic profile info, it
doesn't guarantee email access for all account types - particularly
Google Workspace accounts with restrictive policies or users with
privacy-conscious settings.
[Github
Scopes](https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/scopes-for-oauth-apps)
## Changes
Adding email scope for Google + Github social OAuth.
## Review Focus
N/A
## Screenshots (if applicable)
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5638-Explicitly-add-email-scope-for-social-auth-login-2726d73d3650817ab356fc9c04f8641b)
by [Unito](https://www.unito.io)
---------
Co-authored-by: Alexander Brown <drjkl@comfy.org>
## 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>
## Summary
- Updated frontend to align with backend changes in ComfyUI core PR
#7555
- Changed manager startup argument from `--disable-manager` (opt-out) to
`--enable-manager` (opt-in)
- Manager is now disabled by default unless explicitly enabled
## Changes
- Modified `useManagerState.ts` to check for `--enable-manager` flag
presence
- Inverted logic: manager is disabled when the flag is NOT present
- Updated all related tests to reflect the new opt-in behavior
- Fixed edge case where `systemStats` is null
## Related
- Backend PR: https://github.com/comfyanonymous/ComfyUI/pull/7555
## Test Plan
- [x] All unit tests pass
- [x] Verified manager state logic with different flag combinations
- [x] TypeScript type checking passes
- [x] Linting passes
🤖 Generated with [Claude Code](https://claude.ai/code)
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5635-refactor-Change-manager-flag-from-disable-manager-to-enable-manager-2726d73d36508153a88bd9f152132b2a)
by [Unito](https://www.unito.io)
This pull request improves the lazy loading behavior and caching
strategy for images in the `LazyImage.vue` component. The most
significant changes are focused on optimizing image rendering and
resource management, as well as improving code clarity.
**Lazy loading behavior improvements:**
* Changed the `<img>` element to render only when `cachedSrc` is
available, ensuring that images are not displayed before they are ready.
* Updated watchers in `LazyImage.vue` to use clearer variable names
(`shouldLoadVal` instead of `shouldLoad`) for better readability and
maintainability.
[[1]](diffhunk://#diff-3a1bfa7eb8cb26b04bea73f7b4b4e3c01e9d20a7eba6c3738fb47f96da1a7c95L80-R81)
[[2]](diffhunk://#diff-3a1bfa7eb8cb26b04bea73f7b4b4e3c01e9d20a7eba6c3738fb47f96da1a7c95L96-R96)
**Caching strategy enhancement:**
* Modified the `fetch` call in `mediaCacheService.ts` to use `{ cache:
'force-cache' }`, which leverages the browser's cache more aggressively
when loading media, potentially improving performance and reducing
network requests.
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5626-LazyImage-on-Safari-2716d73d365081eeb1d3c2a96be4d408)
by [Unito](https://www.unito.io)
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>
git commit -m "[auto-fix] Apply ESLint and Prettier fixes"
git commit -m "[automated] Apply ESLint and Prettier fixes"
git push
- name:Final validation
@@ -102,4 +104,4 @@ jobs:
owner: context.repo.owner,
repo: context.repo.repo,
body: '## ⚠️ Linting/Formatting Issues Found\n\nThis PR has linting or formatting issues that need to be fixed.\n\n**Since this PR is from a fork, auto-fix cannot be applied automatically.**\n\n### Option 1: Set up pre-commit hooks (recommended)\nRun this once to automatically format code on every commit:\n```bash\npnpm prepare\n```\n\n### Option 2: Fix manually\nRun these commands and push the changes:\n```bash\npnpm lint:fix\npnpm format\n```\n\nSee [CONTRIBUTING.md](https://github.com/Comfy-Org/ComfyUI_frontend/blob/main/CONTRIBUTING.md#git-pre-commit-hooks) for more details.'
"description":"Electron-specific CSS property that defines draggable regions in custom title bar windows. Setting 'drag' marks a rectangular area as draggable for moving the window; 'no-drag' excludes areas from the draggable region.",
"values":[
{
"name":"drag",
"description":"Marks the element as draggable for moving the Electron window"
},
{
"name":"no-drag",
"description":"Excludes the element from being used to drag the Electron window"
"description":"Use the `@apply` directive to inline any existing utility classes into your own custom CSS. This is useful when you find a common utility pattern in your HTML that you’d like to extract to a new component.",
"description":"DO NOT USE. IF YOU ARE CAUGHT USING @apply YOU WILL FACE SEVERE CONSEQUENCES.",
"description":"Use the `@custom-variant` directive to add a custom variant to your project. Custom variants can be used with utilities like `hover`, `focus`, and responsive breakpoints. Use `@slot` inside the variant to indicate where the utility's styles should be inserted.",
"description":"Use the `@utility` directive to add custom utilities to your project. Custom utilities work with all variants like `hover`, `focus`, and responsive variants. Use `--value()` to create functional utilities that accept arguments.",
- Playwright: place tests in `browser_tests/`; optional tags like `@mobile`, `@2x` are respected by config.
## Commit & Pull Request Guidelines
- Commits: Prefer Conventional Commits (e.g., `feat(ui): add sidebar`), `refactor(litegraph): …`. Use `[skip ci]` for locale-only updates when appropriate.
- PRs: Include clear description, linked issues (`Fixes #123`), and screenshots/GIFs for UI changes. Add/adjust tests and i18n strings when applicable.
- Commits: Use `[skip ci]` for locale-only updates when appropriate.
- PRs: Include clear description, linked issues (`- Fixes #123`), and screenshots/GIFs for UI changes.
- Quality gates: `pnpm lint`, `pnpm typecheck`, and relevant tests must pass. Keep PRs focused and small.
## Security & Configuration Tips
- Secrets: Use `.env` (see `.env_example`); do not commit secrets.
- Backend: Dev server expects ComfyUI backend at `localhost:8188` by default; configure via `.env`.
@@ -18,7 +18,6 @@ This bootstraps the monorepo with dependencies, builds, tests, and dev server ve
-`pnpm build`: Build for production (via nx)
-`pnpm lint`: Linting (via nx)
-`pnpm format`: Prettier formatting
-`pnpm test:component`: Run component tests with browser environment
-`pnpm test:unit`: Run all unit tests
-`pnpm test:browser`: Run E2E tests via Playwright
-`pnpm test:unit -- tests-ui/tests/example.test.ts`: Run single test file
@@ -127,6 +126,5 @@ const value = api.getServerFeature('config_name', defaultValue) // Get config
- NEVER use `--no-verify` flag when committing
- NEVER delete or disable tests to make them pass
- NEVER circumvent quality checks
- NEVER use `dark:`prefix - always use `dark-theme:` for dark mode styles, for example: `dark-theme:text-white dark-theme:bg-black`
- NEVER use `:class="[]"` to merge class names - always use `import { cn } from '@/utils/tailwindUtil'`, for example: `<div :class="cn('bg-red-500', { 'bg-blue-500': condition })" />`
- NEVER use `dark:`or `dark-theme:` tailwind variants. Instead use a semantic value from the `style.css` theme, e.g. `bg-node-component-surface`
- NEVER use `:class="[]"` to merge class names - always use `import { cn } from '@/utils/tailwindUtil'`, for example: `<div :class="cn('text-node-component-header-icon', hasError && 'text-danger')" />`
2. **Iconify Icons** - 200,000+ icons from various libraries: `<i-lucide:settings />`, `<i-mdi:folder />`
2. **Iconify Icons** - 200,000+ icons from various libraries: `<i class="icon-[lucide--settings]" />`, `<i class="icon-[mdi--folder]" />`
3. **Custom Icons** - Your own SVG icons: `<i-comfy:workflow />`
Icons are powered by the unplugin-icons system, which automatically discovers and imports icons as Vue components. Custom icons are stored in `src/assets/icons/custom/` and processed by `build/customIconCollection.ts` with automatic validation.
Icons are powered by the unplugin-icons system, which automatically discovers and imports icons as Vue components. Custom icons are stored in `packages/design-system/src/icons/` and processed by `packages/design-system/src/iconCollection.ts` with automatic validation.
For detailed instructions and code examples, see [src/assets/icons/README.md](src/assets/icons/README.md).
For detailed instructions and code examples, see [packages/design-system/src/icons/README.md](packages/design-system/src/icons/README.md).
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.