diff --git a/static/css/components/recipe-modal.css b/static/css/components/recipe-modal.css index 912a595c..0d5fa3b5 100644 --- a/static/css/components/recipe-modal.css +++ b/static/css/components/recipe-modal.css @@ -4,6 +4,20 @@ justify-content: flex-start; align-items: flex-start; border-bottom: 1px solid var(--lora-border); + padding-bottom: 10px; + margin-bottom: 10px; +} + +.recipe-modal-header h2 { + font-size: 1.4em; /* Reduced from default h2 size */ + line-height: 1.3; + margin: 0; + max-height: 2.6em; /* Limit to 2 lines */ + overflow: hidden; + text-overflow: ellipsis; + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; } /* Recipe Tags styles */ @@ -304,6 +318,10 @@ border: 1px solid var(--border-color); border-radius: var(--border-radius-sm); background: var(--bg-color); + /* Add will-change to create a new stacking context and force hardware acceleration */ + will-change: transform; + /* Create a new containing block for absolutely positioned descendants */ + transform: translateZ(0); } .recipe-lora-item.exists-locally { @@ -343,6 +361,10 @@ align-items: flex-start; justify-content: space-between; gap: var(--space-2); + position: relative; + min-height: 28px; + /* Ensure badges don't move during scroll in Chrome */ + transform: translateZ(0); } .recipe-lora-content h4 { @@ -350,6 +372,13 @@ font-size: 1em; color: var(--text-color); flex: 1; + max-width: calc(100% - 120px); /* Make room for the badge */ + overflow: hidden; + text-overflow: ellipsis; + display: -webkit-box; + -webkit-line-clamp: 2; /* Limit to 2 lines */ + -webkit-box-orient: vertical; + line-height: 1.3; } .recipe-lora-info { @@ -358,6 +387,8 @@ gap: 8px; align-items: center; font-size: 0.85em; + margin-top: 4px; + padding-right: 4px; } .recipe-lora-info .base-model { @@ -381,6 +412,33 @@ color: var(--lora-accent); } +.local-badge, +.missing-badge { + position: absolute; + right: 0; + top: 0; + /* Force hardware acceleration for Chrome */ + transform: translateZ(0); + backface-visibility: hidden; +} + +/* Specific styles for recipe modal badges - update z-index */ +.recipe-lora-header .local-badge, +.recipe-lora-header .missing-badge { + z-index: 2; /* Ensure the badge is above other elements */ + backface-visibility: hidden; +} + +/* Ensure local-path tooltip is properly positioned and won't move during scroll */ +.recipe-lora-header .local-badge .local-path { + z-index: 3; + top: calc(100% + 4px); /* Position tooltip below the badge */ + right: -4px; /* Align with the badge */ + max-width: 250px; + /* Force hardware acceleration for Chrome */ + transform: translateZ(0); +} + .missing-badge { display: inline-flex; align-items: center; @@ -414,3 +472,26 @@ max-height: 300px; } } + +.badge-container { + position: relative; + display: flex; + align-items: center; + justify-content: flex-end; + flex-shrink: 0; + min-width: 110px; + z-index: 2; +} + +/* Update the local-badge and missing-badge to be positioned within the badge-container */ +.badge-container .local-badge, +.badge-container .missing-badge { + position: static; /* Override absolute positioning */ + transform: none; /* Remove the transform */ +} + +/* Ensure the tooltip is still properly positioned */ +.badge-container .local-badge .local-path { + position: fixed; /* Keep as fixed for Chrome */ + z-index: 100; +} diff --git a/static/css/components/shared.css b/static/css/components/shared.css index 1c7965a8..d1ba7c3f 100644 --- a/static/css/components/shared.css +++ b/static/css/components/shared.css @@ -11,6 +11,9 @@ white-space: nowrap; flex-shrink: 0; position: relative; + /* Force hardware acceleration to prevent Chrome scroll issues */ + transform: translateZ(0); + will-change: transform; } .local-badge i { @@ -33,13 +36,19 @@ white-space: normal; word-break: break-all; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); - z-index: 1; + z-index: 100; /* Higher z-index to ensure it's above other elements */ min-width: 200px; max-width: 300px; + /* Create a separate layer with hardware acceleration */ + transform: translateZ(0); + /* Use a fixed position to ensure it's in a separate layer from scrollable content */ + position: fixed; + pointer-events: none; /* Don't block mouse events */ } .local-badge:hover .local-path { display: block; + pointer-events: auto; /* Allow interaction with the tooltip when visible */ } .error-message { diff --git a/static/js/components/RecipeCard.js b/static/js/components/RecipeCard.js index d281e461..ef332ada 100644 --- a/static/js/components/RecipeCard.js +++ b/static/js/components/RecipeCard.js @@ -215,10 +215,7 @@ class RecipeCard { .then(data => { showToast('Recipe deleted successfully', 'success'); - // Refresh the recipe list if we're on the recipes page - if (window.recipeManager && typeof window.recipeManager.loadRecipes === 'function') { - window.recipeManager.loadRecipes(); - } + window.recipeManager.loadRecipes(); modalManager.closeModal('deleteModal'); }) diff --git a/static/js/components/RecipeModal.js b/static/js/components/RecipeModal.js index c2d9c554..5f586827 100644 --- a/static/js/components/RecipeModal.js +++ b/static/js/components/RecipeModal.js @@ -8,6 +8,30 @@ class RecipeModal { init() { this.setupCopyButtons(); + // Set up tooltip positioning handlers after DOM is ready + document.addEventListener('DOMContentLoaded', () => { + this.setupTooltipPositioning(); + }); + } + + // Add tooltip positioning handler to ensure correct positioning of fixed tooltips + setupTooltipPositioning() { + document.addEventListener('mouseover', (event) => { + // Check if we're hovering over a local-badge + if (event.target.closest('.local-badge')) { + const badge = event.target.closest('.local-badge'); + const tooltip = badge.querySelector('.local-path'); + + if (tooltip) { + // Get badge position + const badgeRect = badge.getBoundingClientRect(); + + // Position the tooltip + tooltip.style.top = (badgeRect.bottom + 4) + 'px'; + tooltip.style.left = (badgeRect.right - tooltip.offsetWidth) + 'px'; + } + } + }, true); } showRecipeDetails(recipe) { @@ -178,7 +202,7 @@ class RecipeModal { const existsLocally = lora.inLibrary; const localPath = lora.localPath || ''; - // Create local status badge + // Create local status badge with a more stable structure const localStatus = existsLocally ? `
In Library @@ -196,13 +220,13 @@ class RecipeModal {

${lora.modelName}

- ${localStatus} +
${localStatus}
${lora.modelVersionName ? `
${lora.modelVersionName}
` : ''}
Weight: ${lora.strength || 1.0}
+ ${lora.baseModel ? `
${lora.baseModel}
` : ''}
- ${lora.baseModel ? `
${lora.baseModel}
` : ''}
`; diff --git a/static/js/recipes.js b/static/js/recipes.js index 1ece749a..39c2d1f7 100644 --- a/static/js/recipes.js +++ b/static/js/recipes.js @@ -112,8 +112,6 @@ class RecipeManager { params.append('tags', this.pageState.filters.tags.join(',')); } - console.log('Loading recipes with params:', params.toString()); - // Fetch recipes const response = await fetch(`/api/recipes?${params.toString()}`); @@ -123,8 +121,6 @@ class RecipeManager { const data = await response.json(); - console.log('Recipes data:', data); - // Update recipes grid this.updateRecipesGrid(data, resetPage);