From 2336fb6ef0ab42bb96cc926e222c4fc16048c678 Mon Sep 17 00:00:00 2001 From: Dariusz L Date: Wed, 27 May 2026 00:24:37 +0200 Subject: [PATCH] UI: Add local alternatives toggle and improve link button styling - Add CSS for .ml-local-alternatives-toggle component with hover/focus states - Update missing browser button styles to use compact link button - Adjust disabled footer button opacity for better visibility - Replace alternatives div with toggle button in linker.js - Enhance MLToggleHidden to support aria-expanded and dynamic label/state updates --- web/css/linker-main.css | 98 +++++++++++++++++++++++++++++++++++++++++ web/linker.js | 19 ++++++-- 2 files changed, 114 insertions(+), 3 deletions(-) diff --git a/web/css/linker-main.css b/web/css/linker-main.css index e7b74df..b28a41e 100644 --- a/web/css/linker-main.css +++ b/web/css/linker-main.css @@ -894,6 +894,57 @@ .ml-missing-browser .ml-match-filename { color: var(--ml-text-soft); } +.ml-local-alternatives-toggle { + display: flex; + align-items: center; + width: 100%; + min-height: 28px; + margin: 5px 0; + padding: 0 4px; + gap: 8px; + color: var(--ml-text-muted); + background: transparent; + border: 0; + border-top: 1px solid rgba(255,255,255,0.045); + border-bottom: 1px solid rgba(255,255,255,0.035); + border-radius: 0; + font-family: inherit; + font-size: 11px; + cursor: pointer; + outline: none; + box-sizing: border-box; + transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease; +} +.ml-local-alternatives-toggle:hover { + color: var(--ml-text-soft); + background: rgba(255,255,255,0.018); + border-color: rgba(255,255,255,0.06); +} +.ml-local-alternatives-toggle:focus-visible { + background: rgba(255,255,255,0.022); + box-shadow: inset 0 0 0 1px rgba(255,255,255,0.07); +} +.ml-local-alternatives-label { + color: var(--ml-text-muted); + font-weight: 650; +} +.ml-local-alternatives-state { + margin-left: auto; + color: var(--ml-text-dim); + font-size: 10px; + font-weight: 650; +} +.ml-local-alternatives-chevron { + width: 7px; + height: 7px; + border-right: 1px solid currentColor; + border-bottom: 1px solid currentColor; + transform: rotate(45deg) translateY(-1px); + transition: transform 0.15s ease; +} +.ml-local-alternatives-toggle[aria-expanded="true"] .ml-local-alternatives-chevron { + transform: rotate(225deg) translateY(-1px); +} /* Buttons */ .ml-btn { @@ -1008,6 +1059,43 @@ padding-inline: 5px; font-size: 8.75px; } +.ml-missing-browser .ml-local-link-btn, +.ml-missing-browser .ml-btn-link-compact { + position: relative; + flex: 0 0 46px; + width: 46px; + min-width: 46px; + height: 28px; + min-height: 28px; + padding: 0 9px; + overflow: hidden; + gap: 0; + color: var(--ml-text-muted); + font-size: 0; + font-weight: 650; + background: rgba(255,255,255,0.026); + border-color: rgba(255,255,255,0.09); +} +.ml-missing-browser .ml-local-link-btn::before, +.ml-missing-browser .ml-btn-link-compact::before { + content: "Link"; + display: block; + width: auto; + height: auto; + background: transparent; + font-size: 10px; + line-height: 1; +} +.ml-missing-browser .ml-local-link-btn > *, +.ml-missing-browser .ml-btn-link-compact > * { + display: none; +} +.ml-missing-browser .ml-local-link-btn:hover:not(:disabled), +.ml-missing-browser .ml-btn-link-compact:hover:not(:disabled) { + color: var(--ml-text); + background: rgba(255,255,255,0.05); + border-color: rgba(255,255,255,0.16); +} .ml-btn-icon-only { width: var(--ml-spacing-24); min-width: var(--ml-spacing-24); @@ -1674,6 +1762,16 @@ box-shadow: none; transform: none; } +.ml-btn.ml-footer-btn:disabled, +.ml-btn.ml-btn-primary.ml-footer-btn:disabled, +.ml-btn.ml-btn-download.ml-footer-btn:disabled { + opacity: 1; + color: rgba(255,255,255,0.34); + background: rgba(255,255,255,0.016); + border-color: rgba(255,255,255,0.055); + box-shadow: none; + cursor: not-allowed; +} /* Tabs */ .ml-tabs { diff --git a/web/linker.js b/web/linker.js index 8e9b43f..7b082bf 100644 --- a/web/linker.js +++ b/web/linker.js @@ -815,7 +815,7 @@ class LinkerManagerDialog extends ComfyDialog { html += `
`; html += this.getConfidenceBadge(match.confidence); html += `${formattedPath.display}`; - html += ``; html += `
`; @@ -823,7 +823,12 @@ class LinkerManagerDialog extends ComfyDialog { if (perfectMatches.length > 0 && otherMatches.length > 0) { const matchId = `more-matches-${missing.node_id}-${missing.widget_index}`; - html += ``; + const altLabel = `Alternatives (${otherMatches.length})`; + html += ``; html += `
`; for (let mIdx = 0; mIdx < otherMatches.length; mIdx++) { const match = otherMatches[mIdx]; @@ -6398,7 +6403,15 @@ window.MLToggleHidden = function(id, trigger, collapsedText, expandedText) { const isHidden = element.classList.toggle('ml-hidden'); if (trigger) { - trigger.textContent = isHidden ? collapsedText : expandedText; + trigger.setAttribute('aria-expanded', String(!isHidden)); + const label = trigger.querySelector?.('.ml-local-alternatives-label'); + const state = trigger.querySelector?.('.ml-local-alternatives-state'); + if (label || state) { + if (label) label.textContent = isHidden ? collapsedText : expandedText; + if (state) state.textContent = isHidden ? 'Show' : 'Hide'; + } else { + trigger.textContent = isHidden ? collapsedText : expandedText; + } } };