refactor(dashboard): move controls to overlays and fix mobile/positioning issues
BREAKING CHANGES: - Resize handles and edit controls now render in separate overlay containers - This prevents widget overflow and scrollbar issues Major Changes: Overlay System Refactor: - Create overlay containers for resize handles and edit controls - Append handles/controls to overlays instead of widget DOM - Fix position calculations using offsetLeft/Top instead of getBoundingClientRect - Add position sync after resize/drag/reposition operations - Add cleanup methods when switching tabs Mobile Fixes: - Add pointer/touch event support for Add Widget button - Fix file upload trigger for iOS/Android compatibility - Move modals to document.body with flex centering - Fix modal button font-sizes (rem-based instead of vw) - Add mobile-responsive styling for widget dialog Bug Fixes: - Fix getActiveTabId() calls (use activeTabId property instead) - Fix file input disabled state (exclude type="file" from edit mode disable) - Fix Add Widget modal registry.getAll() destructuring (objects not arrays) - Fix edit/delete button hover (keep visible when hovering buttons) - Fix reset layout to restore deleted widgets (regenerate default layout) UI Improvements: - No more scrollbars from resize handles - Consistent button visibility in edit mode - Touch-friendly button sizes on mobile (44px min-height) - Single-column widget grid on mobile - Proper z-index stacking for overlays Files Changed: - dashboardManager.js: Overlay container management, sync methods - resizeHandler.js: Append to overlay, update positioning - editModeManager.js: Append to overlay, hover behavior, sync/cleanup - dashboardIntegration.js: Mobile touch events, file upload, modal fixes - dashboardTemplate.html: File input accessibility - style.css: Modal button font-sizes, mobile optimizations - RESIZE_HANDLES_INVESTIGATION.md: Technical investigation documentation
This commit is contained in:
@@ -28,6 +28,7 @@ export class ResizeHandler {
|
||||
constructor(gridEngine, options = {}) {
|
||||
this.gridEngine = gridEngine;
|
||||
this.editManager = options.editManager || null; // Reference to EditModeManager for lock state
|
||||
this.resizeHandlesOverlay = options.resizeHandlesOverlay || null; // Overlay container for handles
|
||||
this.options = {
|
||||
showDimensions: true,
|
||||
showGrid: true,
|
||||
@@ -74,7 +75,19 @@ export class ResizeHandler {
|
||||
initWidget(element, widget, onResizeEnd, constraints = {}) {
|
||||
// Create resize handles
|
||||
const handles = this.createResizeHandles();
|
||||
element.appendChild(handles);
|
||||
|
||||
// Store reference to widget element for positioning
|
||||
handles.dataset.widgetId = element.id;
|
||||
|
||||
// Append to overlay instead of widget to prevent overflow/scrollbar issues
|
||||
if (this.resizeHandlesOverlay) {
|
||||
this.resizeHandlesOverlay.appendChild(handles);
|
||||
// Position handles to match widget bounds
|
||||
this.updateHandlePosition(handles, element);
|
||||
} else {
|
||||
// Fallback to old behavior if overlay not available
|
||||
element.appendChild(handles);
|
||||
}
|
||||
|
||||
// Store constraints
|
||||
const widgetConstraints = {
|
||||
@@ -215,6 +228,25 @@ export class ResizeHandler {
|
||||
return container;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update handle container position to match widget bounds
|
||||
* @param {HTMLElement} handles - Resize handles container
|
||||
* @param {HTMLElement} element - Widget element
|
||||
*/
|
||||
updateHandlePosition(handles, element) {
|
||||
if (!handles || !element) return;
|
||||
|
||||
const overlay = this.resizeHandlesOverlay;
|
||||
if (!overlay) return;
|
||||
|
||||
// Use offset properties for parent-relative positioning
|
||||
// Both widget and overlay are children of the same grid container
|
||||
handles.style.left = `${element.offsetLeft}px`;
|
||||
handles.style.top = `${element.offsetTop}px`;
|
||||
handles.style.width = `${element.offsetWidth}px`;
|
||||
handles.style.height = `${element.offsetHeight}px`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start resize operation
|
||||
* @param {MouseEvent|Touch} e - Pointer event
|
||||
@@ -416,6 +448,12 @@ export class ResizeHandler {
|
||||
onResizeEnd(widget, widget.w, widget.h, widget.x, widget.y);
|
||||
}
|
||||
|
||||
// Update handle positions to match new widget size
|
||||
const handlerData = this.resizeHandlers.get(element);
|
||||
if (handlerData && handlerData.handles) {
|
||||
this.updateHandlePosition(handlerData.handles, element);
|
||||
}
|
||||
|
||||
this.cleanup();
|
||||
console.log('[ResizeHandler] Resize completed:', widget.id, `${widget.w}×${widget.h} at (${widget.x}, ${widget.y})`);
|
||||
}
|
||||
@@ -445,6 +483,12 @@ export class ResizeHandler {
|
||||
// Remove resizing class
|
||||
element.classList.remove('resizing');
|
||||
|
||||
// Update handle positions to match restored widget size
|
||||
const handlerData = this.resizeHandlers.get(element);
|
||||
if (handlerData && handlerData.handles) {
|
||||
this.updateHandlePosition(handlerData.handles, element);
|
||||
}
|
||||
|
||||
this.cleanup();
|
||||
console.log('[ResizeHandler] Resize cancelled');
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user