feat(dashboard): implement column-aware defaultSize for optimal 3-4 col widget layout

PROBLEM:
- Reset/auto-layout placed userInfo at 1x1, mood at [1,0] blocking expansion
- Expansion pass couldn't grow userInfo to 2x1 because mood already occupied column 1
- Result: 1x1 userInfo, 1x1 mood, empty space at [2,0] in 3-col layout

ROOT CAUSE:
- Static defaultSize 1x1 → placement happens first
- Expansion happens second, but mood blocks userInfo horizontal growth

SOLUTION - Column-aware defaultSize:
1. userInfoWidget.js: defaultSize now function of columns
   - Mobile (≤2 col): { w: 1, h: 1 } (compact, mood beside it)
   - Desktop (3-4 col): { w: 2, h: 1 } (starts at target size)

2. dashboardManager.js: resetWidgetSizesToDefault() supports function defaultSize
   - Calls defaultSize(columns) if function, otherwise uses static object
   - Same pattern as maxAutoSize support

3. widgetRegistry.js: Updated validation to accept function defaultSize
   - Skip validation for functions (can't validate until runtime)

4. dashboardManager.js: Reordered userWidgetOrder
   - mood(2) before stats(3) so mood sits beside userInfo in top row

RESULT (3-4 columns):
- userInfo starts at 2x1, placed at [0,0]
- mood placed at [2,0] (beside 2-wide userInfo)
- stats placed at [0,1] and expands to 3x? (full width below)
- No expansion blocking, no wasted space

MOBILE FIXES (from previous commits):
- Stats widget: padding-bottom 0.5rem (was 0.3rem, prevent Arousal clipping)
- Refresh button: Show with Dashboard v2 (#rpg-dashboard-container selector)
- Mood text: 0.6rem font-size (improve readability)

AFFECTED:
- userInfoWidget.js: defaultSize + maxAutoSize column-aware functions
- dashboardManager.js: resetWidgetSizesToDefault, userWidgetOrder
- widgetRegistry.js: Validation allows function defaultSize
- userStatsWidget.js: maxAutoSize column-aware (previous commit)
- style.css: Stats padding fix 0.5rem
This commit is contained in:
Lucas 'Paperboy' Rose-Winters
2025-10-24 18:55:38 +11:00
parent ac5bd22e55
commit e031643cd5
4 changed files with 28 additions and 10 deletions
+14 -5
View File
@@ -804,9 +804,9 @@ export class DashboardManager {
// Specific widget type ordering within user category // Specific widget type ordering within user category
const userWidgetOrder = { const userWidgetOrder = {
'userInfo': 1, // Name/level at top 'userInfo': 1, // Name/level at top-left
'userStats': 2, // Health/energy bars 'userMood': 2, // Mood at top-right (before stats so it sits beside userInfo)
'userMood': 3, // Mood 'userStats': 3, // Health/energy bars (after mood, goes below userInfo+mood)
'userAttributes': 4 // STR/DEX/etc 'userAttributes': 4 // STR/DEX/etc
}; };
@@ -1231,8 +1231,17 @@ export class DashboardManager {
const definition = this.registry.get(widget.type); const definition = this.registry.get(widget.type);
if (definition && definition.defaultSize) { if (definition && definition.defaultSize) {
const oldSize = `${widget.w}x${widget.h}`; const oldSize = `${widget.w}x${widget.h}`;
widget.w = definition.defaultSize.w;
widget.h = definition.defaultSize.h; // Support defaultSize as function (column-aware sizing)
let defaultSize;
if (typeof definition.defaultSize === 'function') {
defaultSize = definition.defaultSize(this.gridEngine.columns);
} else {
defaultSize = definition.defaultSize;
}
widget.w = defaultSize.w;
widget.h = defaultSize.h;
const newSize = `${widget.w}x${widget.h}`; const newSize = `${widget.w}x${widget.h}`;
if (oldSize !== newSize) { if (oldSize !== newSize) {
console.log(`[DashboardManager] Reset ${widget.type} from ${oldSize} to ${newSize}`); console.log(`[DashboardManager] Reset ${widget.type} from ${oldSize} to ${newSize}`);
+4 -1
View File
@@ -87,7 +87,10 @@ export class WidgetRegistry {
if (!definition.minSize.w || !definition.minSize.h) { if (!definition.minSize.w || !definition.minSize.h) {
throw new Error('[WidgetRegistry] Widget minSize must have w and h properties'); throw new Error('[WidgetRegistry] Widget minSize must have w and h properties');
} }
if (!definition.defaultSize.w || !definition.defaultSize.h) { // defaultSize can be a function (column-aware) or static object
if (typeof definition.defaultSize === 'function') {
// If function, we can't validate until runtime, skip validation
} else if (!definition.defaultSize.w || !definition.defaultSize.h) {
throw new Error('[WidgetRegistry] Widget defaultSize must have w and h properties'); throw new Error('[WidgetRegistry] Widget defaultSize must have w and h properties');
} }
@@ -38,13 +38,19 @@ export function registerUserInfoWidget(registry, dependencies) {
description: 'User avatar, name, and level display', description: 'User avatar, name, and level display',
category: 'user', category: 'user',
minSize: { w: 1, h: 1 }, minSize: { w: 1, h: 1 },
defaultSize: { w: 1, h: 1 }, // Start compact (1x1), expansion will grow it based on columns // Column-aware default size: start at 2x1 in desktop so mood doesn't block expansion
// Column-aware max size: mobile (2-col) stays 1x1, desktop (3-4 col) expands vertically to 1x2 defaultSize: (columns) => {
if (columns <= 2) {
return { w: 1, h: 1 }; // Mobile: compact 1x1
}
return { w: 2, h: 1 }; // Desktop: 2x1 from the start
},
// Column-aware max size: same as defaultSize to prevent further expansion
maxAutoSize: (columns) => { maxAutoSize: (columns) => {
if (columns <= 2) { if (columns <= 2) {
return { w: 1, h: 1 }; // Mobile: stay compact to allow mood widget beside it return { w: 1, h: 1 }; // Mobile: stay compact to allow mood widget beside it
} }
return { w: 1, h: 2 }; // Desktop: expand vertically, mood fits top-right return { w: 2, h: 1 }; // Desktop: 2x1, mood sits in top-right
}, },
requiresSchema: false, requiresSchema: false,
+1 -1
View File
@@ -4323,7 +4323,7 @@ body:has(.rpg-panel.rpg-position-left) #sheld {
/* User Stats Widget - add bottom padding to prevent last bar (Arousal) from being clipped */ /* User Stats Widget - add bottom padding to prevent last bar (Arousal) from being clipped */
.rpg-widget .rpg-stats-grid { .rpg-widget .rpg-stats-grid {
padding-bottom: 0.3rem !important; padding-bottom: 0.5rem !important;
} }
/* Mood Widget - increase conditions text size for readability */ /* Mood Widget - increase conditions text size for readability */