feat(ui): enhance model card header with sub-type display and gradient overlay

- Add gradient overlay to card header for better icon readability
- Update base model label to display sub-type abbreviation alongside base model
- Add separator between sub-type and base model for visual clarity
- Improve label styling with flex layout, adjusted padding, and enhanced backdrop filter
- Add helper functions for sub-type abbreviation retrieval and display names
This commit is contained in:
Will Miao
2026-01-30 09:46:31 +08:00
parent 84c62f2954
commit 233427600a
3 changed files with 71 additions and 8 deletions

View File

@@ -296,6 +296,19 @@
min-height: 20px; min-height: 20px;
} }
/* Gradient overlay on right side for icon readability */
.card-header::after {
content: '';
position: absolute;
top: 0;
right: 0;
width: 100px;
height: 100%;
background: linear-gradient(to left, oklch(0% 0 0 / 0.4) 0%, transparent 100%);
pointer-events: none;
border-top-right-radius: var(--border-radius);
}
.card-header-info { .card-header-info {
display: flex; display: flex;
align-items: center; align-items: center;
@@ -426,15 +439,39 @@
white-space: nowrap; white-space: nowrap;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
display: inline-block; display: inline-flex;
align-items: center;
gap: 4px;
color: white; color: white;
text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5); text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5);
background: rgba(255, 255, 255, 0.2); background: rgba(255, 255, 255, 0.12);
padding: 2px var(--space-1); padding: 2px 6px;
border-radius: var(--border-radius-xs); border-radius: var(--border-radius-xs);
backdrop-filter: blur(2px); backdrop-filter: blur(4px);
font-size: 0.85em; font-size: 0.8em;
line-height: 1.2; line-height: 1.2;
font-weight: 500;
}
/* Subtle separator between sub-type and base model */
.model-separator {
width: 1px;
height: 0.6em;
background: rgba(255, 255, 255, 0.25);
flex-shrink: 0;
}
/* Sub-type abbreviation styling */
.model-sub-type {
opacity: 0.9;
flex-shrink: 0;
}
/* Base model abbreviation styling */
.model-base-type {
flex-shrink: 1;
overflow: hidden;
text-overflow: ellipsis;
} }
/* Style for version name */ /* Style for version name */

View File

@@ -4,7 +4,7 @@ import { showModelModal } from './ModelModal.js';
import { toggleShowcase } from './showcase/ShowcaseView.js'; import { toggleShowcase } from './showcase/ShowcaseView.js';
import { bulkManager } from '../../managers/BulkManager.js'; import { bulkManager } from '../../managers/BulkManager.js';
import { modalManager } from '../../managers/ModalManager.js'; import { modalManager } from '../../managers/ModalManager.js';
import { NSFW_LEVELS, getBaseModelAbbreviation } from '../../utils/constants.js'; import { NSFW_LEVELS, getBaseModelAbbreviation, getSubTypeAbbreviation, MODEL_SUBTYPE_DISPLAY_NAMES } from '../../utils/constants.js';
import { MODEL_TYPES } from '../../api/apiConfig.js'; import { MODEL_TYPES } from '../../api/apiConfig.js';
import { getModelApiClient } from '../../api/modelApiFactory.js'; import { getModelApiClient } from '../../api/modelApiFactory.js';
import { showDeleteModal } from '../../utils/modalUtils.js'; import { showDeleteModal } from '../../utils/modalUtils.js';
@@ -580,6 +580,11 @@ export function createModelCard(model, modelType) {
const baseModelLabel = model.base_model || 'Unknown'; const baseModelLabel = model.base_model || 'Unknown';
const baseModelAbbreviation = getBaseModelAbbreviation(baseModelLabel); const baseModelAbbreviation = getBaseModelAbbreviation(baseModelLabel);
// Sub-type display (e.g., LoRA, LyCO, DoRA, CKPT, DM, EMB)
const subType = model.sub_type || '';
const subTypeAbbreviation = getSubTypeAbbreviation(subType);
const fullSubTypeName = MODEL_SUBTYPE_DISPLAY_NAMES[subType?.toLowerCase()] || subType || '';
card.innerHTML = ` card.innerHTML = `
<div class="card-preview ${shouldBlur ? 'blurred' : ''}"> <div class="card-preview ${shouldBlur ? 'blurred' : ''}">
${isVideo ? ${isVideo ?
@@ -592,8 +597,11 @@ export function createModelCard(model, modelType) {
<i class="fas fa-eye"></i> <i class="fas fa-eye"></i>
</button>` : ''} </button>` : ''}
<div class="card-header-info"> <div class="card-header-info">
<span class="base-model-label ${shouldBlur ? 'with-toggle' : ''}" title="${baseModelLabel}"> <span class="base-model-label ${shouldBlur ? 'with-toggle' : ''}"
${baseModelAbbreviation} title="${fullSubTypeName ? fullSubTypeName + ' | ' : ''}${baseModelLabel}">
${subTypeAbbreviation ? `<span class="model-sub-type">${subTypeAbbreviation}</span>` : ''}
${subTypeAbbreviation ? `<span class="model-separator"></span>` : ''}
<span class="model-base-type">${baseModelAbbreviation}</span>
</span> </span>
${hasUpdateAvailable ? ` ${hasUpdateAvailable ? `
<span class="model-update-badge" title="${updateBadgeTooltip}"> <span class="model-update-badge" title="${updateBadgeTooltip}">

View File

@@ -73,6 +73,24 @@ export const MODEL_SUBTYPE_DISPLAY_NAMES = {
// Backward compatibility alias // Backward compatibility alias
export const MODEL_TYPE_DISPLAY_NAMES = MODEL_SUBTYPE_DISPLAY_NAMES; export const MODEL_TYPE_DISPLAY_NAMES = MODEL_SUBTYPE_DISPLAY_NAMES;
// Abbreviated sub-type names for compact display (e.g., in model card labels)
export const MODEL_SUBTYPE_ABBREVIATIONS = {
lora: "LoRA",
locon: "LyCO",
dora: "DoRA",
checkpoint: "CKPT",
diffusion_model: "DM",
embedding: "EMB",
};
export function getSubTypeAbbreviation(subType) {
if (!subType || typeof subType !== 'string') {
return '';
}
const normalized = subType.toLowerCase();
return MODEL_SUBTYPE_ABBREVIATIONS[normalized] || subType.toUpperCase().slice(0, 4);
}
export const BASE_MODEL_ABBREVIATIONS = { export const BASE_MODEL_ABBREVIATIONS = {
// Stable Diffusion 1.x models // Stable Diffusion 1.x models
[BASE_MODELS.SD_1_4]: 'SD1', [BASE_MODELS.SD_1_4]: 'SD1',