diff --git a/web/constants.js b/web/constants.js index 441a766..df0d251 100644 --- a/web/constants.js +++ b/web/constants.js @@ -1,10 +1,24 @@ export const BUTTON_STYLES = { - base: "width: 100%; padding: 8px 12px; font-size: 12px; color: white; border: none; border-radius: 4px; cursor: pointer; transition: all 0.2s; font-weight: 500;", - clearMemory: "background-color: #555;", - success: "background-color: #3ca03c;", - error: "background-color: #c04c4c;", + // Base styles with unified padding + base: "width: 100%; padding: 4px 14px; color: white; border: none; border-radius: 4px; cursor: pointer; transition: all 0.2s; font-size: 12px; font-weight: 500;", + + // Context-specific combined styles + workerControl: "flex: 1; font-size: 11px;", + + // Layout modifiers + hidden: "display: none;", + marginLeftAuto: "margin-left: auto;", + + // Color variants + cancel: "background-color: #555;", + info: "background-color: #333;", + success: "background-color: #4a7c4a;", + error: "background-color: #7c4a4a;", launch: "background-color: #4a7c4a;", stop: "background-color: #7c4a4a;", + log: "background-color: #685434;", + clearMemory: "background-color: #555; padding: 6px 14px;", + interrupt: "background-color: #555; padding: 6px 14px;", }; export const STATUS_COLORS = { @@ -30,22 +44,23 @@ export const PULSE_ANIMATION_CSS = ` @keyframes pulse { 0% { opacity: 1; - transform: scale(1); + transform: scale(0.8); box-shadow: 0 0 0 0 rgba(240, 173, 78, 0.7); } 50% { opacity: 0.3; - transform: scale(1.3); + transform: scale(1.1); box-shadow: 0 0 0 6px rgba(240, 173, 78, 0); } 100% { opacity: 1; - transform: scale(1); + transform: scale(0.8); box-shadow: 0 0 0 0 rgba(240, 173, 78, 0); } } .status-pulsing { animation: pulse 1.2s ease-in-out infinite; + transform-origin: center; } /* Button hover effects */ diff --git a/web/sidebarRenderer.js b/web/sidebarRenderer.js index 3187ee4..9fc95a0 100644 --- a/web/sidebarRenderer.js +++ b/web/sidebarRenderer.js @@ -24,7 +24,9 @@ export async function renderSidebarContent(extension, el) { el.innerHTML = ''; const loadingDiv = document.createElement("div"); loadingDiv.style.cssText = "display: flex; align-items: center; justify-content: center; height: calc(100vh - 100px); color: #888;"; - loadingDiv.innerHTML = `
◐
`; + loadingDiv.innerHTML = ` + + `; el.appendChild(loadingDiv); // Add rotation animation @@ -36,7 +38,7 @@ export async function renderSidebarContent(extension, el) { } `; document.head.appendChild(style); - loadingDiv.querySelector('div').style.animation = 'rotate 1s linear infinite'; + loadingDiv.querySelector('svg').style.animation = 'rotate 1s linear infinite'; // Preload data outside render await extension.loadConfig(); @@ -128,15 +130,15 @@ export async function renderSidebarContent(extension, el) { BUTTON_STYLES.clearMemory ); clearMemButton.title = "Clear VRAM on all enabled worker GPUs (not master)"; - clearMemButton.style.cssText += " flex: 1;"; + clearMemButton.style.cssText = BUTTON_STYLES.base + " flex: 1;" + BUTTON_STYLES.clearMemory; const interruptButton = extension.ui.createButtonHelper( "Interrupt Workers", (e) => extension._handleInterruptWorkers(e.target), - BUTTON_STYLES.clearMemory + BUTTON_STYLES.interrupt ); interruptButton.title = "Cancel/interrupt execution on all enabled worker GPUs"; - interruptButton.style.cssText += " flex: 1;"; + interruptButton.style.cssText = BUTTON_STYLES.base + " flex: 1;" + BUTTON_STYLES.interrupt; buttonRow.appendChild(clearMemButton); buttonRow.appendChild(interruptButton); diff --git a/web/ui.js b/web/ui.js index 24f0808..de41240 100644 --- a/web/ui.js +++ b/web/ui.js @@ -591,17 +591,17 @@ export class DistributedUI { const saveBtn = this.createButton("Save", () => extension.saveWorkerSettings(worker.id), "background-color: #4a7c4a;"); - saveBtn.style.cssText += " padding: 6px 14px; font-size: 12px; font-weight: 500;"; + saveBtn.style.cssText = BUTTON_STYLES.base + BUTTON_STYLES.success; const cancelBtn = this.createButton("Cancel", () => extension.cancelWorkerSettings(worker.id), "background-color: #555;"); - cancelBtn.style.cssText += " padding: 6px 14px; font-size: 12px; font-weight: 500;"; + cancelBtn.style.cssText = BUTTON_STYLES.base + BUTTON_STYLES.cancel; const deleteBtn = this.createButton("Delete", () => extension.deleteWorker(worker.id), "background-color: #7c4a4a;"); - deleteBtn.style.cssText += " padding: 6px 14px; font-size: 12px; font-weight: 500; margin-left: auto;"; + deleteBtn.style.cssText = BUTTON_STYLES.base + BUTTON_STYLES.error + BUTTON_STYLES.marginLeftAuto; const buttonGroup = this.createButtonGroup([saveBtn, cancelBtn, deleteBtn], " margin-top: 8px;"); form.appendChild(buttonGroup); @@ -728,8 +728,8 @@ export class DistributedUI { if (config.dynamic && data) { if (isRemote) { - const remoteInfo = this.createButton("Remote worker", null, "background-color: #333;"); - remoteInfo.style.cssText += " flex: 1; padding: 5px 14px; font-size: 11px; font-weight: 500; color: #999; cursor: default;"; + const remoteInfo = this.createButton("Remote worker", null, BUTTON_STYLES.info); + remoteInfo.style.cssText = BUTTON_STYLES.base + BUTTON_STYLES.workerControl + BUTTON_STYLES.info + " color: #999; cursor: default;"; remoteInfo.disabled = true; controlsWrapper.appendChild(remoteInfo); } else { @@ -743,13 +743,13 @@ export class DistributedUI { const stopBtn = controls.querySelector(`#stop-${data.id}`); const logBtn = controls.querySelector(`#log-${data.id}`); - launchBtn.style.cssText += ` flex: 1; padding: 5px 14px; font-size: 11px; font-weight: 500; ${BUTTON_STYLES.launch}`; + launchBtn.style.cssText = BUTTON_STYLES.base + BUTTON_STYLES.workerControl + BUTTON_STYLES.launch; launchBtn.title = "Launch worker (runs in background with logging)"; - stopBtn.style.cssText += ` flex: 1; padding: 5px 14px; font-size: 11px; font-weight: 500; ${BUTTON_STYLES.stop} display: none;`; + stopBtn.style.cssText = BUTTON_STYLES.base + BUTTON_STYLES.workerControl + BUTTON_STYLES.stop + BUTTON_STYLES.hidden; stopBtn.title = "Stop worker"; - logBtn.style.cssText += ' flex: 1; padding: 5px 14px; font-size: 11px; font-weight: 500; display: none; background-color: #685434;'; + logBtn.style.cssText = BUTTON_STYLES.base + BUTTON_STYLES.workerControl + BUTTON_STYLES.log + BUTTON_STYLES.hidden; while (controls.firstChild) { controlsWrapper.appendChild(controls.firstChild); @@ -757,7 +757,7 @@ export class DistributedUI { } } else if (config.type === 'info') { const infoBtn = this.createButton(config.text, null, config.style || ""); - infoBtn.style.cssText += " flex: 1; padding: 5px 14px; font-size: 11px; font-weight: 500; cursor: default;"; + infoBtn.style.cssText = BUTTON_STYLES.base + BUTTON_STYLES.workerControl + (config.style || BUTTON_STYLES.info) + " cursor: default;"; infoBtn.disabled = true; controlsWrapper.appendChild(infoBtn); } else if (config.type === 'ghost') { @@ -860,13 +860,13 @@ export class DistributedUI { saveBtn.textContent = "Saved!"; setTimeout(() => { saveBtn.textContent = "Save"; }, TIMEOUTS.FLASH_LONG); }, "background-color: #4a7c4a;"); - saveBtn.style.cssText += " padding: 6px 12px; font-size: 12px;"; + saveBtn.style.cssText = BUTTON_STYLES.base + BUTTON_STYLES.success; const cancelBtn = this.createButton("Cancel", () => { document.getElementById('master-name').value = extension.config?.master?.name || "Master"; document.getElementById('master-host').value = extension.config?.master?.host || ""; }, "background-color: #555;"); - cancelBtn.style.cssText += " padding: 6px 12px; font-size: 12px;"; + cancelBtn.style.cssText = BUTTON_STYLES.base + BUTTON_STYLES.cancel; const buttonGroup = this.createButtonGroup([saveBtn, cancelBtn], " margin-top: 8px;"); settingsForm.appendChild(buttonGroup);