From 2565f5aececf6b9b108e62720005c5733ea48f6d Mon Sep 17 00:00:00 2001 From: Robert Wojciechowski Date: Tue, 24 Feb 2026 23:09:20 +0000 Subject: [PATCH] feat: adapt panel styling to Nodes 2.0 (Modern Node Design) Detects the Comfy.VueNodes.Enabled setting via addEventListener and toggles a `distributed-panel--nodes2` class on the panel root element. CSS visual properties (backgrounds, borders, border-radius) are migrated from inline JS styles to CSS classes, enabling clean theme overrides for Nodes 2.0 using PrimeVue surface variables (--p-surface-*, --p-text-*). --- web/constants.js | 18 ++++---- web/distributed.css | 106 ++++++++++++++++++++++++++++++++++++++++++++ web/main.js | 32 ++++++++++--- web/ui.js | 12 +++-- 4 files changed, 149 insertions(+), 19 deletions(-) diff --git a/web/constants.js b/web/constants.js index 863aa06..2d3dac3 100644 --- a/web/constants.js +++ b/web/constants.js @@ -134,17 +134,17 @@ export const UI_STYLES = { controlsDiv: "padding: 0 12px 12px 12px; display: flex; gap: 6px;", formGroup: "display: flex; flex-direction: column; gap: 5px;", formLabel: "font-size: 12px; color: #ccc; font-weight: 500;", - formInput: "padding: 6px 10px; background: #2a2a2a; border: 1px solid #444; color: white; font-size: 12px; border-radius: 4px; transition: border-color 0.2s;", + formInput: "padding: 6px 10px; color: white; font-size: 12px; transition: border-color 0.2s;", // Card styles - cardBase: "margin-bottom: 12px; border-radius: 6px; overflow: hidden; display: flex;", - workerCard: "margin-bottom: 12px; border-radius: 6px; overflow: hidden; display: flex; background: #2a2a2a;", - cardBlueprint: "border: 2px dashed #555; cursor: pointer; transition: all 0.2s ease; background: rgba(255, 255, 255, 0.02);", - cardAdd: "border: 1px dashed #444; cursor: pointer; transition: all 0.2s ease; background: transparent;", - + cardBase: "margin-bottom: 12px; overflow: hidden; display: flex;", + workerCard: "margin-bottom: 12px; overflow: hidden; display: flex;", + cardBlueprint: "cursor: pointer; transition: all 0.2s ease;", + cardAdd: "cursor: pointer; transition: all 0.2s ease;", + // Column styles columnBase: "display: flex; align-items: center; justify-content: center;", - checkboxColumn: "flex: 0 0 44px; display: flex; align-items: center; justify-content: center; border-right: 1px solid #3a3a3a; cursor: default; background: rgba(0,0,0,0.1);", + checkboxColumn: "flex: 0 0 44px; display: flex; align-items: center; justify-content: center; cursor: default;", contentColumn: "flex: 1; display: flex; flex-direction: column; transition: background-color 0.2s ease;", iconColumn: "width: 44px; flex-shrink: 0; font-size: 20px; color: #666;", @@ -162,8 +162,8 @@ export const UI_STYLES = { // Existing styles settingsArrow: "font-size: 12px; color: #888; transition: all 0.2s ease; margin-left: auto; padding: 4px;", - infoBox: "background-color: #333; color: #999; padding: 5px 14px; border-radius: 4px; font-size: 11px; text-align: center; flex: 1; font-weight: 500;", - workerSettings: "margin: 0 12px; padding: 0 12px; background: #1e1e1e; border-radius: 4px; border: 1px solid #2a2a2a;" + infoBox: "color: #999; padding: 5px 14px; font-size: 11px; text-align: center; flex: 1; font-weight: 500;", + workerSettings: "margin: 0 12px; padding: 0 12px;" }; export const TIMEOUTS = { diff --git a/web/distributed.css b/web/distributed.css index b36a911..39e19d8 100644 --- a/web/distributed.css +++ b/web/distributed.css @@ -107,6 +107,112 @@ background-color: var(--tunnel-disable) !important; } +/* ---- Themeable card/column/input defaults (Classic) ---- */ + +.dist-card { + background: #2a2a2a; + border-radius: 6px; +} + +.dist-card--blueprint { + border: 2px dashed #555; + background: rgba(255, 255, 255, 0.02); +} + +.dist-card--add { + border: 1px dashed #444; + background: transparent; +} + +.dist-card__left-col { + border-right: 1px solid #3a3a3a; + background: rgba(0, 0, 0, 0.1); +} + +.dist-info-box { + background-color: #333; + border-radius: 4px; +} + +.dist-form-input { + background: #2a2a2a; + border: 1px solid #444; + border-radius: 4px; +} + +.worker-settings { + background: #1e1e1e; + border: 1px solid #2a2a2a; + border-radius: 4px; +} + +/* ---- Nodes 2.0 Theme ---- */ + +.distributed-panel--nodes2 .dist-card { + background: var(--p-surface-800, #1e1e1e); + border: 1px solid var(--p-surface-700, #2c2c2c); + border-radius: 8px; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3); +} + +.distributed-panel--nodes2 .dist-card--blueprint { + border: 2px dashed var(--p-surface-600, #404040); + background: rgba(255, 255, 255, 0.015); + box-shadow: none; +} + +.distributed-panel--nodes2 .dist-card--add { + border: 1px dashed var(--p-surface-600, #404040); + background: transparent; + box-shadow: none; +} + +.distributed-panel--nodes2 .dist-card__left-col { + border-right-color: var(--p-surface-700, #2c2c2c); + background: var(--p-surface-900, #131313); +} + +.distributed-panel--nodes2 .dist-info-box { + background-color: var(--p-surface-700, #2c2c2c); + color: var(--p-text-muted-color, #9e9e9e); + border-radius: 6px; +} + +.distributed-panel--nodes2 .dist-form-input { + background: var(--p-surface-800, #1e1e1e); + border-color: var(--p-surface-600, #404040); + border-radius: 6px; + color: var(--p-text-color, #ffffff); +} + +.distributed-panel--nodes2 .worker-settings { + background: var(--p-surface-900, #131313); + border-color: var(--p-surface-700, #2c2c2c); + border-radius: 6px; +} + +.distributed-panel--nodes2 .entity-card-content--hovered { + background-color: var(--p-surface-700, #2c2c2c) !important; +} + +.distributed-panel--nodes2 .placeholder-card--blueprint { + border-color: var(--p-surface-600, #404040) !important; +} + +.distributed-panel--nodes2 .placeholder-card--blueprint.is-hovered { + border-color: var(--p-surface-500, #555555) !important; +} + +.distributed-panel--nodes2 .placeholder-card--add { + border-color: var(--p-surface-600, #404040) !important; +} + +.distributed-panel--nodes2 .placeholder-card--add.is-hovered { + border-color: var(--p-surface-500, #555555) !important; +} + +/* ---- End Nodes 2.0 Theme ---- */ + .is-hidden { display: none !important; } diff --git a/web/main.js b/web/main.js index 160f28f..fe3e966 100644 --- a/web/main.js +++ b/web/main.js @@ -49,6 +49,8 @@ class DistributedExtension { loadManagedWorkers(this); // Detect master IP after everything is set up this.detectMasterIP(); + // Listen for Nodes 2.0 setting changes (once, for the lifetime of the extension) + this._setupNodes2Listener(); }); } @@ -260,7 +262,8 @@ class DistributedExtension { render: (el) => { this.panelElement = el; this.onPanelOpen(); - return renderSidebarContent(this, el); + renderSidebarContent(this, el); + this._applyNodes2Style(); }, destroy: () => { this.onPanelClose(); @@ -274,25 +277,40 @@ class DistributedExtension { checkAllWorkerStatuses(this); } } - + onPanelClose() { this.log("Panel closed - stopping status polling", "debug"); - + // Cancel any pending status checks if (this.statusCheckAbortController) { this.statusCheckAbortController.abort(); this.statusCheckAbortController = null; } - + // Clear the timeout if (this.statusCheckTimeout) { clearTimeout(this.statusCheckTimeout); this.statusCheckTimeout = null; } - + this.panelElement = null; } + _applyNodes2Style() { + if (!this.panelElement) return; + const enabled = app.ui.settings.getSettingValue("Comfy.VueNodes.Enabled") ?? false; + this.panelElement.classList.toggle('distributed-panel--nodes2', Boolean(enabled)); + } + + _setupNodes2Listener() { + app.ui.settings.addEventListener("Comfy.VueNodes.Enabled.change", (e) => { + const enabled = e.detail?.value ?? false; + if (this.panelElement) { + this.panelElement.classList.toggle('distributed-panel--nodes2', Boolean(enabled)); + } + }); + } + // --- Core Logic & Execution --- setupInterceptor() { @@ -311,12 +329,12 @@ class DistributedExtension { clearInterval(this.logAutoRefreshInterval); this.logAutoRefreshInterval = null; } - + if (this.statusCheckTimeout) { clearTimeout(this.statusCheckTimeout); this.statusCheckTimeout = null; } - + this.log("Cleaned up intervals", "debug"); } diff --git a/web/ui.js b/web/ui.js index 3185d7e..5dcce91 100644 --- a/web/ui.js +++ b/web/ui.js @@ -201,6 +201,7 @@ export class DistributedUI { input.id = id; input.value = value; input.placeholder = placeholder; + input.classList.add('dist-form-input'); input.style.cssText = this.styles.formInput; group.appendChild(labelEl); @@ -211,6 +212,7 @@ export class DistributedUI { createInfoBox(text) { const box = document.createElement("div"); + box.classList.add('dist-info-box'); box.style.cssText = this.styles.infoBox; box.textContent = text; return box; @@ -223,18 +225,21 @@ export class DistributedUI { createCard(type = 'worker', options = {}) { const card = document.createElement("div"); - + card.classList.add('dist-card'); + switch(type) { case 'master': case 'worker': card.style.cssText = this.styles.workerCard; break; case 'blueprint': + card.classList.add('dist-card--blueprint'); card.style.cssText = this.styles.cardBase + this.styles.cardBlueprint; if (options.onClick) card.onclick = options.onClick; if (options.title) card.title = options.title; break; case 'add': + card.classList.add('dist-card--add'); card.style.cssText = this.styles.cardBase + this.styles.cardAdd; if (options.onClick) card.onclick = options.onClick; if (options.title) card.title = options.title; @@ -253,9 +258,10 @@ export class DistributedUI { createCardColumn(type = 'checkbox', options = {}) { const column = document.createElement("div"); - + switch(type) { case 'checkbox': + column.classList.add('dist-card__left-col'); column.style.cssText = this.styles.checkboxColumn; if (options.title) column.title = options.title; break; @@ -562,8 +568,8 @@ export class DistributedUI { const fallbackActive = extension.isMasterFallbackActive(); let message; const badge = document.createElement("div"); + badge.classList.add("dist-info-box", "master-info-badge"); badge.style.cssText = this.styles.infoBox; - badge.classList.add("master-info-badge"); if (fallbackActive) { message = "No workers selected. Master fallback execution active."; badge.textContent = message;