feat(model-modal): improve transition animations and fix navigation logic

- Add `!important` to overlay background and closing opacity for consistent styling
- Remove navigation spam prevention to allow consecutive transitions
- Implement in-place content updates during model transitions instead of reopening modal
- Add opacity transitions for showcase and metadata components
- Fetch complete Civitai metadata during transitions for updated model data
This commit is contained in:
Will Miao
2026-02-07 10:20:05 +08:00
parent 66e9d77c67
commit 26884630d3
2 changed files with 39 additions and 13 deletions

View File

@@ -7,12 +7,12 @@
right: 0;
bottom: 0;
z-index: var(--z-modal, 1000);
display: grid;
grid-template-columns: 1.2fr 0.8fr;
gap: 0;
background: var(--bg-color);
background: var(--bg-color) !important;
opacity: 0;
animation: modalOverlayFadeIn 0.25s ease-out forwards;
}
@@ -32,6 +32,7 @@
}
.model-overlay.closing {
opacity: 1 !important;
animation: modalOverlayFadeOut 0.2s ease-out forwards;
}
@@ -154,8 +155,13 @@ body.modal-open {
}
/* Transition effect for content when switching models */
.showcase,
.metadata {
opacity: 1;
transition: opacity 0.15s ease-out;
}
.showcase.transitioning,
.metadata.transitioning {
opacity: 0;
transition: opacity 0.15s ease-out;
}

View File

@@ -31,9 +31,6 @@ export class ModelModal {
* @param {string} modelType - Type of model ('loras', 'checkpoints', 'embeddings')
*/
static async show(model, modelType) {
// Prevent navigation spam
if (this.isNavigating) return;
// If already open, animate transition to new model
if (this.isOpen()) {
await this.transitionToModel(model, modelType);
@@ -151,8 +148,12 @@ export class ModelModal {
* Transition to a different model with animation
*/
static async transitionToModel(model, modelType) {
if (this.isNavigating) return;
this.isNavigating = true;
// Ensure components are initialized
if (!this.showcase || !this.metadataPanel) {
console.warn('Showcase or MetadataPanel not initialized, falling back to show()');
await this.show(model, modelType);
return;
}
// Fade out current content
this.showcase?.element?.classList.add('transitioning');
@@ -160,11 +161,30 @@ export class ModelModal {
await new Promise(resolve => setTimeout(resolve, 150));
// Close and reopen with new model
this.close(false); // Don't remove overlay immediately
await this.show(model, modelType);
// Fetch complete metadata for new model
let completeCivitaiData = model.civitai || {};
if (model.file_path) {
try {
const fullMetadata = await getModelApiClient().fetchModelMetadata(model.file_path);
completeCivitaiData = fullMetadata || model.civitai || {};
} catch (error) {
console.warn('Failed to fetch complete metadata:', error);
}
}
this.isNavigating = false;
// Update model data in-place
this.currentModel = {
...model,
civitai: completeCivitaiData
};
this.currentModelType = modelType;
// Render new content in-place
await this.render();
// Fade in new content
this.showcase?.element?.classList.remove('transitioning');
this.metadataPanel?.element?.classList.remove('transitioning');
}
/**