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