diff --git a/static/css/components/duplicates.css b/static/css/components/duplicates.css index 2372ed64..9456e3fb 100644 --- a/static/css/components/duplicates.css +++ b/static/css/components/duplicates.css @@ -17,12 +17,13 @@ } .duplicates-banner .banner-content { - max-width: 1400px; /* Match the container max-width */ + position: relative; + max-width: 1400px; margin: 0 auto; display: flex; align-items: center; gap: 12px; - padding: 0 16px; /* Move horizontal padding to the content */ + padding: 0 16px; } /* Responsive container for larger screens - match container in layout.css */ @@ -122,6 +123,23 @@ margin-bottom: 24px; background: var(--card-bg); box-shadow: 0 2px 6px rgba(0, 0, 0, 0.12); /* Add subtle shadow to groups */ + /* Add responsive width settings to match banner */ + max-width: 1400px; + margin-left: auto; + margin-right: auto; +} + +/* Add responsive container adjustments for duplicate groups - match container in banner */ +@media (min-width: 2000px) { + .duplicate-group { + max-width: 1800px; + } +} + +@media (min-width: 3000px) { + .duplicate-group { + max-width: 2400px; + } } .duplicate-group-header { @@ -345,6 +363,49 @@ } } +/* Help icon styling */ +.help-icon { + color: var(--text-color); + opacity: 0.7; + cursor: help; + font-size: 16px; + margin-left: 8px; + transition: all 0.2s ease; +} + +.help-icon:hover { + opacity: 1; + color: oklch(var(--lora-accent-l) var(--lora-accent-c) var(--lora-accent-h)); +} + +/* Help tooltip */ +.help-tooltip { + display: none; + position: absolute; + max-width: 400px; + background: var(--card-bg); + color: var(--text-color); + border: 1px solid var(--border-color); + border-radius: var(--border-radius-sm); + padding: 12px 16px; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); + z-index: var(--z-overlay); + font-size: 0.9em; + margin-top: 10px; + text-align: left; + pointer-events: none; +} + +.help-tooltip:after { + content: ""; + position: absolute; + top: -8px; + left: 10px; /* Position the arrow near the left instead of center */ + border-width: 0 8px 8px 8px; + border-style: solid; + border-color: transparent transparent var(--card-bg) transparent; +} + /* Responsive adjustments */ @media (max-width: 768px) { .duplicates-banner .banner-content { @@ -375,6 +436,15 @@ margin-left: 0; flex: 1; } + + .help-tooltip { + max-width: calc(100% - 40px); + } + + /* Remove the fixed positioning adjustments for mobile since we're now using dynamic positioning */ + .help-tooltip:after { + left: 10px; + } } /* In dark mode, add additional distinction */ @@ -387,6 +457,10 @@ html[data-theme="dark"] .duplicate-group { box-shadow: 0 2px 8px rgba(0, 0, 0, 0.25); /* Stronger shadow in dark mode */ } +html[data-theme="dark"] .help-tooltip { + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3); +} + /* Styles for disabled controls during duplicates mode */ .disabled-during-duplicates { opacity: 0.5 !important; diff --git a/static/js/components/ModelDuplicatesManager.js b/static/js/components/ModelDuplicatesManager.js index f0a9b2e1..bb416b86 100644 --- a/static/js/components/ModelDuplicatesManager.js +++ b/static/js/components/ModelDuplicatesManager.js @@ -123,6 +123,9 @@ export class ModelDuplicatesManager { if (banner && countSpan) { countSpan.textContent = `Found ${this.duplicateGroups.length} duplicate group${this.duplicateGroups.length !== 1 ? 's' : ''}`; banner.style.display = 'block'; + + // Setup help tooltip behavior + this.setupHelpTooltip(); } // Disable virtual scrolling if active @@ -551,4 +554,46 @@ export class ModelDuplicatesManager { // Use this method after refresh operations this.checkDuplicatesCount(); } + + // Add this new method for tooltip behavior + setupHelpTooltip() { + const helpIcon = document.getElementById('duplicatesHelp'); + const helpTooltip = document.getElementById('duplicatesHelpTooltip'); + + if (!helpIcon || !helpTooltip) return; + + helpIcon.addEventListener('mouseenter', (e) => { + // Get the container's positioning context + const bannerContent = helpIcon.closest('.banner-content'); + + // Get positions relative to the viewport + const iconRect = helpIcon.getBoundingClientRect(); + const bannerRect = bannerContent.getBoundingClientRect(); + + // Set initial position relative to the banner content + helpTooltip.style.display = 'block'; + helpTooltip.style.top = `${iconRect.bottom - bannerRect.top + 10}px`; + helpTooltip.style.left = `${iconRect.left - bannerRect.left - 10}px`; + + // Check if the tooltip is going off-screen to the right + const tooltipRect = helpTooltip.getBoundingClientRect(); + const viewportWidth = window.innerWidth; + + if (tooltipRect.right > viewportWidth - 20) { + // Reposition relative to container if too close to right edge + helpTooltip.style.left = `${bannerContent.offsetWidth - tooltipRect.width - 20}px`; + } + }); + + // Rest of the event listeners remain unchanged + helpIcon.addEventListener('mouseleave', () => { + helpTooltip.style.display = 'none'; + }); + + document.addEventListener('click', (e) => { + if (!helpIcon.contains(e.target)) { + helpTooltip.style.display = 'none'; + } + }); + } } diff --git a/templates/checkpoints.html b/templates/checkpoints.html index 702b6b95..e8ebce2d 100644 --- a/templates/checkpoints.html +++ b/templates/checkpoints.html @@ -37,6 +37,7 @@
+Identical hashes mean identical model files, even if they have different names or previews.
+Keep only one version (preferably with better metadata/previews) and safely delete the others.
+Identical hashes mean identical model files, even if they have different names or previews.
+Keep only one version (preferably with better metadata/previews) and safely delete the others.
+