diff --git a/js/comfyui-gui-builder.css b/js/comfyui-gui-builder.css new file mode 100644 index 000000000..4a5245f87 --- /dev/null +++ b/js/comfyui-gui-builder.css @@ -0,0 +1,82 @@ +.cm-ui-overlay { + z-index: 1000; + background: rgb(0 0 0 / 50%); +} + +.cm-ui-dialog { + max-width: calc(100vw - 2rem); + max-height: calc(100vh - 2rem); + border: 1px solid var(--border, var(--border-color)); + border-radius: 12px; + background: var(--background, var(--comfy-menu-bg)); + color: var(--foreground, var(--fg-color)); + box-shadow: var(--shadow-lg, 0 8px 24px rgb(0 0 0 / 30%)); +} + +.cm-ui-header { + flex-shrink: 0; + padding: 1rem; +} + +.cm-ui-content { + padding: 0 1rem 1rem; + overflow: auto; +} + +.cm-ui-muted { + color: var(--muted-foreground, var(--fg-color)); +} + +:where(.cm-ui-button) { + display: inline-flex; + align-items: center; + justify-content: center; + gap: 0.5rem; + padding: 0.5rem 0.75rem; + border: 1px solid var(--border, var(--border-color)); + border-radius: 6px; + background: var(--secondary, var(--comfy-input-bg)); + color: var(--foreground, var(--input-text)); + font: inherit; + line-height: 1.25; + cursor: pointer; +} + +:where(.cm-ui-input) { + padding: 0.5rem; + border: 1px solid var(--border, var(--border-color)); + border-radius: 6px; + background: var(--secondary, var(--comfy-input-bg)); + color: var(--foreground, var(--input-text)); + font: inherit; +} + +.cm-ui-button:not(:disabled):hover { + filter: brightness(115%); +} + +.cm-ui-button:disabled { + opacity: 0.5; + cursor: not-allowed; +} + +.cm-ui-button:focus-visible, +.cm-ui-input:focus-visible { + outline: 2px solid var(--ring, var(--input-text)); + outline-offset: 2px; +} + +.cm-ui-close { + width: 2rem; + height: 2rem; + flex-shrink: 0; + padding: 0; + border: 0; + border-radius: 50%; + background: transparent; + color: inherit; +} + +.cm-ui-close:not(:disabled):hover { + background: var(--accent, var(--comfy-input-bg)); +} diff --git a/js/comfyui-gui-builder.js b/js/comfyui-gui-builder.js index e6de81c6d..29152ba41 100644 --- a/js/comfyui-gui-builder.js +++ b/js/comfyui-gui-builder.js @@ -1,4 +1,7 @@ import { $el } from "../../scripts/ui.js"; +import { loadCss } from "./common.js"; + +loadCss("./comfyui-gui-builder.css"); function normalizeContent(content) { const tmp = document.createElement('div'); @@ -16,7 +19,7 @@ export function createSettingsCombo(label, content) { const settingItem = $el("div.setting-item", {}, [ $el("div.flex.flex-row.items-center.gap-2",[ $el("div.form-label.flex.grow.items-center", [ - $el("span.text-muted", { textContent: label },) + $el("span.cm-ui-muted", { textContent: label },) ]), $el("div.form-input.flex.justify-end", [content] @@ -28,51 +31,27 @@ export function createSettingsCombo(label, content) { } export function buildGuiFrame(dialogId, title, iconClass, content, owner) { - const dialog_mask = $el("div.p-dialog-mask.p-overlay-mask.p-overlay-mask-enter", { + const dialog_mask = $el("div.cm-ui-overlay.fixed.inset-0.flex.items-center.justify-center", { parent: document.body, - style: { - position: "fixed", - height: "100%", - width: "100%", - left: "0px", - top: "0px", - display: "flex", - justifyContent: "center", - alignItems: "center", - pointerEvents: "auto", - zIndex: "1000" - }, onclick: (e) => { if (e.target === dialog_mask) { owner.close(); } } - // data-pc-section="mask" }); - const header_actions = $el("div.p-dialog-header-actions", { - // [TODO] - // data-pc-section="headeractions" - } - ); + const header_actions = $el("div.flex.items-center"); - const close_button = $el("button.p-button.p-component.p-button-icon-only.p-button-secondary.p-button-rounded.p-button-text.p-dialog-close-button", { + $el("button.cm-ui-button.cm-ui-close", { parent: header_actions, type: "button", ariaLabel: "Close", onclick: () => owner.close(), - // "data-pc-name": "pcclosebutton", - // "data-p-disabled": "false", - // "data-p-severity": "secondary", - // "data-pc-group-section": "headericon", - // "data-pc-extend": "button", - // "data-pc-section": "root", - // [FIXME] Not sure how to do most of the SVG using $el - innerHTML: ' ' + innerHTML: '' } ); - const dialog_header = $el("div.p-dialog-header", + const dialog_header = $el("div.cm-ui-header.flex.items-center.justify-between.gap-2", [ $el("div", [ $el("div", @@ -96,8 +75,8 @@ export function buildGuiFrame(dialogId, title, iconClass, content, owner) { ] ); - const contentFrame = $el("div.p-dialog-content", {}, normalizeContent(content)); - const manager_dialog = $el("div.p-dialog.p-component.global-dialog", { + const contentFrame = $el("div.cm-ui-content.min-h-0", {}, normalizeContent(content)); + $el("div.cm-ui-dialog.global-dialog.flex.flex-col", { id: dialogId, parent: dialog_mask, style: { @@ -108,76 +87,35 @@ export function buildGuiFrame(dialogId, title, iconClass, content, owner) { }, role: 'dialog', ariaModal: 'true', - // [TODO] - // ariaLabbelledby: 'cm-title', - // maximized: 'false', - // data-pc-name: 'dialog', - // data-pc-section: 'root', - // data-pd-focustrap: 'true' }, [ dialog_header, contentFrame ] ); - - const hidden_accessible = $el("span.p-hidden-accessible.p-hidden-focusable", { - parent: manager_dialog, - tabindex: "0", - role: "presentation", - ariaHidden: "true", - "data-p-hidden-accessible": "true", - "data-p-hidden-focusable": "true", - "data-pc-section": "firstfocusableelement" - }); - return dialog_mask; } export function buildGuiFrameCustomHeader(dialogId, customHeader, content, owner) { - const dialog_mask = $el("div.p-dialog-mask.p-overlay-mask.p-overlay-mask-enter", { + const dialog_mask = $el("div.cm-ui-overlay.fixed.inset-0.flex.items-center.justify-center", { parent: document.body, - style: { - position: "fixed", - height: "100%", - width: "100%", - left: "0px", - top: "0px", - display: "flex", - justifyContent: "center", - alignItems: "center", - pointerEvents: "auto", - zIndex: "1000" - }, onclick: (e) => { if (e.target === dialog_mask) { owner.close(); } } - // data-pc-section="mask" }); - const header_actions = $el("div.p-dialog-header-actions", { - // [TODO] - // data-pc-section="headeractions" - } - ); + const header_actions = $el("div.flex.items-center"); - const close_button = $el("button.p-button.p-component.p-button-icon-only.p-button-secondary.p-button-rounded.p-button-text.p-dialog-close-button", { + $el("button.cm-ui-button.cm-ui-close", { parent: header_actions, type: "button", ariaLabel: "Close", onclick: () => owner.close(), - // "data-pc-name": "pcclosebutton", - // "data-p-disabled": "false", - // "data-p-severity": "secondary", - // "data-pc-group-section": "headericon", - // "data-pc-extend": "button", - // "data-pc-section": "root", - // [FIXME] Not sure how to do most of the SVG using $el - innerHTML: ' ' + innerHTML: '' } ); const _customHeader = normalizeContent(customHeader); - const dialog_header = $el("div.p-dialog-header", + const dialog_header = $el("div.cm-ui-header.flex.items-center.justify-between.gap-2", [ $el("div", [ $el("div", @@ -191,8 +129,8 @@ export function buildGuiFrameCustomHeader(dialogId, customHeader, content, owner ] ); - const contentFrame = $el("div.p-dialog-content", {}, normalizeContent(content)); - const manager_dialog = $el("div.p-dialog.p-component.global-dialog", { + const contentFrame = $el("div.cm-ui-content.min-h-0", {}, normalizeContent(content)); + $el("div.cm-ui-dialog.global-dialog.flex.flex-col", { id: dialogId, parent: dialog_mask, style: { @@ -203,25 +141,8 @@ export function buildGuiFrameCustomHeader(dialogId, customHeader, content, owner }, role: 'dialog', ariaModal: 'true', - // [TODO] - // ariaLabbelledby: 'cm-title', - // maximized: 'false', - // data-pc-name: 'dialog', - // data-pc-section: 'root', - // data-pd-focustrap: 'true' }, [ dialog_header, contentFrame ] ); - - const hidden_accessible = $el("span.p-hidden-accessible.p-hidden-focusable", { - parent: manager_dialog, - tabindex: "0", - role: "presentation", - ariaHidden: "true", - "data-p-hidden-accessible": "true", - "data-p-hidden-focusable": "true", - "data-pc-section": "firstfocusableelement" - }); - return dialog_mask; -} \ No newline at end of file +} diff --git a/js/comfyui-manager.js b/js/comfyui-manager.js index 4af212a77..138708b65 100644 --- a/js/comfyui-manager.js +++ b/js/comfyui-manager.js @@ -826,7 +826,7 @@ class ManagerMenuDialog extends ComfyDialog { const isElectron = 'electronAPI' in window; update_comfyui_button = - $el("button.p-button.p-component.cm-button", { + $el("button.cm-ui-button.cm-button", { type: "button", textContent: "Update ComfyUI", style: { @@ -837,7 +837,7 @@ class ManagerMenuDialog extends ComfyDialog { }); switch_comfyui_button = - $el("button.p-button.p-component.cm-button", { + $el("button.cm-ui-button.cm-button", { type: "button", textContent: "Switch ComfyUI", style: { @@ -848,7 +848,7 @@ class ManagerMenuDialog extends ComfyDialog { }); restart_stop_button = - $el("button.p-button.p-component.cm-button-red", { + $el("button.cm-ui-button.cm-button-red", { type: "button", textContent: "Restart", onclick: () => restartOrStop() @@ -856,7 +856,7 @@ class ManagerMenuDialog extends ComfyDialog { if(isElectron) { update_all_button = - $el("button.p-button.p-component.cm-button", { + $el("button.cm-ui-button.cm-button", { type: "button", textContent: "Update All Custom Nodes", onclick: @@ -865,7 +865,7 @@ class ManagerMenuDialog extends ComfyDialog { } else { update_all_button = - $el("button.p-button.p-component.cm-button", { + $el("button.cm-ui-button.cm-button", { type: "button", textContent: "Update All", onclick: @@ -875,7 +875,7 @@ class ManagerMenuDialog extends ComfyDialog { const res = [ - $el("button.p-button.p-component.cm-button", { + $el("button.cm-ui-button.cm-button", { type: "button", textContent: "Custom Nodes Manager", onclick: @@ -887,7 +887,7 @@ class ManagerMenuDialog extends ComfyDialog { } }), - $el("button.p-button.p-component.cm-button", { + $el("button.cm-ui-button.cm-button", { type: "button", textContent: "Install Missing Custom Nodes", onclick: @@ -899,7 +899,7 @@ class ManagerMenuDialog extends ComfyDialog { } }), - $el("button.p-button.p-component.cm-button", { + $el("button.cm-ui-button.cm-button", { type: "button", textContent: "Custom Nodes In Workflow", onclick: @@ -910,7 +910,7 @@ class ManagerMenuDialog extends ComfyDialog { CustomNodesManager.instance.show(CustomNodesManager.ShowMode.IN_WORKFLOW); } }), - $el("button.cm-button", { + $el("button.cm-ui-button.cm-button", { type: "button", textContent: "Node Usage Analyzer", onclick: @@ -923,7 +923,7 @@ class ManagerMenuDialog extends ComfyDialog { }), $el("div", {}, []), - $el("button.p-button.p-component.cm-button", { + $el("button.cm-ui-button.cm-button", { type: "button", textContent: "Model Manager", onclick: @@ -935,7 +935,7 @@ class ManagerMenuDialog extends ComfyDialog { } }), - $el("button.p-button.p-component.cm-button", { + $el("button.cm-ui-button.cm-button", { type: "button", textContent: "Install via Git URL", onclick: async () => { @@ -969,7 +969,7 @@ class ManagerMenuDialog extends ComfyDialog { this.datasrc_combo = document.createElement("select"); this.datasrc_combo.setAttribute("title", "Configure where to retrieve node/model information. If set to 'local,' the channel is ignored, and if set to 'channel (remote),' it fetches the latest information each time the list is opened."); - this.datasrc_combo.className = "cm-menu-combo p-select p-component p-inputwrapper p-inputwrapper-filled "; + this.datasrc_combo.className = "cm-menu-combo cm-ui-input "; this.datasrc_combo.appendChild($el('option', { value: 'cache', text: 'Channel (1day cache)' }, [])); this.datasrc_combo.appendChild($el('option', { value: 'local', text: 'Local' }, [])); this.datasrc_combo.appendChild($el('option', { value: 'remote', text: 'Channel (remote)' }, [])); @@ -987,7 +987,7 @@ class ManagerMenuDialog extends ComfyDialog { // preview method let preview_combo = document.createElement("select"); preview_combo.setAttribute("title", "Configure how latent variables will be decoded during preview in the sampling process."); - preview_combo.className = "cm-menu-combo p-select p-component p-inputwrapper p-inputwrapper-filled"; + preview_combo.className = "cm-menu-combo cm-ui-input"; // Loading state to prevent flash of enabled state preview_combo.appendChild($el('option', { value: '', text: 'Loading...', disabled: true }, [])); @@ -1085,7 +1085,7 @@ class ManagerMenuDialog extends ComfyDialog { // channel let channel_combo = document.createElement("select"); channel_combo.setAttribute("title", "Configure the channel for retrieving data from the Custom Node list (including missing nodes) or the Model list."); - channel_combo.className = "cm-menu-combo p-select p-component p-inputwrapper p-inputwrapper-filled"; + channel_combo.className = "cm-menu-combo cm-ui-input"; api.fetchApi('/manager/channel_url_list') .then(response => response.json()) .then(async data => { @@ -1115,7 +1115,7 @@ class ManagerMenuDialog extends ComfyDialog { // share let share_combo = document.createElement("select"); share_combo.setAttribute("title", "Hide the share button in the main menu or set the default action upon clicking it. Additionally, configure the default share site when sharing via the context menu's share button."); - share_combo.className = "cm-menu-combo p-select p-component p-inputwrapper p-inputwrapper-filled"; + share_combo.className = "cm-menu-combo cm-ui-input"; const share_options = [ ['none', 'None'], ['openart', 'OpenArt AI'], @@ -1152,7 +1152,7 @@ class ManagerMenuDialog extends ComfyDialog { let component_policy_combo = document.createElement("select"); component_policy_combo.setAttribute("title", "When loading the workflow, configure which version of the component to use."); - component_policy_combo.className = "cm-menu-combo p-select p-component p-inputwrapper p-inputwrapper-filled"; + component_policy_combo.className = "cm-menu-combo cm-ui-input"; component_policy_combo.appendChild($el('option', { value: 'workflow', text: 'Use workflow version' }, [])); component_policy_combo.appendChild($el('option', { value: 'higher', text: 'Use higher version' }, [])); component_policy_combo.appendChild($el('option', { value: 'mine', text: 'Use my version' }, [])); @@ -1173,7 +1173,7 @@ class ManagerMenuDialog extends ComfyDialog { update_policy_combo = document.createElement("select"); update_policy_combo.setAttribute("title", "Sets the policy to be applied when performing an update."); - update_policy_combo.className = "cm-menu-combo p-select p-component p-inputwrapper p-inputwrapper-filled"; + update_policy_combo.className = "cm-menu-combo cm-ui-input"; update_policy_combo.appendChild($el('option', { value: 'stable-comfyui', text: 'ComfyUI Stable Version' }, [])); update_policy_combo.appendChild($el('option', { value: 'nightly-comfyui', text: 'ComfyUI Nightly Version' }, [])); api.fetchApi('/manager/policy/update') @@ -1201,7 +1201,7 @@ class ManagerMenuDialog extends ComfyDialog { //[TODO] replace mt-2 with wrapper div with flex column gap $el("filedset.cm-experimental.mt-auto", {}, [ $el("legend.cm-experimental-legend", {}, ["EXPERIMENTAL"]), - $el("button.p-button.p-component.cm-button.cm-experimental-button", { + $el("button.cm-ui-button.cm-button.cm-experimental-button", { type: "button", textContent: "Snapshot Manager", onclick: @@ -1211,7 +1211,7 @@ class ManagerMenuDialog extends ComfyDialog { SnapshotManager.instance.show(); } }), - $el("button.p-button.p-component.cm-button.cm-experimental-button.mt-2", { + $el("button.cm-ui-button.cm-button.cm-experimental-button.mt-2", { type: "button", textContent: "Install PIP packages", onclick: @@ -1229,7 +1229,7 @@ class ManagerMenuDialog extends ComfyDialog { createControlsRight() { const elts = [ - $el("button.p-button.p-component.cm-button", { + $el("button.cm-ui-button.cm-button", { id: 'cm-manual-button', type: "button", textContent: "Community Manual", @@ -1280,7 +1280,7 @@ class ManagerMenuDialog extends ComfyDialog { }) ]), - $el("button.p-button.p-component.cm-button", { + $el("button.cm-ui-button.cm-button", { id: 'workflowgallery-button', type: "button", style: { @@ -1323,7 +1323,7 @@ class ManagerMenuDialog extends ComfyDialog { }) ]), - $el("button.p-button.p-component.cm-button", { + $el("button.cm-ui-button.cm-button", { id: 'cm-nodeinfo-button', type: "button", textContent: "Nodes Info", diff --git a/js/custom-nodes-manager.css b/js/custom-nodes-manager.css index 4ea82580c..423e8a072 100644 --- a/js/custom-nodes-manager.css +++ b/js/custom-nodes-manager.css @@ -103,7 +103,7 @@ line-height: 28px; cursor: pointer; - padding: 0.5em 0.5em; + padding: 0 0.5em; border: 1px solid var(--border-color); border-radius: 6px; background: var(--comfy-input-bg); @@ -726,4 +726,4 @@ .cn-manager-light .cn-btn-install { background-color: #333; -} \ No newline at end of file +} diff --git a/js/custom-nodes-manager.js b/js/custom-nodes-manager.js index dff9a048f..a4eeccbc6 100644 --- a/js/custom-nodes-manager.js +++ b/js/custom-nodes-manager.js @@ -24,13 +24,13 @@ const pageHtml = `
`; @@ -85,7 +85,7 @@ export class CustomNodesManager { // $el("select.cn-manager-filter") // ]), createSettingsCombo("Filter", $el("select.cn-manager-filter")), - $el("input.cn-manager-keywords.p-inputtext.p-component", { type: "search", placeholder: "Search" }), + $el("input.cn-manager-keywords.cm-ui-input", { type: "search", placeholder: "Search" }), $el("div.cn-manager-status"), $el("div.cn-flex-auto"), $el("div.cn-manager-channel") @@ -384,7 +384,7 @@ export class CustomNodesManager { return list.map(id => { const bt = buttons[id]; - return ``; + return ``; }).join(""); } diff --git a/js/model-manager.css b/js/model-manager.css index 6c9ab04ac..30d6ec1a1 100644 --- a/js/model-manager.css +++ b/js/model-manager.css @@ -71,7 +71,7 @@ line-height: 28px; cursor: pointer; - padding: 0.5em 0.5em; + padding: 0 0.5em; border: 1px solid var(--border-color); border-radius: 6px; background: var(--comfy-input-bg); @@ -234,4 +234,4 @@ .cmm-manager-light .cmm-btn-install { background-color: #333; -} \ No newline at end of file +} diff --git a/js/model-manager.js b/js/model-manager.js index b8c3f2d85..747151125 100644 --- a/js/model-manager.js +++ b/js/model-manager.js @@ -31,8 +31,8 @@ const pageHtml = `
@@ -61,7 +61,7 @@ export class ModelManager { createSettingsCombo("Filter", $el("select.cmm-manager-filter")), createSettingsCombo("Type", $el("select.cmm-manager-type")), createSettingsCombo("Base", $el("select.cmm-manager-base")), - $el("input.cmm-manager-keywords.p-inputtext.p-component", { type: "search", placeholder: "Search" }), + $el("input.cmm-manager-keywords.cm-ui-input", { type: "search", placeholder: "Search" }), $el("div.cmm-manager-status"), $el("div.cmm-flex-auto") ]); @@ -347,7 +347,7 @@ export class ModelManager { if (installed === "True") { return `
${icons.passed}
`; } - return ``; + return ``; } }, { id: 'url', @@ -425,7 +425,7 @@ export class ModelManager { } this.selectedModels = selectedList; - this.showSelection(`Selected ${selectedList.length} models `); + this.showSelection(`Selected ${selectedList.length} models `); } focusInstall(item) { diff --git a/js/snapshot.js b/js/snapshot.js index 89a893bd6..51032bb21 100644 --- a/js/snapshot.js +++ b/js/snapshot.js @@ -29,7 +29,7 @@ async function restore_snapshot(target) { } finally { await SnapshotManager.instance.invalidateControl(); - SnapshotManager.instance.updateMessage("
To apply the snapshot, please ComfyUI. And refresh browser.", 'cm-reboot-button2'); + SnapshotManager.instance.updateMessage("
To apply the snapshot, please ComfyUI. And refresh browser.", 'cm-reboot-button2'); } } } @@ -122,7 +122,7 @@ export class SnapshotManager extends ComfyDialog { createControls() { return [ - $el("button.p-button.p-component", { + $el("button.cm-ui-button", { type: "button", textContent: "Close", onclick: () => { this.close(); } @@ -220,7 +220,7 @@ export class SnapshotManager extends ComfyDialog { data_button.className = "data-btns"; var restoreBtn = document.createElement('button'); - restoreBtn.className = "snapshot-restore-btn p-button p-component"; + restoreBtn.className = "snapshot-restore-btn cm-ui-button"; restoreBtn.innerHTML = 'Restore'; restoreBtn.style.width = "100px"; @@ -229,7 +229,7 @@ export class SnapshotManager extends ComfyDialog { }); var removeBtn = document.createElement('button'); - removeBtn.className = "snapshot-remove-btn p-button p-component"; + removeBtn.className = "snapshot-remove-btn cm-ui-button"; removeBtn.innerHTML = 'Remove'; removeBtn.style.width = "100px"; @@ -279,7 +279,7 @@ export class SnapshotManager extends ComfyDialog { async createBottomControls() { var save_button = document.createElement("button"); - save_button.className = "p-button p-component"; + save_button.className = "cm-ui-button"; save_button.innerHTML = "Save snapshot"; save_button.onclick = () => { save_current_snapshot(); } save_button.style.horizontalAlign = "right"; diff --git a/tests/test_message_sink_provenance.py b/tests/test_message_sink_provenance.py index 8a662341a..5862dda01 100644 --- a/tests/test_message_sink_provenance.py +++ b/tests/test_message_sink_provenance.py @@ -349,7 +349,7 @@ class HtmlByDesignSinkTest(unittest.TestCase): '"");', '"");', '`Selected ${selectedList.length} models `);', + 'class="cmm-btn-install cm-ui-button" mode="install">Install`);', ], "node-usage-analyzer.js": [ '"");',