chore: remove investigation documentation file

This commit is contained in:
Lucas 'Paperboy' Rose-Winters
2025-10-29 19:34:18 +11:00
parent 9fbc35dbd9
commit 79d6fcbfe7
-321
View File
@@ -1,321 +0,0 @@
# Resize Handle Overlay Issue - Investigation Report
## Problem Summary
The resize handles in edit mode are being rendered **INSIDE the widget container DOM**, causing:
- Widgets to stretch and overflow their grid bounds
- Scrollbars to appear unexpectedly
- Edit/delete buttons to be hidden or inconsistently visible
- Layout overflow issues
The handles use negative positioning (`top: -6px`, `left: -3px`) to extend outside widget bounds, but being children of the widget element causes them to contribute to the widget's `offsetHeight` and `offsetWidth`, which creates unwanted scrollbars and overflow.
---
## Investigation Findings
### 1. Where Resize Handles Are Created and Appended
**File:** `src/systems/dashboard/resizeHandler.js`
**Key Code (Lines 172-215):**
```javascript
createResizeHandles() {
const container = document.createElement('div');
container.className = 'resize-handles';
container.style.position = 'absolute';
container.style.inset = '0';
container.style.pointerEvents = 'none';
// Create 8 handles (4 corners + 4 edges)
Object.entries(this.handleTypes).forEach(([handleType, cursor]) => {
const handle = document.createElement('div');
handle.className = `resize-handle resize-handle-${handleType}`;
// ... positioning ...
handle.style.top = '-6px'; // Negative positioning
handle.style.left = '-3px'; // Negative positioning
handle.style.zIndex = '100';
container.appendChild(handle);
});
return container;
}
```
**Appended At (Line 77):**
```javascript
initWidget(element, widget, onResizeEnd, constraints = {}) {
const handles = this.createResizeHandles();
element.appendChild(handles); // <-- APPENDED INSIDE WIDGET
// ...
}
```
**Problem:** The handles container is appended directly to the widget element (`element.appendChild(handles)`), making it a child of `.rpg-widget`.
---
### 2. Where Edit/Delete Buttons Are Created
**File:** `src/systems/dashboard/editModeManager.js`
**Key Code (Lines 325-373):**
```javascript
addWidgetControls(element, widgetId) {
const controls = document.createElement('div');
controls.className = 'widget-edit-controls';
controls.style.position = 'absolute';
controls.style.top = '4px';
controls.style.right = '4px';
controls.style.display = 'flex';
controls.style.gap = '4px';
controls.style.zIndex = '100';
controls.style.opacity = '0';
controls.style.transition = 'opacity 0.2s';
// Create settings and delete buttons
const settingsBtn = this.createControlButton('⚙', 'Settings');
const deleteBtn = this.createControlButton('×', 'Delete');
controls.appendChild(settingsBtn);
controls.appendChild(deleteBtn);
element.appendChild(controls); // <-- APPENDED INSIDE WIDGET
// ...
}
```
**Problem:** Like the resize handles, the edit controls are appended inside the widget element as a child.
---
### 3. Current DOM Structure
```
<div class="rpg-widget" id="widget-widget-usermood">
<!-- Widget content (rendered by widget definition) -->
<div class="widget-content">...</div>
<!-- Resize handles INSIDE widget (PROBLEM) -->
<div class="resize-handles" style="position: absolute; inset: 0; pointer-events: none;">
<div class="resize-handle resize-handle-nw" style="top: -6px; left: -3px; ..."></div>
<!-- 7 more handles... -->
</div>
<!-- Edit controls INSIDE widget (PROBLEM) -->
<div class="widget-edit-controls" style="position: absolute; top: 4px; right: 4px; ...">
<button>⚙</button>
<button>×</button>
</div>
</div>
```
**Why This Causes Issues:**
- Even though handles have `position: absolute`, they're still part of the DOM flow calculation
- Negative positioning extends them outside the widget visually, but the browser still includes them in overflow calculations
- This causes scrollbars when the widget container has `overflow: auto` or `overflow: scroll`
- The controls at `top: 4px; right: 4px` with `z-index: 100` can be covered or hidden by other elements
---
### 4. CSS Widget Styling
**File:** `style.css`
**Key Widget CSS:**
```css
.rpg-widget {
box-sizing: border-box;
overflow: visible; /* Allow resize handles to extend beyond widget bounds */
display: flex;
flex-direction: column;
max-height: 100%; /* Prevent content from overflowing grid cell */
/* ... other styles ... */
}
/* Hide resize handles by default */
.resize-handles {
opacity: 0;
pointer-events: none;
transition: opacity 0.2s;
}
/* Show resize handles in edit mode */
.edit-mode .resize-handles {
opacity: 1;
pointer-events: auto;
}
/* Hide resize handles when widgets are locked */
.widgets-locked .resize-handles {
opacity: 0 !important;
pointer-events: none !important;
}
```
**Current State:**
- Widget has `overflow: visible` - correct for allowing handles to show
- But the negative positioning of handles inside the widget still causes layout issues
- The `max-height: 100%` on flex column can cause scrollbars if child heights exceed parent
---
### 5. Why Buttons Are Inconsistently Visible
The edit/delete buttons are positioned inside the widget at `top: 4px; right: 4px;` with `z-index: 100`. Issues arise:
1. **Scrollbars Overlap:** If the widget develops a scrollbar, the buttons are positioned relative to the widget's content box, not the visible area, so they can be hidden by the scrollbar.
2. **Parent Stacking Context:** The widget element's positioning and z-index hierarchy may cause the buttons to be layered differently depending on scroll state.
3. **Hover State Lost:** When scrollbars appear, the widget's visual bounds change, and hover detection may fail to show/hide buttons consistently.
4. **Absolute Positioning Within Scrollable Parent:** Buttons positioned absolutely within a widget that can scroll create unpredictable rendering.
---
## Recommended Approach: Make Handles & Buttons True Overlays
### Strategy
**Move resize handles and edit controls outside the widget DOM to a shared overlay container at the dashboard/grid level.**
**Current (Problematic) Structure:**
```
<div class="rpg-widget">
<widget-content/>
<resize-handles/>
<edit-controls/>
</div>
```
**Target (Fixed) Structure:**
```
<div id="rpg-dashboard-grid">
<div class="rpg-widget">
<widget-content/>
</div>
<div id="rpg-widget-overlays">
<resize-handles for="widget-1"/>
<resize-handles for="widget-2"/>
<edit-controls for="widget-1"/>
<edit-controls for="widget-2"/>
</div>
</div>
```
### Benefits
1. **No DOM Overflow:** Handles and controls are outside widgets, don't contribute to widget dimensions
2. **Clean Widget DOM:** Widgets only contain their actual content
3. **Consistent Visibility:** Overlays are positioned relative to grid container, not affected by widget scrolling
4. **Proper Z-stacking:** True layers with proper z-index control
5. **Easier Positioning:** Overlay containers can be precisely positioned relative to grid, and handles/controls positioned relative to overlay
6. **No Scrollbar Interference:** Buttons and handles won't be hidden by scrollbars
### Implementation Plan
1. **Create overlay container management in DashboardManager:**
- Create and maintain `#rpg-resize-handles-overlay` container
- Create and maintain `#rpg-edit-controls-overlay` container
- Both positioned absolutely, covering entire grid, `pointer-events: none` by default
2. **Modify ResizeHandler:**
- Change `initWidget()` to NOT append handles to widget element
- Instead, create handles and append to `#rpg-resize-handles-overlay`
- Position handles using absolute positioning relative to overlay container
- Calculate positions based on widget's grid position + negative offsets
3. **Modify EditModeManager:**
- Change `addWidgetControls()` to NOT append controls to widget element
- Instead, create controls and append to `#rpg-edit-controls-overlay`
- Position controls using absolute positioning relative to overlay container
- Calculate positions based on widget's grid position
4. **Update repositioning logic:**
- When widgets are repositioned (drag/resize), update overlay child positions
- On tab switch, show/hide overlay child elements for that tab's widgets
- On widget removal, remove corresponding overlay children
5. **CSS updates:**
- Add styles for overlay containers
- Add positioning rules for handles and controls within overlays
---
## Key Files Needing Changes
| File | Change | Impact |
|------|--------|--------|
| `src/systems/dashboard/resizeHandler.js` | Don't append handles to widget; append to overlay instead | Prevents widget overflow |
| `src/systems/dashboard/editModeManager.js` | Don't append controls to widget; append to overlay instead | Fixes button visibility |
| `src/systems/dashboard/dashboardManager.js` | Create/maintain overlay containers; manage overlay children on reposition | Coordinates layout |
| `style.css` | Add overlay container styles; update handle/control positioning | Visual presentation |
---
## CSS Overflow Issue Analysis
**Current `.rpg-widget` CSS:**
```css
.rpg-widget {
overflow: visible; /* Good - allows content overflow */
max-height: 100%; /* Can cause scrollbars if flex children exceed 100% */
display: flex;
flex-direction: column;
}
```
**Why Scrollbars Appear:**
1. Widget has `display: flex; flex-direction: column`
2. Widget has `max-height: 100%`
3. If flex children (content + handles + controls) exceed max-height, scrollbars appear
4. The `overflow: visible` doesn't prevent scrollbars - `max-height` triggers them
**Solution:**
- Moving handles/controls outside widget DOM solves the flex child height problem
- Keep `overflow: visible` for clean content overflow
- Remove or adjust `max-height` constraint
---
## Event Handler Interaction Points
### Resize Handler
- **Source:** `resizeHandler.js`, line 77 in `initWidget()`
- **Current:** Appends handles to widget element
- **Change:** Accept overlay container reference, append there instead
### Drag/Drop Handler
- **Source:** `dragDrop.js`, line 76 checks for `.resize-handle` with `closest()`
- **Impact:** Still works (CSS class-based detection)
- **Change:** None needed - will still detect overlaid handles
### Edit Mode Manager
- **Source:** `editModeManager.js`, lines 325-373 in `addWidgetControls()`
- **Current:** Appends controls to widget element
- **Change:** Accept overlay container reference, append there instead
### Dashboard Manager
- **Source:** `dashboardManager.js`, lines 631-703 in `renderWidget()`
- **Current:** Calls `resizeHandler.initWidget()` and `editManager.addWidgetControls()` with widget element
- **Change:** Pass overlay containers, handle repositioning on layout changes
---
## Summary
The resize handles are being rendered **inside the widget container**, causing them to:
1. Contribute to widget dimensions via negative positioning tricks
2. Trigger scrollbars when combined with flex layout and `max-height`
3. Cause edit/delete buttons to be hidden or inaccessible
4. Create inconsistent UI behavior
**Solution:** Create true overlay containers at the grid level, position handles and controls outside the widget DOM, and coordinate their positioning through the DashboardManager lifecycle.
This approach is used in many professional UI frameworks and provides:
- Clean separation of concerns
- Better visual control
- Elimination of overflow/scrollbar issues
- Consistent button visibility
- Proper z-index layering