Gallery Layout Refactor: Remove buttons and modernize grid

This commit is contained in:
DemonGatanjieu
2026-08-06 20:45:44 +08:00
parent 23f4dbb05b
commit ea6f3c43ab
3 changed files with 38 additions and 47 deletions
+1
View File
@@ -8,6 +8,7 @@
- **Node Cards & Smart Expansion**: Each node's parameters are wrapped in a styled card (`.anomalous-recipe-detail-parameter-node`). The inner widgets use a responsive grid layout to eliminate vertical cramming. Overly long nodes automatically collapse to a maximum height (`is-collapsed`) with a smooth gradient mask and a bottom expand button.
- **Hero Image Gallery (Plan B)**: Replaced the bottom inline gallery section with a prominent Hero Section (`.anomalous-recipe-detail-hero`) at the top. The first generated image acts as a large cover banner.
- **Modal Gallery Viewer**: If a recipe has multiple generated images, a sleek glassmorphism button overlay appears on the hero image (e.g., `🖼️ 图库 (5)`). Clicking it opens a native HTML `<dialog>` containing the full gallery grid, preventing the parameter view from bloating vertically while keeping the core browsing experience focused.
- **Gallery Grid Refactor**: Removed the cluttered action buttons ("Set Cover", "Compare", "View Image") from all gallery cards across the application. Gallery grids now use a sleek, uniform responsive layout (`aspect-ratio: 1`, `object-fit: cover`) with a subtle hover zoom effect, relying on a direct click to view the original image.
**Validation**
+2 -47
View File
@@ -1806,15 +1806,8 @@ function renderRecipeParameters(content, owner, recipe, gallery, refreshGallery,
const image = document.createElement('img');
image.src = url;
image.loading = 'lazy';
image.onclick = () => { void showGalleryComparison(card, owner, sourceImage); };
image.onclick = () => owner.showGalleryViewer?.(url);
card.appendChild(image);
const actions = document.createElement('div');
actions.className = 'anomalous-recipe-gallery-card-actions';
const viewBtn = button(actions, t('recipeGalleryOpenImage'), 'anomalous-btn-ghost');
viewBtn.onclick = () => owner.showGalleryViewer?.(url);
const compareBtn = button(actions, t('recipeGalleryCompare'), 'anomalous-btn-ghost');
compareBtn.onclick = () => { void showGalleryComparison(card, owner, sourceImage); };
card.appendChild(actions);
grid.appendChild(card);
}
dialog.appendChild(grid);
@@ -2008,46 +2001,8 @@ function renderRecipeGallery(content, owner, recipe, gallery, refresh) {
image.src = url;
image.alt = t('recipeGalleryOpenImage');
image.loading = 'lazy';
image.onclick = () => { void showGalleryComparison(card, owner, sourceImage); };
image.onclick = () => owner.showGalleryViewer?.(url);
card.appendChild(image);
const actions = document.createElement('div');
actions.className = 'anomalous-recipe-gallery-card-actions';
const viewImage = button(actions, t('recipeGalleryOpenImage'), 'anomalous-btn-ghost');
viewImage.onclick = (event) => {
event.stopPropagation();
owner.showGalleryViewer?.(url);
};
const compare = button(actions, t('recipeGalleryCompare'), 'anomalous-btn-ghost');
compare.onclick = (event) => {
event.stopPropagation();
void showGalleryComparison(card, owner, sourceImage);
};
const setCover = button(actions, t('recipeGallerySetCover'), 'anomalous-btn-primary');
setCover.onclick = (event) => {
event.stopPropagation();
void runRecipeAction(setCover, async () => {
const response = await fetch('/anomalous/set_recipe_gallery_cover', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ filename: owner.recipeDetailFilename, source_image: sourceImage }),
});
if (!response.ok) throw new Error('recipe gallery cover update failed');
const payload = await response.json();
recipe.source_image = payload.source_image || sourceImage;
recipe.thumbnail = null;
recipe.presentation = {
...(recipe.presentation || {}),
cover_asset_id: payload.cover?.asset_id,
};
if (payload.workflow_fingerprint) recipe.workflow_fingerprint = payload.workflow_fingerprint;
await owner.refreshRecipes();
setCover.textContent = t('recipeGalleryCoverSaved');
}).catch(async (error) => {
console.error('Could not set recipe gallery cover:', error);
await anomalousAlert(t('recipeGalleryCoverError'));
});
};
card.appendChild(actions);
grid.appendChild(card);
}
section.appendChild(grid);
+35
View File
@@ -3127,3 +3127,38 @@
border-radius: 50%;
cursor: pointer;
}
/* Gallery Grid Refactor */
.anomalous-recipe-gallery-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
gap: 16px;
padding: 16px 0;
}
.anomalous-recipe-gallery-card {
position: relative;
border-radius: 8px;
overflow: hidden;
background: rgba(0, 0, 0, 0.2);
aspect-ratio: 1;
transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.anomalous-recipe-gallery-card:hover {
transform: scale(1.03);
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.4);
z-index: 2;
}
.anomalous-recipe-gallery-card img {
width: 100%;
height: 100%;
object-fit: cover;
display: block;
cursor: pointer;
}
.anomalous-recipe-gallery-card-actions {
display: none !important;
}