Loads of styling

This commit is contained in:
space-nuko
2023-05-12 15:52:10 -05:00
parent f64db2035a
commit 4f241c17ab
13 changed files with 349 additions and 173 deletions

View File

@@ -63,6 +63,7 @@
"img-comparison-slider": "^8.0.0",
"pollen-css": "^4.6.2",
"radix-icons-svelte": "^1.2.1",
"svelte-feather-icons": "^4.0.0",
"svelte-preprocess": "^5.0.3",
"svelte-select": "^5.5.3",
"svelte-splitpanes": "^0.7.13",

9
pnpm-lock.yaml generated
View File

@@ -88,6 +88,9 @@ importers:
radix-icons-svelte:
specifier: ^1.2.1
version: 1.2.1
svelte-feather-icons:
specifier: ^4.0.0
version: 4.0.0
svelte-preprocess:
specifier: ^5.0.3
version: 5.0.3(sass@1.61.0)(svelte@3.58.0)(typescript@5.0.3)
@@ -6097,6 +6100,12 @@ packages:
svelte: 3.58.0
dev: true
/svelte-feather-icons@4.0.0:
resolution: {integrity: sha512-4ieUsjp+VYa1r6y80jDt9zRiRUZyJNbESpRdHdJJhiBubyuXX96A7f1UZSK4olxzP6Qsg5ZAuyZlnmvD+/swAA==}
dependencies:
svelte: 3.58.0
dev: false
/svelte-floating-ui@1.2.8:
resolution: {integrity: sha512-8Ifi5CD2Ui7FX7NjJRmutFtXjrB8T/FMNoS2H8P81t5LHK4I9G4NIs007rLWG/nRl7y+zJUXa3tWuTjYXw/O5A==}
dependencies:

View File

@@ -1,6 +1,10 @@
import { clamp, negmod } from "./utils";
export class ImageViewer {
root: HTMLDivElement;
lightboxModal: HTMLDivElement;
currentImages: string[] = []
selectedIndex: number = -1;
currentGallery: HTMLDivElement | null = null;
private static _instance: ImageViewer;
@@ -22,6 +26,8 @@ export class ImageViewer {
// A full size 'lightbox' preview modal shown when left clicking on gallery previews
closeModal() {
this.lightboxModal.style.display = "none";
this.currentImages = []
this.selectedIndex = -1;
this.currentGallery = null;
}
@@ -36,30 +42,24 @@ export class ImageViewer {
return visibleGalleryButtons;
}
static selected_gallery_button(gallery: HTMLDivElement): HTMLButtonElement | null {
static selected_gallery_button(gallery: HTMLDivElement): [HTMLButtonElement | null, number] {
var allCurrentButtons = gallery.querySelectorAll('.preview > .thumbnails > .thumbnail-item.thumbnail-small.selected');
var visibleCurrentButton = null;
allCurrentButtons.forEach((elem) => {
let index = -1;
allCurrentButtons.forEach((elem, i) => {
if (elem.parentElement.offsetParent) {
visibleCurrentButton = elem;
index = i;
}
})
return visibleCurrentButton;
return [visibleCurrentButton, index];
}
showModal(event: Event) {
const source = (event.target || event.srcElement) as HTMLImageElement;
const galleryElem = source.closest<HTMLDivElement>("div.block")
console.debug("[ImageViewer] showModal", event, source, galleryElem);
if (!galleryElem || ImageViewer.all_gallery_buttons(galleryElem).length === 0) {
console.error("No buttons found on gallery element!", galleryElem)
return;
}
showModal(imageUrls: string[], index: number, galleryElem?: HTMLDivElement) {
this.currentImages = imageUrls
this.selectedIndex = index
this.currentGallery = galleryElem;
this.modalImage.src = source.src
if (this.modalImage.style.display === 'none') {
this.lightboxModal.style.setProperty('background-image', 'url(' + source.src + ')');
}
this.setModalImageSrc(imageUrls[index])
this.lightboxModal.style.display = "flex";
setTimeout(() => {
this.modalImage.focus()
@@ -68,52 +68,52 @@ export class ImageViewer {
event.stopPropagation()
}
static negmod(n: number, m: number) {
return ((n % m) + m) % m;
static get_gallery_urls(galleryElem: HTMLDivElement): string[] {
return ImageViewer.all_gallery_buttons(galleryElem)
.map(b => (b.children[0] as HTMLImageElement).src)
}
updateOnBackgroundChange() {
refreshImages() {
if (this.currentGallery) {
this.currentImages = ImageViewer.get_gallery_urls(this.currentGallery)
let [_currentButton, index] = ImageViewer.selected_gallery_button(this.currentGallery);
this.selectedIndex = index;
}
const selectedImageUrl = this.currentImages[this.selectedIndex];
this.setModalImageSrc(selectedImageUrl)
}
private setModalImageSrc(src: string, isTiling: boolean = false) {
const modalImage = this.modalImage
if (modalImage && modalImage.offsetParent && this.currentGallery) {
let currentButton = ImageViewer.selected_gallery_button(this.currentGallery);
if (currentButton?.children?.length > 0 && modalImage.src != currentButton.children[0].src) {
modalImage.src = currentButton.children[0].src;
if (modalImage.style.display === 'none') {
this.lightboxModal.style.setProperty('background-image', `url(${modalImage.src})`)
}
}
const modal = this.lightboxModal
modalImage.src = src;
if (isTiling) {
modalImage.style.display = 'none';
modal.style.setProperty('background-image', `url(${modalImage.src})`)
} else {
modalImage.style.display = 'block';
modal.style.setProperty('background-image', 'none')
}
}
modalImageSwitch(offset: number) {
if (!this.currentGallery)
return
this.selectedIndex = negmod(this.selectedIndex + offset, this.currentImages.length - 1);
const selectedImageUrl = this.currentImages[this.selectedIndex];
this.setModalImageSrc(selectedImageUrl)
if (this.currentGallery) {
var galleryButtons = ImageViewer.all_gallery_buttons(this.currentGallery);
var [_currentButton, index] = ImageViewer.selected_gallery_button(this.currentGallery);
if (galleryButtons.length > 1) {
var currentButton = ImageViewer.selected_gallery_button(this.currentGallery);
var result = -1
galleryButtons.forEach((v, i) => {
if (v == currentButton) {
result = i
}
})
if (result != -1) {
const nextButton = galleryButtons[ImageViewer.negmod((result + offset), galleryButtons.length)]
if (index != -1) {
const nextButton = galleryButtons[negmod((index + offset), galleryButtons.length)]
nextButton.click()
const modalImage = this.modalImage;
const modal = this.lightboxModal
modalImage.src = nextButton.children[0].src;
if (modalImage.style.display === 'none') {
modal.style.setProperty('background-image', `url(${modalImage.src})`)
}
setTimeout(() => { modal.focus() }, 10)
}
}
setTimeout(() => { this.lightboxModal.focus() }, 10)
}
modalNextImage(event) {
@@ -140,7 +140,7 @@ export class ImageViewer {
}
}
setupImageForLightbox(e: HTMLImageElement) {
setupGalleryImageForLightbox(e: HTMLImageElement) {
if (e.dataset.modded === "true")
return;
@@ -161,7 +161,21 @@ export class ImageViewer {
const initiallyZoomed = true
this.modalZoomSet(this.modalImage, initiallyZoomed)
evt.preventDefault()
this.showModal(evt)
const source = evt.target as HTMLImageElement;
const galleryElem = source.closest<HTMLDivElement>("div.block")
console.debug("[ImageViewer] showModal", event, source, galleryElem);
if (!galleryElem || ImageViewer.all_gallery_buttons(galleryElem).length === 0) {
console.error("No buttons found on gallery element!", galleryElem)
return;
}
let urls = ImageViewer.get_gallery_urls(galleryElem)
const [_currentButton, index] = ImageViewer.selected_gallery_button(galleryElem)
this.showModal(urls, index, galleryElem)
evt.stopPropagation();
}, true);
}
@@ -181,17 +195,8 @@ export class ImageViewer {
}
modalTileImageToggle(event: Event) {
const modalImage = this.modalImage
const modal = this.lightboxModal
const isTiling = modalImage.style.display === 'none';
if (isTiling) {
modalImage.style.display = 'block';
modal.style.setProperty('background-image', 'none')
} else {
modalImage.style.display = 'none';
modal.style.setProperty('background-image', `url(${modalImage.src})`)
}
const isTiling = this.modalImage.style.display === 'none';
this.setModalImageSrc(this.modalImage.src, isTiling)
event.stopPropagation()
}
}

View File

@@ -298,7 +298,7 @@ export default class ComfyAPI {
return Promise.reject(error)
}
return fetch("/" + type, {
return fetch(this.getBackendUrl() + "/" + type, {
method: "POST",
headers: {
"Content-Type": "application/json",
@@ -328,6 +328,6 @@ export default class ComfyAPI {
* Interrupts the execution of the running prompt
*/
async interrupt(): Promise<Response> {
return fetch("/interrupt", { method: "POST" });
return fetch(this.getBackendUrl() + "/interrupt", { method: "POST" });
}
}

View File

@@ -452,8 +452,6 @@ export default class ComfyApp {
this.lGraph.start();
this.lGraph.eventBus.on("afterExecute", () => this.lCanvas.draw(true))
uiState.update(s => { s.uiUnlocked = this.lGraph._nodes.length === 0; return s; })
}
async initDefaultGraph() {
@@ -468,6 +466,7 @@ export default class ComfyApp {
state = structuredClone(blankGraph)
}
await this.deserialize(state)
uiState.update(s => { s.uiUnlocked = true; return s; })
}
/**

View File

@@ -2,13 +2,19 @@
import queueState, { type CompletedQueueEntry, type QueueEntry, type QueueEntryStatus } from "$lib/stores/queueState";
import ProgressBar from "./ProgressBar.svelte";
import Spinner from "./Spinner.svelte";
import { ListIcon as List } from "svelte-feather-icons";
import { convertComfyOutputToComfyURL, convertFilenameToComfyURL, getNodeInfo } from "$lib/utils"
import type { Writable } from "svelte/store";
import type { QueueItemType } from "$lib/api";
import { ImageViewer } from "$lib/ImageViewer";
import { Button } from "@gradio/button";
import type ComfyApp from "./ComfyApp";
import { tick } from "svelte";
let queuePending: Writable<QueueEntry[]> | null = null;
let queueRunning: Writable<QueueEntry[]> | null = null;
let queueCompleted: Writable<CompletedQueueEntry[]> | null = null;
let queueList: HTMLDivElement | null = null;
type QueueUIEntry = {
message: string,
@@ -28,7 +34,6 @@
let mode: QueueItemType = "queue";
function switchMode(newMode: QueueItemType) {
console.warn("SwitchMode", newMode)
const changed = mode !== newMode
mode = newMode
if (changed)
@@ -66,6 +71,9 @@
message = `Prompt: ${entry.extraData.subgraphs.join(', ')}`
let submessage = `Nodes: ${Object.keys(entry.prompt).length}`
if (Object.keys(entry.outputs).length > 0) {
submessage = `Images: ${Object.keys(entry.outputs).length}`
}
return {
message,
@@ -80,19 +88,47 @@
const result = convertEntry(entry.entry);
result.status = entry.status;
result.error = entry.error;
if (result.status === "all_cached")
result.submessage = "(Execution was cached)"
return result;
}
function updateFromQueue() {
_entries = $queuePending.map(convertEntry);
async function updateFromQueue() {
_entries = $queuePending.map(convertEntry).reverse(); // newest entries appear at the top
if (queueList) {
await tick(); // Wait for list size to be recalculated
queueList.scroll({ top: queueList.scrollHeight })
}
console.warn("[ComfyQueue] BUILDQUEUE", _entries, $queuePending)
}
function updateFromHistory() {
async function updateFromHistory() {
_entries = $queueCompleted.map(convertCompletedEntry);
if (queueList) {
await tick(); // Wait for list size to be recalculated
queueList.scroll({ top: queueList.scrollHeight })
}
console.warn("[ComfyQueue] BUILDHISTORY", _entries, $queueCompleted)
}
function showLightbox(entry: QueueUIEntry, e: Event) {
e.preventDefault()
if (!entry.images)
return
ImageViewer.instance.showModal(entry.images, 0)
}
async function interrupt() {
const app = (window as any).app as ComfyApp;
if (!app || !app.api)
return;
await app.api.interrupt();
}
let queued = false
$: queued = Boolean($queueState.runningNodeID || $queueState.progress);
@@ -101,11 +137,14 @@
</script>
<div class="queue">
<div class="queue-entries">
<div class="queue-entries" bind:this={queueList}>
{#if _entries.length > 0}
{#each _entries as entry}
<div class="queue-entry {entry.status}">
{#if entry.images.length > 0}
<div class="queue-entry-images" on:click={(e) => showLightbox(entry, e)}>
<img class="queue-entry-image" src={entry.images[0]} alt="thumbnail" />
</div>
{:else}
<!-- <div class="queue-entry-image-placeholder" /> -->
{/if}
@@ -126,14 +165,26 @@
</div>
</div>
{/each}
{:else}
<div class="queue-empty">
<div class="queue-empty-container">
<div class="queue-empty-icon">
<List size="120rem" />
</div>
<div class="queue-empty-message">
(No entries)
</div>
</div>
</div>
{/if}
</div>
<div class="mode-buttons">
<div class="mode-button"
<div class="mode-button secondary"
on:click={() => switchMode("queue")}
class:mode-selected={mode === "queue"}>
Queue
</div>
<div class="mode-button"
<div class="mode-button secondary"
on:click={() => switchMode("history")}
class:mode-selected={mode === "history"}>
History
@@ -159,6 +210,11 @@
<div>
<ProgressBar value={$queueState.progress?.value} max={$queueState.progress?.max} />
</div>
<div class="queue-action-buttons">
<Button variant="secondary" on:click={interrupt} style={{ full_width: true }}>
Interrupt
</Button>
</div>
{/if}
</div>
</div>
@@ -177,13 +233,37 @@
overflow-y: scroll;
height: $queue-height;
max-height: $queue-height;
> .queue-empty {
display: flex;
color: var(--comfy-accent-soft);
flex-direction: row;
margin: auto;
height: 100%;
> .queue-empty-container {
margin: auto;
display: flex;
flex-direction: column;
> .queue-empty-icon {
margin: auto;
}
> .queue-empty-message {
margin: auto;
font-size: 32px;
font-weight: bolder;
}
}
}
}
.queue-entry {
padding: 1.0rem;
display: flex;
flex-direction: row;
border-bottom: 1px solid var(--panel-border-color);
border-bottom: 1px solid var(--block-border-color);
border-top: 1px solid var(--table-border-color);
background: var(--panel-background-fill);
&.success {
@@ -193,7 +273,9 @@
background: red;
}
&.all_cached {
background: grey;
filter: brightness(80%);
background: var(--neutral-600);
color: var(--neutral-300);
}
&.running {
/* background: lightblue; */
@@ -203,8 +285,17 @@
}
}
.queue-entry-image {
width: var(--size-20);
.queue-entry-images {
height: 100%;
aspect-ratio: 1/1;
margin: auto;
> .queue-entry-image {
filter: none;
&:hover {
filter: brightness(120%) contrast(120%);
}
}
}
.queue-entry-image-placeholder {
@@ -240,28 +331,45 @@
font-size: 10px;
position:absolute;
right: 0px;
bottom:0px;
bottom: 0px;
padding: 0.0rem 0.4rem;
color: var(--body-text-color);
}
.mode-buttons {
height: calc($mode-buttons-height);
display: flex;
flex-direction: row;
text-align: center;
justify-content: center;
height: 100%;
> .mode-button {
width: 100%;
}
}
.mode-button {
height: calc($mode-buttons-height);
padding: 0.2rem;
width: 100%;
height: 100%;
border: 1px solid var(--panel-border-color);
font-weight: bold;
background: var(--button-secondary-background-fill);
text-align: center;
margin: auto;
&.primary {
background: var(--button-primary-background-fill);
&:hover {
background: var(--button-primary-background-fill-hover);
}
}
&.secondary {
background: var(--button-secondary-background-fill);
&:hover {
background: var(--button-secondary-background-fill-hover);
}
}
&:hover {
filter: brightness(120%);
}
&:active {
@@ -271,18 +379,17 @@
filter: brightness(150%)
}
}
}
.bottom {
width: 100%;
height: calc($pending-height);
position: absolute;
border: 2px solid var(--panel-border-color);
.node-name {
background-color: var(--comfy-node-name-background);
color: var(--comfy-node-name-foreground);
padding: 0.2em;
margin: 5px;
display: flex;
justify-content: center;
align-items: center;
@@ -302,7 +409,16 @@
}
&.queued {
height: calc($pending-height - $bottom-bar-height);
height: calc($pending-height - $mode-buttons-height - $bottom-bar-height - 16px);
}
}
.queue-action-buttons {
margin: 5px;
height: 20px;
:global(button) {
border-radius: 0px !important;
}
}
}

View File

@@ -23,8 +23,8 @@
<style>
.progress {
width: 100%;
height: 30px;
margin: 5px;
text-align: center;
background: var(--comfy-progress-bar-background);
padding: 0px;

View File

@@ -161,7 +161,7 @@ export abstract class ComfyWidgetNode<T = any> extends ComfyGraphNode {
}
private triggerChangeEvent(value: any) {
console.debug("[Widget] trigger changed", this, value)
// console.debug("[Widget] trigger changed", this, value)
const changedOutput = this.outputs[this.changedIndex]
if (changedOutput.type === BuiltInSlotType.EVENT)
this.triggerSlot(this.changedIndex, value)
@@ -271,7 +271,7 @@ export abstract class ComfyWidgetNode<T = any> extends ComfyGraphNode {
}
}
console.debug("Property copy", input, this.properties)
// console.debug("Property copy", input, this.properties)
this.setValue(get(this.value))
@@ -288,7 +288,7 @@ export abstract class ComfyWidgetNode<T = any> extends ComfyGraphNode {
if (layoutEntry && layoutEntry.parent) {
layoutEntry.parent.attrsChanged.set(get(layoutEntry.parent.attrsChanged) + 1)
}
console.debug("propsChanged", this)
// console.debug("propsChanged", this)
this.propsChanged.set(get(this.propsChanged) + 1)
}

View File

@@ -122,6 +122,34 @@ function statusUpdated(status: ComfyAPIStatusResponse | null) {
})
}
function findEntryInPending(promptID: PromptID): [number, QueueEntry, Writable<QueueEntry[]>] | null {
const state = get(store);
let index = get(state.queuePending).findIndex(e => e.promptID === promptID)
if (index)
return [index, get(state.queuePending)[index], state.queuePending]
index = get(state.queueRunning).findIndex(e => e.promptID === promptID)
if (index)
return [index, get(state.queueRunning)[index], state.queueRunning]
return null
}
function moveToCompleted(index: number, queue: Writable<QueueEntry[]>, status: QueueEntryStatus, error?: string) {
const state = get(store)
const entry = get(queue)[index];
entry.finishedAt = new Date() // Now
queue.update(qp => { qp.splice(index, 1); return qp });
state.queueCompleted.update(qc => {
const completed: CompletedQueueEntry = { entry, status, error }
qc.push(completed)
return qc
})
store.set(state)
}
function executingUpdated(promptID: PromptID | null, runningNodeID: NodeID | null) {
console.debug("[queueState] executingUpdated", promptID, runningNodeID)
store.update((s) => {
@@ -131,20 +159,12 @@ function executingUpdated(promptID: PromptID | null, runningNodeID: NodeID | nul
}
else if (promptID != null) {
// Prompt finished executing.
const queuePending = get(s.queuePending)
const index = queuePending.findIndex(e => e.promptID === promptID)
if (index) {
const entry = queuePending[index]
entry.finishedAt = new Date() // Now
s.queuePending.update(qp => { qp.splice(index, 1); return qp });
s.queueCompleted.update(qc => {
const completed: CompletedQueueEntry = {
entry,
status: "success",
const [index, entry, queue] = findEntryInPending(promptID);
if (entry) {
moveToCompleted(index, queue, "success")
}
qc.push(completed)
return qc
})
else {
console.error("[queueState] Could not find in pending! (executingUpdated)", promptID)
}
s.progress = null;
s.runningNodeID = null;
@@ -156,23 +176,14 @@ function executingUpdated(promptID: PromptID | null, runningNodeID: NodeID | nul
function executionCached(promptID: PromptID, nodes: NodeID[]) {
console.debug("[queueState] executionCached", promptID, nodes)
store.update(s => {
const queuePending = get(s.queuePending)
const index = queuePending.findIndex(e => e.promptID === promptID)
if (index) {
const entry = queuePending[index]
if (nodes.length >= Object.keys(entry.prompt.output).length) {
entry.finishedAt = new Date() // Now
s.queuePending.update(qp => { qp.splice(index, 1); return qp });
s.queueCompleted.update(qc => {
const completed: CompletedQueueEntry = {
entry,
status: "all_cached",
const [index, entry, queue] = findEntryInPending(promptID);
if (entry) {
if (nodes.length >= Object.keys(entry.prompt).length) {
moveToCompleted(index, queue, "all_cached");
}
qc.push(completed)
return qc
})
}
else {
console.error("[queueState] Could not find in pending! (executionCached)", promptID)
}
s.progress = null;
s.runningNodeID = null;
@@ -183,21 +194,12 @@ function executionCached(promptID: PromptID, nodes: NodeID[]) {
function executionError(promptID: PromptID, message: string) {
console.debug("[queueState] executionError", promptID, message)
store.update(s => {
const queuePending = get(s.queuePending)
const index = queuePending.findIndex(e => e.promptID === promptID)
if (index) {
const entry = s.queuePending[index]
entry.finishedAt = new Date() // Now
s.queuePending.update(qp => { qp.splice(index, 1); return qp });
s.queueCompleted.update(qc => {
const completed: CompletedQueueEntry = {
entry,
status: "error",
error: message
const [index, entry, queue] = findEntryInPending(promptID);
if (entry) {
moveToCompleted(index, queue, "error", message)
}
qc.push(completed)
return qc
})
else {
console.error("[queueState] Could not find in pending! (executionError)", promptID)
}
s.progress = null;
s.runningNodeID = null;
@@ -206,7 +208,7 @@ function executionError(promptID: PromptID, message: string) {
}
function afterQueued(promptID: PromptID, number: number, prompt: SerializedPromptInputsAll, extraData: any) {
console.debug("[queueState] afterQueued", promptID, Object.keys(prompt.nodes))
console.debug("[queueState] afterQueued", promptID, Object.keys(prompt))
store.update(s => {
const entry: QueueEntry = {
number,
@@ -226,11 +228,13 @@ function afterQueued(promptID: PromptID, number: number, prompt: SerializedPromp
function onExecuted(promptID: PromptID, nodeID: NodeID, output: GalleryOutput) {
console.debug("[queueState] onExecuted", promptID, nodeID, output)
store.update(s => {
const queuePending = get(s.queuePending)
const entry = queuePending.find(e => e.promptID === promptID)
const [index, entry, queue] = findEntryInPending(promptID)
if (entry) {
entry.outputs[nodeID] = output;
s.queuePending.update(qp => { qp.push(entry); return qp; })
queue.set(get(queue))
}
else {
console.error("[queueState] Could not find in pending! (onExecuted)", promptID)
}
return s
})

View File

@@ -13,6 +13,10 @@ export function clamp(n: number, min: number, max: number): number {
return Math.min(Math.max(n, min), max)
}
export function negmod(n: number, m: number): number {
return ((n % m) + m) % m;
}
export function range(size: number, startAt: number = 0): ReadonlyArray<number> {
return [...Array(size).keys()].map(i => i + startAt);
}

View File

@@ -122,14 +122,14 @@
// the event might fire too early
const callback = isMobile ? setupImageForMobileLightbox
: ImageViewer.instance.setupImageForLightbox.bind(ImageViewer.instance)
: ImageViewer.instance.setupGalleryImageForLightbox.bind(ImageViewer.instance)
setTimeout(() => {
const images = element.querySelectorAll<HTMLImageElement>('div.block div > img')
if (images != null) {
images.forEach(callback);
}
ImageViewer.instance.updateOnBackgroundChange();
ImageViewer.instance.refreshImages();
}, 200)
// Update index

View File

@@ -14,6 +14,7 @@ body {
:root {
--color-blue-500: #3985f5;
--comfy-accent-soft: var(--neutral-400);
--comfy-splitpanes-background-fill: var(--secondary-100);
--comfy-splitpanes-background-fill-hover: var(--secondary-300);
--comfy-splitpanes-background-fill-active: var(--secondary-400);
@@ -21,8 +22,8 @@ body {
--comfy-dropdown-item-background-hover: var(--neutral-400);
--comfy-dropdown-item-color-active: var(--neutral-100);
--comfy-dropdown-item-background-active: var(--secondary-600);
--comfy-progress-bar-background: var(--secondary-300);
--comfy-progress-bar-foreground: #var(--body-text-color);
--comfy-progress-bar-background: var(--neutral-300);
--comfy-progress-bar-foreground: var(--secondary-300);
--comfy-node-name-background: var(--color-red-300);
--comfy-node-name-foreground: var(--body-text-color);
--comfy-spinner-main-color: var(--neutral-400);
@@ -32,6 +33,7 @@ body {
.dark {
color-scheme: dark;
--comfy-accent-soft: var(--neutral-600);
--comfy-splitpanes-background-fill: var(--panel-border-color);
--comfy-splitpanes-background-fill-hover: var(--secondary-500);
--comfy-splitpanes-background-fill-active: var(--secondary-300);
@@ -40,9 +42,9 @@ body {
--comfy-dropdown-item-background-hover: var(--neutral-600);
--comfy-dropdown-item-background-active: var(--secondary-600);
--comfy-dropdown-border-color: var(--neutral-600);
--comfy-progress-bar-background: var(--secondary-400);
--comfy-progress-bar-foreground: #var(--body-text-color);
--comfy-node-name-background: var(--primary-500);
--comfy-progress-bar-background: var(--neutral-500);
--comfy-progress-bar-foreground: var(--secondary-400);
--comfy-node-name-background: var(--neutral-700);
--comfy-node-name-foreground: var(--body-text-color);
--comfy-spinner-main-color: var(--neutral-600);
--comfy-spinner-accent-color: var(--secondary-600);
@@ -96,6 +98,30 @@ select {
// }
}
// button {
// filter: none;
// &.primary:active {
// filter: brightness(80%)
// }
// &.secondary:active {
// filter: brightness(80%)
// }
// }
button {
&.primary:active {
border-color: var(--button-primary-border-color-active) !important;
background: var(--button-primary-background-fill-active) !important;
color: var(--button-primary-text-color-active) !important;
}
&.secondary:active {
border-color: var(--button-secondary-border-color-active) !important;
background: var(--button-secondary-background-fill-active) !important;
color: var(--button-secondary-text-color-active) !important;
}
}
.widget {
// padding: var(--ae-outside-gap-size);
// border: 1px solid var(--ae-panel-border-color);

View File

@@ -180,16 +180,22 @@
--button-large-text-weight: 600;
--button-primary-background-fill: linear-gradient(to bottom right, var(--primary-100), var(--primary-300));
--button-primary-background-fill-hover: linear-gradient(to bottom right, var(--primary-100), var(--primary-200));
--button-primary-background-fill-active: linear-gradient(to bottom right, var(--primary-200), var(--primary-400));
--button-primary-border-color: var(--primary-200);
--button-primary-border-color-hover: var(--button-primary-border-color);
--button-primary-border-color-active: var(--button-primary-border-color);
--button-primary-text-color: var(--primary-600);
--button-primary-text-color-hover: var(--button-primary-text-color);
--button-primary-text-color-active: var(--button-primary-text-color);
--button-secondary-background-fill: linear-gradient(to bottom right, var(--neutral-100), var(--neutral-200));
--button-secondary-background-fill-hover: linear-gradient(to bottom right, var(--neutral-100), var(--neutral-100));
--button-secondary-background-fill-active: linear-gradient(to bottom right, var(--neutral-200), var(--neutral-300));
--button-secondary-border-color: var(--neutral-200);
--button-secondary-border-color-hover: var(--button-secondary-border-color);
--button-secondary-border-color-active: var(--button-secondary-border-color);
--button-secondary-text-color: var(--neutral-700);
--button-secondary-text-color-hover: var(--button-secondary-text-color);
--button-secondary-text-color-active: var(--neutral-800);
--button-shadow: var(--shadow-drop);
--button-shadow-active: var(--shadow-inset);
--button-shadow-hover: var(--shadow-drop-lg);
@@ -277,16 +283,22 @@
--button-cancel-text-color-hover: var(--button-cancel-text-color);
--button-primary-background-fill: linear-gradient(to bottom right, var(--primary-500), var(--primary-600));
--button-primary-background-fill-hover: linear-gradient(to bottom right, var(--primary-500), var(--primary-500));
--button-primary-background-fill-active: linear-gradient(to bottom right, var(--primary-600), var(--primary-700));
--button-primary-border-color: var(--primary-500);
--button-primary-border-color-hover: var(--button-primary-border-color);
--button-primary-border-color-active: var(--button-primary-border-color);
--button-primary-text-color: white;
--button-primary-text-color-hover: var(--button-primary-text-color);
--button-primary-text-color-active: var(--neutral-300);
--button-secondary-background-fill: linear-gradient(to bottom right, var(--neutral-600), var(--neutral-700));
--button-secondary-background-fill-hover: linear-gradient(to bottom right, var(--neutral-600), var(--neutral-600));
--button-secondary-background-fill-active: linear-gradient(to bottom right, var(--neutral-700), var(--neutral-800));
--button-secondary-border-color: var(--neutral-600);
--button-secondary-border-color-hover: var(--button-secondary-border-color);
--button-secondary-border-color-active: var(--button-secondary-border-color);
--button-secondary-text-color: white;
--button-secondary-text-color-hover: var(--button-secondary-text-color);
--button-secondary-text-color-active: var(--neutral-300);
--name: default;
--primary-50: #fff7ed;
--primary-100: #ffedd5;