feat: refactor info panel hover expansion with CSS classes and prevent bottom screen overflow

This commit is contained in:
AEmotionStudio
2026-01-02 12:57:06 -08:00
parent 404e1098b9
commit 1aa53b9f95
4 changed files with 56 additions and 28 deletions
+30 -11
View File
@@ -82,19 +82,41 @@ export class UIManager {
}
document.body.appendChild(this.elements.panel);
// Hover-expand: Remove inline max-height on hover to show all content
// Hover-expand: Add/remove 'is-expanded' class and reposition for full content
let originalTop: number | null = null;
this.elements.panel.addEventListener('mouseenter', () => {
if (!this.stateManager.state.isPanelMinimized && this.elements.panel) {
this.elements.panel.style.maxHeight = 'none';
this.elements.panel.style.overflow = 'visible';
// Save original position
originalTop = this.elements.panel.offsetTop;
// Add expanded class
this.elements.panel.classList.add('is-expanded');
// After a short delay, check if panel extends below viewport and adjust
requestAnimationFrame(() => {
if (!this.elements.panel) return;
const rect = this.elements.panel.getBoundingClientRect();
const bottomOverflow = rect.bottom - window.innerHeight;
if (bottomOverflow > 0) {
// Panel extends below viewport - move it up
const newTop = Math.max(10, originalTop! - bottomOverflow - 10);
this.elements.panel.style.top = `${newTop}px`;
}
});
}
});
this.elements.panel.addEventListener('mouseleave', () => {
if (this.elements.panel) {
const maxHeight = this.stateManager.state.settings["🔍MagnifyGlass.InfoPanelMaxHeight"];
this.elements.panel.style.maxHeight = `${maxHeight}px`;
this.elements.panel.style.overflow = '';
this.elements.panel.classList.remove('is-expanded');
// Restore original position
if (originalTop !== null) {
this.elements.panel.style.top = `${originalTop}px`;
originalTop = null;
}
}
});
@@ -358,13 +380,10 @@ export class UIManager {
// 1. Apply dimensions
this.elements.panel.style.width = `${settings["🔍MagnifyGlass.InfoPanelWidth"]}px`;
// Set height to auto so panel grows with content, up to max-height
// Skip max-height if panel is hovered (allow full expansion)
// Set max-height via CSS variable so CSS :hover rules can override
const maxHeight = settings["🔍MagnifyGlass.InfoPanelMaxHeight"];
this.elements.panel.style.setProperty('--panel-max-height', `${maxHeight}px`);
this.elements.panel.style.height = 'auto';
if (!this.stateManager.state.isPanelHovered) {
this.elements.panel.style.maxHeight = `${maxHeight}px`;
}
// 2. Apply static styles (only needed once or if overwritten, but safe to set)
this.elements.panel.style.position = 'absolute';
+7 -8
View File
@@ -46,7 +46,7 @@
border-radius: 12px;
backdrop-filter: blur(20px);
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.3), 0 0 0 1px rgba(255, 255, 255, 0.1);
overflow: hidden;
overflow: visible;
font-size: 16px;
line-height: 1.6;
pointer-events: auto;
@@ -178,15 +178,15 @@
transition: max-height 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}
/* Hover-expand: Temporarily remove max-height limit when hovering to show all content */
.magnify-info-panel:hover:not(.panel-minimized) {
/* Hover-expand: Show ALL content at once - no scrollbar, full expansion */
.magnify-info-panel.is-expanded:not(.panel-minimized) {
max-height: none !important;
overflow: visible;
overflow: visible !important;
}
.magnify-info-panel:hover:not(.panel-minimized) .panel-content {
.magnify-info-panel.is-expanded:not(.panel-minimized) .panel-content {
max-height: none !important;
overflow-y: visible;
overflow: visible !important;
}
.floating-controls {
@@ -390,8 +390,7 @@
padding: 0;
flex: 1;
min-height: 0;
overflow-y: auto;
scrollbar-width: thin;
overflow: visible;
}
.panel-content::-webkit-scrollbar {
+18 -8
View File
@@ -47,17 +47,29 @@ class UIManager {
this.elements.panel.classList.add("panel-minimized");
}
document.body.appendChild(this.elements.panel);
let originalTop = null;
this.elements.panel.addEventListener("mouseenter", () => {
if (!this.stateManager.state.isPanelMinimized && this.elements.panel) {
this.elements.panel.style.maxHeight = "none";
this.elements.panel.style.overflow = "visible";
originalTop = this.elements.panel.offsetTop;
this.elements.panel.classList.add("is-expanded");
requestAnimationFrame(() => {
if (!this.elements.panel) return;
const rect = this.elements.panel.getBoundingClientRect();
const bottomOverflow = rect.bottom - window.innerHeight;
if (bottomOverflow > 0) {
const newTop = Math.max(10, originalTop - bottomOverflow - 10);
this.elements.panel.style.top = `${newTop}px`;
}
});
}
});
this.elements.panel.addEventListener("mouseleave", () => {
if (this.elements.panel) {
const maxHeight = this.stateManager.state.settings["🔍MagnifyGlass.InfoPanelMaxHeight"];
this.elements.panel.style.maxHeight = `${maxHeight}px`;
this.elements.panel.style.overflow = "";
this.elements.panel.classList.remove("is-expanded");
if (originalTop !== null) {
this.elements.panel.style.top = `${originalTop}px`;
originalTop = null;
}
}
});
this.elements.panel.addEventListener("click", (e) => {
@@ -237,10 +249,8 @@ class UIManager {
console.log(`[UIManager] applyStyles - MaxHeight: ${settings["🔍MagnifyGlass.InfoPanelMaxHeight"]}`);
this.elements.panel.style.width = `${settings["🔍MagnifyGlass.InfoPanelWidth"]}px`;
const maxHeight = settings["🔍MagnifyGlass.InfoPanelMaxHeight"];
this.elements.panel.style.setProperty("--panel-max-height", `${maxHeight}px`);
this.elements.panel.style.height = "auto";
if (!this.stateManager.state.isPanelHovered) {
this.elements.panel.style.maxHeight = `${maxHeight}px`;
}
this.elements.panel.style.position = "absolute";
this.elements.panel.style.zIndex = "99999";
this.elements.panel.style.transform = "translateY(-10px)";
File diff suppressed because one or more lines are too long