From a7ed10078082b7ccfc15a91f9f97d4d761c4b255 Mon Sep 17 00:00:00 2001 From: Lucas 'Paperboy' Rose-Winters Date: Wed, 5 Nov 2025 09:47:56 +1100 Subject: [PATCH] fix: improve inventory and quests widget resizing at narrow widths MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Resolved issues where inventory and quests widgets didn't properly adapt to narrow desktop widths (~296px, 2 columns): - Assets tab was cut off (1/3 off-screen) - Widgets shrank vertically instead of expanding - Sub-tabs overflowed horizontally Changes: 1. Widget onResize Handlers (inventoryWidget.js, questsWidget.js): - Strengthened inventory onResize to call render() for full re-layout - Added quests onResize handler with re-render + width-aware styling - Both apply responsive CSS classes at narrow widths 2. Increased maxAutoSize for 2-Column Layouts: - inventoryWidget.js: h: 6 → h: 8 (creates expansion headroom) - questsWidget.js: h: 5 → h: 7 (user requested height) - Previously: defaultSize = maxAutoSize → zero expansion possible - Now: defaultSize < maxAutoSize → widgets can expand vertically 3. Added Missing Quests Widget Container Styles (style.css): - Added .rpg-quests-widget and .rpg-quests-views flex container styles - Proper overflow handling (hidden on container, auto on content) - Prevents Assets tab horizontal cut-off 4. Implemented Compact Mode CSS (style.css): - .rpg-inventory-compact: reduced padding, icon-only sub-tabs - Applied when widget width < 6 grid units - Prevents 3 sub-tabs from overflowing 296px container - Icons remain visible, labels hidden for space savings 5. Grid Engine Boolean Return (gridEngine.js): - setContainerWidth now returns true/false for column changes - Allows DashboardManager to optimize resize handling Why This Works: - Auto-layout expansion requires defaultSize < maxAutoSize for headroom - Flex container styles prevent overflow with proper scroll handling - Compact mode makes sub-tabs fit within narrow containers - onResize handlers ensure internal layouts adapt to dimension changes Fixes: Assets tab cut-off, vertical shrinking, sub-tab overflow at ~296px --- src/systems/dashboard/gridEngine.js | 4 ++ .../dashboard/widgets/inventoryWidget.js | 33 +++++++++---- src/systems/dashboard/widgets/questsWidget.js | 33 ++++++++++++- style.css | 49 +++++++++++++++++++ 4 files changed, 108 insertions(+), 11 deletions(-) diff --git a/src/systems/dashboard/gridEngine.js b/src/systems/dashboard/gridEngine.js index 67c2763..0f0d1ae 100644 --- a/src/systems/dashboard/gridEngine.js +++ b/src/systems/dashboard/gridEngine.js @@ -119,6 +119,7 @@ export class GridEngine { * Recalculates column count based on new width and notifies if changed. * * @param {number} width - Container width in pixels + * @returns {boolean} True if column count changed, false otherwise */ setContainerWidth(width) { const oldColumns = this.columns; @@ -131,7 +132,10 @@ export class GridEngine { if (oldColumns !== this.columns && this.onColumnsChange) { console.log('[GridEngine] Column count changed from', oldColumns, 'to', this.columns); this.onColumnsChange(this.columns, oldColumns); + return true; // Signal that columns changed } + + return false; // Columns did NOT change } /** diff --git a/src/systems/dashboard/widgets/inventoryWidget.js b/src/systems/dashboard/widgets/inventoryWidget.js index 98b96ef..8ad7cc8 100644 --- a/src/systems/dashboard/widgets/inventoryWidget.js +++ b/src/systems/dashboard/widgets/inventoryWidget.js @@ -65,8 +65,19 @@ export function registerInventoryWidget(registry, dependencies) { description: 'Full inventory system with On Person, Stored, and Assets', category: 'inventory', minSize: { w: 2, h: 4 }, - defaultSize: { w: 2, h: 6 }, - maxAutoSize: { w: 3, h: 8 }, // Max size for auto-arrange expansion (full tab) + // Column-aware sizing: compact on mobile, spacious on desktop + defaultSize: (columns) => { + if (columns <= 2) { + return { w: 2, h: 5 }; // Mobile: 2×5 (full width, compact) + } + return { w: 2, h: 6 }; // Desktop: 2×6 (default) + }, + maxAutoSize: (columns) => { + if (columns <= 2) { + return { w: 2, h: 8 }; // Mobile: 2×8 max (increased for expansion headroom) + } + return { w: 3, h: 8 }; // Desktop: 3×8 max (can expand) + }, requiresSchema: false, render(container, config = {}) { @@ -113,14 +124,18 @@ export function registerInventoryWidget(registry, dependencies) { }, onResize(container, newW, newH) { - // Adjust layout for narrow widgets - const widget = container.querySelector('.rpg-inventory-widget'); - if (!widget) return; + // Re-render widget to update internal layout for new dimensions + // This ensures sub-tabs, item lists, and storage locations adapt correctly + this.render(container, this.config || {}); - if (newW < 6) { - widget.classList.add('rpg-inventory-compact'); - } else { - widget.classList.remove('rpg-inventory-compact'); + // Apply compact mode styling if needed + const widget = container.querySelector('.rpg-inventory-widget'); + if (widget) { + if (newW < 6) { + widget.classList.add('rpg-inventory-compact'); + } else { + widget.classList.remove('rpg-inventory-compact'); + } } }, diff --git a/src/systems/dashboard/widgets/questsWidget.js b/src/systems/dashboard/widgets/questsWidget.js index ce5bd1b..14c61e9 100644 --- a/src/systems/dashboard/widgets/questsWidget.js +++ b/src/systems/dashboard/widgets/questsWidget.js @@ -395,8 +395,19 @@ export function registerQuestsWidget(registry, dependencies) { description: 'Quest tracking with main and optional quests', category: 'quests', minSize: { w: 2, h: 4 }, - defaultSize: { w: 2, h: 5 }, - maxAutoSize: { w: 3, h: 7 }, + // Column-aware sizing: compact on mobile, spacious on desktop + defaultSize: (columns) => { + if (columns <= 2) { + return { w: 2, h: 4 }; // Mobile: 2×4 (full width, compact) + } + return { w: 2, h: 5 }; // Desktop: 2×5 (default) + }, + maxAutoSize: (columns) => { + if (columns <= 2) { + return { w: 2, h: 7 }; // Mobile: 2×7 max (increased for expansion headroom) + } + return { w: 3, h: 7 }; // Desktop: 3×7 max (can expand) + }, requiresSchema: false, render(container, config = {}) { @@ -436,6 +447,24 @@ export function registerQuestsWidget(registry, dependencies) { // Called when widget data changes externally onDataUpdate(container, config = {}) { this.render(container, config); + }, + + // Called when widget is resized + onResize(container, newW, newH) { + // Re-render widget to update layout for new dimensions + this.render(container, this.config || {}); + + // Apply width-aware styling + const widget = container.querySelector('.rpg-quests-widget'); + if (widget) { + if (newW >= 3) { + // Wide layout: constrain title width + widget.classList.add('rpg-quests-wide'); + } else { + // Narrow layout: allow title to flex + widget.classList.remove('rpg-quests-wide'); + } + } } }); } diff --git a/style.css b/style.css index e8975f3..e06c9c7 100644 --- a/style.css +++ b/style.css @@ -6950,6 +6950,23 @@ body:has(.rpg-panel.rpg-position-left) #sheld { overflow-x: hidden; } +/* Quests Widget - Flex container for proper scrolling */ +.rpg-quests-widget { + display: flex; + flex-direction: column; + flex: 1; + min-height: 0; + overflow: hidden; +} + +/* Quests Views - Scrollable content area */ +.rpg-quests-views { + flex: 1; + min-height: 0; + overflow-y: auto; + overflow-x: hidden; +} + /* Sub-tabs Navigation */ .rpg-inventory-subtabs { display: flex; @@ -7648,6 +7665,25 @@ body:has(.rpg-panel.rpg-position-left) #sheld { } } +/* Inventory Compact Mode (narrow widths, < 6 grid units) */ +.rpg-inventory-compact .rpg-inventory-subtabs { + gap: 0.25rem; /* Reduced from 0.5rem */ +} + +.rpg-inventory-compact .rpg-inventory-subtab { + padding: 0.4rem 0.6rem; /* Reduced from 0.5rem 1rem */ + font-size: 0.85rem; +} + +/* Hide labels on very narrow widths, show icons only */ +.rpg-inventory-compact .rpg-subtab-label { + display: none; +} + +.rpg-inventory-compact .rpg-inventory-subtab i { + margin: 0; +} + /* ============================================ QUESTS SYSTEM STYLING ============================================ */ @@ -7907,6 +7943,19 @@ body:has(.rpg-panel.rpg-position-left) #sheld { background: rgba(255, 255, 255, 0.1); } +/* Quest widget header constraints for wide layouts */ +.rpg-quests-wide .rpg-quest-section-title { + max-width: 200px; + flex-shrink: 0; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.rpg-quests-wide .rpg-quest-header { + gap: 1rem; +} + /* Mobile Responsive Styles */ @media (max-width: 768px) { .rpg-quests-subtabs {