style(workbench): move filmstrip to left rail and enlarge thumbnail cards

This commit is contained in:
DemonGatanjieu
2026-09-04 14:44:11 +08:00
parent 57b480da79
commit 3c29cc0142
4 changed files with 99 additions and 42 deletions
+1 -1
View File
@@ -75,7 +75,7 @@ DOM or live LiteGraph state.
primary model-browser surfaces.
- `ui_gallery_detail.js` owns the full-screen / studio Image Detail Workbench,
multi-dimensional image navigation (keyboard shortcuts, floating glass arrows,
bottom filmstrip rail), and segmented Bento parameter inspection with ComfyUI
left vertical thumbnail rail), and segmented Bento parameter inspection with ComfyUI
canvas injection (`app.loadGraphData`).
- `ui_notebooks.js`, `ui_recipes.js`, and `ui_recipe_detail.js` own Workspace
presentation, featuring Bento-style visual cards, quick spec tags, real-time environment readiness indicators (🟢/🟡/🔴), one-click batch model matching, and lazy DOM rendering for node parameter trees.
+2 -2
View File
@@ -88,7 +88,7 @@ export const i18n = {
workbenchCopySuccess: '✅ 分享文本已复制',
workbenchNext: '下一张 (→)',
workbenchPrev: '上一张 (←)',
workbenchFilmstrip: '底栏缩略图',
workbenchFilmstrip: '侧栏缩略图',
workbenchTabOverview: '核心参数',
workbenchTabPrompts: '提示词工坊',
workbenchTabModels: '模型资产',
@@ -954,7 +954,7 @@ export const i18n = {
workbenchCopySuccess: '✅ Share text copied',
workbenchNext: 'Next (→)',
workbenchPrev: 'Previous (←)',
workbenchFilmstrip: 'Filmstrip',
workbenchFilmstrip: 'Thumbnail Rail',
workbenchTabOverview: 'Key Specs',
workbenchTabPrompts: 'Prompts',
workbenchTabModels: 'Models & LoRA',
+20 -9
View File
@@ -4,7 +4,7 @@
* Features:
* - Fullscreen studio workspace / windowed modal toggle
* - Prev / Next image navigation (keyboard arrows, floating glass arrows, counter jump)
* - Collapsible bottom thumbnail filmstrip with smooth auto-centering
* - Collapsible left thumbnail rail with smooth vertical auto-centering
* - High-speed in-memory LRU metadata cache (imageMetadataCache)
* - Preloading of adjacent images and AbortController request cancellation
* - Segmented Bento Inspector: Key Specs Bento grid, Prompts Station, Models & LoRA with weight pills, Node structure
@@ -225,7 +225,7 @@ function buildWorkbenchHeader(item, index, total, onNavigate) {
? 'anomalous-workbench-tool-btn is-active'
: 'anomalous-workbench-tool-btn';
filmstripToggle.innerHTML = '🎞️';
filmstripToggle.title = t('workbenchFilmstrip') || '底栏缩略图';
filmstripToggle.title = t('workbenchFilmstrip') || (window.anomalous_browser_lang === 'zh' ? '侧栏缩略图' : 'Thumbnail Rail');
filmstripToggle.onclick = () => {
wb.isFilmstripVisible = !wb.isFilmstripVisible;
filmstripToggle.classList.toggle('is-active', wb.isFilmstripVisible);
@@ -338,11 +338,14 @@ function setupStagePanZoom(stage, img) {
}
/**
* Build Bottom Filmstrip Rail
* Build Left Vertical Filmstrip Rail
*/
function buildFilmstripRail(items, currentIndex, onNavigate) {
const rail = document.createElement('div');
rail.className = 'anomalous-workbench-filmstrip';
if (wb && wb.isFilmstripVisible === false) {
rail.classList.add('is-hidden');
}
const track = document.createElement('div');
track.className = 'anomalous-workbench-filmstrip-track';
@@ -360,6 +363,11 @@ function buildFilmstripRail(items, currentIndex, onNavigate) {
thumbImg.alt = '';
thumbWrap.appendChild(thumbImg);
const badge = document.createElement('span');
badge.className = 'anomalous-workbench-thumb-index';
badge.textContent = String(idx + 1);
thumbWrap.appendChild(badge);
thumbWrap.onclick = (e) => {
e.stopPropagation();
if (idx !== currentIndex) onNavigate(idx);
@@ -367,10 +375,12 @@ function buildFilmstripRail(items, currentIndex, onNavigate) {
track.appendChild(thumbWrap);
// Auto-center active thumbnail
// Auto-center active thumbnail vertically
if (idx === currentIndex) {
requestAnimationFrame(() => {
thumbWrap.scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'center' });
setTimeout(() => {
thumbWrap.scrollIntoView({ behavior: 'smooth', block: 'center', inline: 'nearest' });
}, 40);
});
}
});
@@ -758,7 +768,7 @@ async function loadWorkbenchImage(index) {
thumbs.forEach((el, i) => {
el.classList.toggle('is-active', i === index);
if (i === index) {
el.scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'center' });
el.scrollIntoView({ behavior: 'smooth', block: 'center', inline: 'nearest' });
}
});
}
@@ -1321,14 +1331,15 @@ export async function showImageWorkbench(owner, sourceImage, imageUrl, options =
zoomBar.append(fitBtn, actualBtn, zoomOutBtn, zoomInBtn);
stageArea.appendChild(zoomBar);
// Bottom Filmstrip
// 4A. Left Vertical Filmstrip Rail
const filmstripRail = buildFilmstripRail(items, currentIndex, (idx) => loadWorkbenchImage(idx));
wb.filmstripEl = filmstripRail;
stageArea.appendChild(filmstripRail);
bodyContainer.appendChild(filmstripRail);
// 4B. Center Canvas Stage Area
bodyContainer.appendChild(stageArea);
// 4B. Right Inspector Panel
// 4C. Right Inspector Panel
const inspector = document.createElement('div');
inspector.className = 'anomalous-workbench-inspector';
+76 -30
View File
@@ -5556,10 +5556,10 @@ dialog.anomalous-gallery-viewer::backdrop {
transform: scale(1.05);
}
/* Main Body: Stage Area + Inspector */
/* Main Body: Left Thumbnail Rail + Center Stage Area + Right Inspector */
.anomalous-workbench-body {
display: grid;
grid-template-columns: minmax(0, 1.45fr) minmax(460px, 0.95fr);
grid-template-columns: auto minmax(0, 1.45fr) minmax(460px, 0.95fr);
flex: 1;
min-height: 0;
overflow: hidden;
@@ -5635,7 +5635,7 @@ dialog.anomalous-gallery-viewer::backdrop {
/* Floating Zoom Bar */
.anomalous-workbench-zoom-bar {
position: absolute;
bottom: 86px;
bottom: 18px;
right: 18px;
z-index: 12;
display: flex;
@@ -5666,45 +5666,69 @@ dialog.anomalous-gallery-viewer::backdrop {
color: #fff;
}
/* Bottom Filmstrip Rail */
/* Left Filmstrip Rail */
.anomalous-workbench-filmstrip {
flex: 0 0 82px;
height: 82px;
padding: 8px 16px;
border-top: 1px solid rgba(255, 255, 255, 0.08);
background: #0b0d13;
overflow-x: auto;
overflow-y: hidden;
transition: all 0.22s cubic-bezier(0.16, 1, 0.3, 1);
width: 116px;
height: 100%;
min-height: 0;
padding: 12px 10px;
border-right: 1px solid rgba(255, 255, 255, 0.08);
background: #080a0f;
overflow-x: hidden;
overflow-y: auto;
box-sizing: border-box;
transition: width 0.22s cubic-bezier(0.16, 1, 0.3, 1),
padding 0.22s cubic-bezier(0.16, 1, 0.3, 1),
opacity 0.18s ease;
}
.anomalous-workbench-filmstrip.is-hidden {
flex: 0 0 0px;
height: 0px;
padding: 0;
border-top: none;
overflow: hidden;
opacity: 0;
width: 0 !important;
min-width: 0 !important;
padding: 0 !important;
border-right: none !important;
overflow: hidden !important;
opacity: 0 !important;
pointer-events: none !important;
}
.anomalous-workbench-filmstrip::-webkit-scrollbar {
width: 4px;
}
.anomalous-workbench-filmstrip::-webkit-scrollbar-track {
background: transparent;
}
.anomalous-workbench-filmstrip::-webkit-scrollbar-thumb {
background: rgba(255, 255, 255, 0.14);
border-radius: 4px;
}
.anomalous-workbench-filmstrip::-webkit-scrollbar-thumb:hover {
background: rgba(45, 212, 191, 0.45);
}
.anomalous-workbench-filmstrip-track {
display: flex;
flex-direction: column;
align-items: center;
gap: 10px;
height: 100%;
gap: 12px;
width: 100%;
}
.anomalous-workbench-filmstrip-thumb {
position: relative;
flex: 0 0 64px;
width: 64px;
height: 64px;
border-radius: 8px;
flex: 0 0 92px;
width: 92px;
height: 92px;
border-radius: 10px;
overflow: hidden;
border: 2px solid rgba(255, 255, 255, 0.1);
background: #141720;
background: #12151e;
cursor: pointer;
transition: all 0.18s cubic-bezier(0.16, 1, 0.3, 1);
box-sizing: border-box;
transition: border-color 0.18s ease, transform 0.18s cubic-bezier(0.16, 1, 0.3, 1), box-shadow 0.18s ease;
}
.anomalous-workbench-filmstrip-thumb img {
@@ -5715,14 +5739,36 @@ dialog.anomalous-gallery-viewer::backdrop {
}
.anomalous-workbench-filmstrip-thumb:hover {
border-color: rgba(255, 255, 255, 0.35);
transform: translateY(-2px);
border-color: rgba(255, 255, 255, 0.45);
transform: scale(1.04);
}
.anomalous-workbench-filmstrip-thumb.is-active {
border-color: #2dd4bf;
box-shadow: 0 0 14px rgba(45, 212, 191, 0.5);
transform: scale(1.06);
box-shadow: 0 0 16px rgba(45, 212, 191, 0.55), inset 0 0 0 1px #2dd4bf;
transform: scale(1.04);
}
.anomalous-workbench-thumb-index {
position: absolute;
bottom: 4px;
right: 4px;
font-size: 10px;
font-weight: 700;
line-height: 1;
color: #94a3b8;
background: rgba(10, 13, 20, 0.82);
backdrop-filter: blur(4px);
padding: 2px 5px;
border-radius: 4px;
pointer-events: none;
transition: color 0.15s, background 0.15s;
}
.anomalous-workbench-filmstrip-thumb.is-active .anomalous-workbench-thumb-index {
color: #2dd4bf;
background: rgba(13, 23, 27, 0.92);
font-weight: 800;
}
/* Right Inspector Panel */