From ef7e5f90ec67de862bc8ecb08dcd7ee5935387f3 Mon Sep 17 00:00:00 2001 From: pewdiepie-archdaemon Date: Sat, 27 Jun 2026 22:01:23 +0000 Subject: [PATCH] Add icons to cookbook engine filter --- static/js/cookbook-hwfit.js | 80 ++++++++++++++++++++++++++++++++- static/js/cookbook.js | 9 +++- static/js/cookbookServe.js | 6 +-- static/style.css | 90 ++++++++++++++++++++++++++++++++++++- 4 files changed, 179 insertions(+), 6 deletions(-) diff --git a/static/js/cookbook-hwfit.js b/static/js/cookbook-hwfit.js index 7fab5570c..25a65779c 100644 --- a/static/js/cookbook-hwfit.js +++ b/static/js/cookbook-hwfit.js @@ -468,7 +468,7 @@ function _hwfitShowError(list, host, detail) { if (rb) rb.addEventListener('click', () => { _resetGpuToggleState(); _hwfitFetch(true); }); } -// Client-side "Engine" filter (llama.cpp / vLLM / SGLang / Ollama). Empty = +// Client-side "Engine" filter (llama.cpp / vLLM / SGLang / Ollama / Diffusers). Empty = // show all. Uses the same _detectBackend() the serve commands use, so what you // filter to is exactly what would be launched. Pure view filter — no refetch // needed. Ollama rows are merged into the main list (see _ensureOllamaLib + @@ -1804,6 +1804,83 @@ export function _expandModelRow(row, modelData) { } +const _HWFIT_ENGINE_GLYPHS = { + '': '', + vllm: '', + sglang: '', + llamacpp: '', + ollama: '', + diffusers: '', +}; + +function _hwfitEngineGlyph(value) { + return _HWFIT_ENGINE_GLYPHS[value] || _HWFIT_ENGINE_GLYPHS['']; +} + +function _bindHwfitEnginePicker(engine) { + const wrap = engine?.closest('.hwfit-engine-wrap'); + const btn = wrap?.querySelector('[data-hwfit-engine-btn]'); + const menu = wrap?.querySelector('[data-hwfit-engine-menu]'); + const icon = wrap?.querySelector('[data-hwfit-engine-icon]'); + const label = wrap?.querySelector('[data-hwfit-engine-label]'); + if (!engine || !wrap || !btn || !menu || wrap.dataset.enginePickerBound) return; + wrap.dataset.enginePickerBound = '1'; + + const setOpen = (open) => { + menu.hidden = !open; + btn.setAttribute('aria-expanded', open ? 'true' : 'false'); + }; + const currentLabel = () => { + const opt = Array.from(engine.options).find((o) => o.value === engine.value); + return opt?.textContent || 'Engine'; + }; + const syncButton = () => { + if (label) label.textContent = currentLabel(); + if (icon) icon.innerHTML = _hwfitEngineGlyph(engine.value); + menu.querySelectorAll('[data-hwfit-engine-value]').forEach((item) => { + const active = item.dataset.hwfitEngineValue === engine.value; + item.classList.toggle('active', active); + item.setAttribute('aria-selected', active ? 'true' : 'false'); + }); + }; + const renderMenu = () => { + menu.innerHTML = Array.from(engine.options).map((opt) => ( + `' + )).join(''); + menu.querySelectorAll('[data-hwfit-engine-value]').forEach((item) => { + item.addEventListener('click', (ev) => { + ev.preventDefault(); + ev.stopPropagation(); + const next = item.dataset.hwfitEngineValue || ''; + if (engine.value !== next) { + engine.value = next; + engine.dispatchEvent(new Event('change', { bubbles: true })); + } + syncButton(); + setOpen(false); + }); + }); + syncButton(); + }; + + btn.addEventListener('click', (ev) => { + ev.preventDefault(); + ev.stopPropagation(); + setOpen(menu.hidden); + }); + engine.addEventListener('change', syncButton); + document.addEventListener('click', (ev) => { + if (!wrap.contains(ev.target)) setOpen(false); + }); + document.addEventListener('keydown', (ev) => { + if (ev.key === 'Escape') setOpen(false); + }); + renderMenu(); +} + export function _hwfitInit() { const uc = document.getElementById('hwfit-usecase'); const sort = document.getElementById('hwfit-sort'); @@ -1819,6 +1896,7 @@ export function _hwfitInit() { // Engine filter is a pure client-side view filter over the already-fetched // list (HF + Ollama merged), so just re-render from cache. const engine = document.getElementById('hwfit-engine'); + if (engine) _bindHwfitEnginePicker(engine); if (engine) engine.addEventListener('change', () => { const list = document.getElementById('hwfit-list'); if (list && _hwfitCache && Array.isArray(_hwfitCache.models)) { diff --git a/static/js/cookbook.js b/static/js/cookbook.js index 6451f4bc0..972f38014 100644 --- a/static/js/cookbook.js +++ b/static/js/cookbook.js @@ -2692,13 +2692,20 @@ function _renderRecipes() { // levers (Engine / Quant / Context) live to the right. html += ''; html += ''; - html += ''; html += ''; html += ''; html += ''; html += ''; html += ''; + html += ''; html += ''; + html += ''; + html += ''; html += '?'; html += ''; // Quant (Q4/Q8/…). Default is "All" so the list shows the best-scoring diff --git a/static/js/cookbookServe.js b/static/js/cookbookServe.js index 511c49564..981e70f4c 100644 --- a/static/js/cookbookServe.js +++ b/static/js/cookbookServe.js @@ -1390,7 +1390,7 @@ function _rerenderCachedModels() { // Row 2b: Diffusers settings const diffDtypeOpts = ['bfloat16','float16','float32'].map(d => ``).join(''); const deviceMapOpts = ['balanced','auto','sequential'].map(d => ``).join(''); - panelHtml += `
`; + panelHtml += `
`; panelHtml += ``; panelHtml += ``; panelHtml += ``; @@ -1495,11 +1495,11 @@ function _rerenderCachedModels() { panelHtml += ``; panelHtml += `
`; // Row 3b: Checkboxes (diffusers) - panelHtml += `
`; + panelHtml += `
`; panelHtml += ``; panelHtml += ``; panelHtml += ``; - panelHtml += `
`; + panelHtml += `
`; panelHtml += ``; panelHtml += `
`; // Model-specific optimizations. The checks row always renders for the diff --git a/static/style.css b/static/style.css index 731961888..99523d7db 100644 --- a/static/style.css +++ b/static/style.css @@ -20479,7 +20479,7 @@ body.gallery-selecting .gallery-dl-btn, width: 100%; } .hwfit-serve-cmd-details { - margin: 6px 0 0; + margin: 4px 0 0; } .hwfit-serve-cmd-summary { display: flex; @@ -22201,6 +22201,7 @@ body.gallery-selecting .gallery-dl-btn, .hwfit-toolbar .hwfit-usecase { min-width: 70px; flex-shrink: 0; } .hwfit-toolbar .hwfit-quant { min-width: 0; width: 78px; flex-shrink: 0; font-size: 10px; } .hwfit-toolbar .hwfit-engine { min-width: 0; width: 86px; flex-shrink: 0; font-size: 10px; } +.hwfit-toolbar .hwfit-engine-btn { min-width: 0; width: 86px; flex-shrink: 0; font-size: 10px; } .hwfit-toolbar .hwfit-search { flex: 1; min-width: 80px; } /* Lower-opacity "Search models..." placeholder so it reads as a hint, not a label — matches the muted form-field feel of the inline filters. */ @@ -22271,6 +22272,83 @@ body.gallery-selecting .gallery-dl-btn, display: inline-flex; align-items: center; } +.hwfit-engine-btn { + height: 28px; + padding: 0 30px 0 7px; + display: inline-flex; + align-items: center; + gap: 5px; + color: var(--fg); + background: var(--bg); + border: 1px solid var(--border); + border-radius: 4px; + font: inherit; + cursor: pointer; + text-align: left; +} +.hwfit-engine-btn-icon, +.hwfit-engine-item-icon { + width: 14px; + height: 14px; + display: inline-flex; + align-items: center; + justify-content: center; + color: var(--accent, var(--red)); + flex-shrink: 0; +} +.hwfit-engine-btn-label { + flex: 1; + min-width: 0; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} +.hwfit-engine-caret { + position: absolute; + right: 6px; + opacity: 0.55; + pointer-events: none; +} +.hwfit-engine-menu { + position: absolute; + top: calc(100% + 4px); + left: 0; + right: 0; + z-index: 120; + padding: 4px; + background: var(--panel, var(--bg)); + border: 1px solid var(--border); + border-radius: 6px; + box-shadow: 0 6px 20px rgba(0,0,0,0.22); +} +.hwfit-engine-item { + width: 100%; + min-height: 26px; + padding: 5px 7px; + display: flex; + align-items: center; + gap: 7px; + color: var(--fg); + background: transparent; + border: 0; + border-radius: 5px; + font: inherit; + font-size: 11px; + text-align: left; + cursor: pointer; + box-sizing: border-box; +} +.hwfit-engine-item:hover, +.hwfit-engine-item.active { + background: color-mix(in srgb, var(--fg) 8%, transparent); +} +.hwfit-engine-item-label { + flex: 1; + min-width: 0; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} .hwfit-quant-wrap .hwfit-quant, .hwfit-engine-wrap .hwfit-engine { /* Make room for the ? on the right edge, in addition to the native chevron. */ @@ -24056,6 +24134,16 @@ details.hwfit-serve-advanced > .hwfit-llama-monitor-row, details.hwfit-serve-advanced > .hwfit-llama-checks-row { margin-top: -18px !important; } +details.hwfit-serve-advanced > .hwfit-diff-settings-row { + row-gap: 2px; +} +details.hwfit-serve-advanced > .hwfit-diff-checks-row, +details.hwfit-serve-advanced > .hwfit-diff-harmonize-row { + margin-top: -10px !important; +} +details.hwfit-serve-advanced > .hwfit-diff-checks-row { + row-gap: 2px; +} details.hwfit-serve-advanced > .hwfit-serve-row.hwfit-vram-monitor { gap: 4px !important; grid-template-columns: max-content minmax(0, 1fr);