Cookbook/Dependencies: variant toggle now uses the agent/chat mode-toggle; Copy inside code

- Drop the 'Install via' label and the pill-tag variant buttons. The
  toggle is now the same sliding-pill mode-toggle used by the
  Agent/Chat selector in the chat input. Pip/uv on the left, Docker on
  the right, default = Pip/uv. CSS: extended .mode-chat::before's
  translateX(100%) rule to also fire on .mode-right so non-chat
  callers can use the same animation without claiming the chat-only
  class name.
- Copy button moves inside the <pre>: absolute-positioned at the
  top-right corner, icon-only, padding-right on the pre makes room.
  Matches the Setup-token copy pattern in the integrations form.
This commit is contained in:
pewdiepie-archdaemon
2026-06-14 22:54:38 +09:00
parent 63b4ad2e9c
commit 768bcb565a
2 changed files with 38 additions and 19 deletions
+15 -14
View File
@@ -868,21 +868,21 @@ async function _fetchDependencies() {
const initial = pickRecipe(backend, '') || candidates[0];
const initialVariant = RECIPE_DEFAULT_VARIANT;
const initialCmds = recipeCommands(initial, initialVariant);
const _variantBtn = (v, label) =>
`<button type="button" class="cookbook-dep-tag cookbook-dep-variant${v === initialVariant ? ' is-active' : ''}" data-dep-recipe-variant="${esc(backend)}" data-variant="${esc(v)}" style="font-size:10px;padding:3px 8px;cursor:pointer;${v === initialVariant ? 'background:color-mix(in srgb, var(--accent, var(--red)) 18%, transparent);color:var(--accent, var(--red));' : 'opacity:0.7;'}">${label}</button>`;
const rightActive = initialVariant === 'docker' ? ' mode-right' : '';
return `<div class="cookbook-dep-recipe-panel" data-dep-recipe-panel="${esc(backend)}" data-dep-recipe-active-variant="${esc(initialVariant)}" style="display:none;margin:-4px 0 8px;padding:8px 12px 10px;background:rgba(0,0,0,0.04);border:1px solid var(--border);border-top:none;border-radius:0 0 6px 6px;">
<div style="display:flex;align-items:center;gap:8px;margin-bottom:6px;">
<span style="font-size:11px;opacity:0.75;flex-shrink:0;">Serving which model?</span>
<select class="settings-select cookbook-dep-recipe-pick" data-dep-recipe-pick="${esc(backend)}" style="flex:1;font-size:11px;padding:3px 6px;">${opts}</select>
<div class="mode-toggle${rightActive}" data-dep-recipe-variants="${esc(backend)}" style="flex-shrink:0;">
<button type="button" class="mode-toggle-btn${initialVariant === 'pip' ? ' active' : ''}" data-dep-recipe-variant="${esc(backend)}" data-variant="pip" aria-pressed="${initialVariant === 'pip'}">Pip/uv</button>
<button type="button" class="mode-toggle-btn${initialVariant === 'docker' ? ' active' : ''}" data-dep-recipe-variant="${esc(backend)}" data-variant="docker" aria-pressed="${initialVariant === 'docker'}">Docker</button>
</div>
</div>
<div style="display:flex;gap:4px;margin-bottom:6px;align-items:center;">
<span style="font-size:11px;opacity:0.75;flex-shrink:0;">Install via</span>
${_variantBtn('pip', 'Pip / uv')}
${_variantBtn('docker', 'Docker')}
<div style="position:relative;">
<pre class="cookbook-dep-recipe-cmds" data-dep-recipe-cmds="${esc(backend)}" data-dep-recipe-install="${esc(initialCmds.join('\n'))}" style="margin:0;padding:8px 36px 8px 10px;background:rgba(0,0,0,0.08);border-radius:4px;font-size:11px;line-height:1.5;overflow-x:auto;white-space:pre;">${esc(_recipeDisplayText(initialCmds, initialVariant))}</pre>
<button type="button" id="recipe-copy-${esc(backend)}" class="cookbook-dep-recipe-copy" data-dep-recipe-copy="${esc(backend)}" title="Copy" aria-label="Copy" style="position:absolute;top:6px;right:6px;padding:3px 5px;background:none;border:none;color:inherit;opacity:0.7;cursor:pointer;display:inline-flex;align-items:center;"><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg></button>
</div>
<pre class="cookbook-dep-recipe-cmds" data-dep-recipe-cmds="${esc(backend)}" data-dep-recipe-install="${esc(initialCmds.join('\n'))}" style="margin:0;padding:8px 10px;background:rgba(0,0,0,0.08);border-radius:4px;font-size:11px;line-height:1.5;overflow-x:auto;white-space:pre;">${esc(_recipeDisplayText(initialCmds, initialVariant))}</pre>
<div style="display:flex;gap:6px;justify-content:flex-end;margin-top:6px;">
<button type="button" class="cookbook-dep-tag cookbook-dep-recipe-copy" data-dep-recipe-copy="${esc(backend)}" style="display:inline-flex;align-items:center;gap:4px;cursor:pointer;"><svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg>Copy</button>
<button type="button" class="cookbook-dep-tag cookbook-dep-install cookbook-dep-recipe-run" data-dep-recipe-run="${esc(backend)}" style="display:inline-flex;align-items:center;gap:4px;cursor:pointer;"><svg width="11" height="11" viewBox="0 0 24 24" fill="currentColor"><polygon points="5 3 19 12 5 21 5 3"/></svg>Run</button>
</div>
</div>`;
@@ -1028,7 +1028,9 @@ async function _fetchDependencies() {
list.querySelectorAll('[data-dep-recipe-pick]').forEach(sel => {
sel.addEventListener('change', () => _refreshRecipePre(sel.dataset.depRecipePick));
});
// Variant pill (Pip/uv vs Docker): toggles the active install variant.
// Variant toggle (Pip/uv vs Docker): mirrors the agent/chat mode-toggle
// pattern — buttons get .active, container gets .mode-right when the
// right slot is selected so the sliding pill animates over.
list.querySelectorAll('[data-dep-recipe-variant]').forEach(btn => {
btn.addEventListener('click', (e) => {
e.stopPropagation();
@@ -1037,13 +1039,12 @@ async function _fetchDependencies() {
const panel = list.querySelector(`[data-dep-recipe-panel="${CSS.escape(backend)}"]`);
if (!panel) return;
panel.dataset.depRecipeActiveVariant = variant;
// Reflect active state on the pills.
const container = panel.querySelector('.mode-toggle[data-dep-recipe-variants]');
if (container) container.classList.toggle('mode-right', variant === 'docker');
panel.querySelectorAll('[data-dep-recipe-variant]').forEach(b => {
const on = b.dataset.variant === variant;
b.classList.toggle('is-active', on);
b.style.background = on ? 'color-mix(in srgb, var(--accent, var(--red)) 18%, transparent)' : '';
b.style.color = on ? 'var(--accent, var(--red))' : '';
b.style.opacity = on ? '' : '0.7';
b.classList.toggle('active', on);
b.setAttribute('aria-pressed', on ? 'true' : 'false');
});
_refreshRecipePre(backend);
});
+23 -5
View File
@@ -2672,7 +2672,8 @@ body.bg-pattern-sparkles {
transition: transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
z-index: 0;
}
.mode-toggle.mode-chat::before {
.mode-toggle.mode-chat::before,
.mode-toggle.mode-right::before {
transform: translateX(100%);
}
#mode-agent-btn {
@@ -18958,12 +18959,12 @@ body.gallery-selecting .gallery-dl-btn,
}
.cookbook-gpu-group {
display: flex;
gap: 2px;
gap: 3px;
margin-top: -4px;
}
.cookbook-gpu-btn {
width: 22px; height: 22px;
font-size: 10px;
width: 28px; height: 26px;
font-size: 12px;
font-family: 'Fira Code', monospace;
border: 1px solid var(--border);
border-radius: 4px;
@@ -19594,6 +19595,15 @@ body.gallery-selecting .gallery-dl-btn,
position: relative;
top: -4px;
}
/* The Settings label wraps the Save split right-align its title text
so the word "Settings" sits above the right-aligned Save button
instead of floating off to the left of its grid cell. 8px right
padding now (16px 8px) per follow-up tweak, brings the title back
over the actual Save button instead of overshooting it. */
.hwfit-serve-row label:has(> .cookbook-serve-slots) {
text-align: right;
padding-right: 8px;
}
/* Expanded serve panel make sure it can be scrolled past when it
grows taller than the visible viewport. Caps panel height to viewport
minus chrome and gives it its own internal scroll, so the surrounding
@@ -19771,11 +19781,19 @@ body.gallery-selecting .gallery-dl-btn,
.hwfit-spec-tokens-bare {
-moz-appearance: textfield;
appearance: textfield;
/* Tighten + center now that the spinner column is gone without this
the input still reserves the old 44px and the number floats with a
dead gutter on the right. !important beats the inline width=44px
that ships in the markup. */
width: 30px !important;
padding-right: 4px !important;
text-align: center;
}
.hwfit-spec-tokens-bare::-webkit-outer-spin-button,
.hwfit-spec-tokens-bare::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
display: none;
}
/* Themed step buttons replacing the native number-input spinner. */
.hwfit-numstep {
@@ -19851,7 +19869,7 @@ body.gallery-selecting .gallery-dl-btn,
.hwfit-sf-cb input[type="checkbox"]::after {
content: '';
position: absolute;
top: 1.5px;
top: 1px;
left: 2px;
width: 10px;
height: 10px;