feat(dashboard): implement smart widget collision and category-aware layout
Complete dashboard v2 improvements for better UX and visual consistency: **1. Push-Aside Drag/Drop (dragDrop.js)** - Replace swap/revert logic with intelligent reflow algorithm - When widgets collide on drag, automatically push overlapping widgets down - All affected widgets repositioned after reflow completes - Eliminates widget overlap issues **2. Unified Widget Styling (style.css)** - Add consistent .rpg-widget container styling for all widgets - Background: rgba(0,0,0,0.2) for visual separation - Border-left: 3px highlight for category identification - Box-shadow and border-radius for depth and polish - Maintain individual widget decorative styles **3. Logical Default Layout (defaultLayout.js)** - Reorganize widgets into semantic clusters with clear comments: - USER CLUSTER (top): userInfo → userStats → userMood + userAttributes - SCENE CLUSTER (middle): calendar + weather → temp + clock → location - SOCIAL CLUSTER (bottom): presentCharacters - userInfo widget now at top (y=0) as expected - All positions use rem units for responsive scaling **4. Category-Aware Auto-Layout (dashboardManager.js)** - Implement sortWidgetsByCategory() with priority ordering: user → scene → social → inventory - Within user category, specific ordering: userInfo → userStats → userMood → userAttributes - Add preserveOrder option to gridEngine.autoLayout() - Auto-arrange now uses logical grouping instead of random bin-packing **5. Multi-Tab Auto-Distribution (dashboardManager.js)** - Add estimateLayoutHeight() to detect when content exceeds threshold - Implement distributeWidgetsByCategory() for automatic tab creation: - "Status" tab: user + scene widgets - "Social" tab: social widgets (if any) - "Inventory" tab: inventory widgets (if any) - Each tab gets category-aware auto-layout - 80rem height threshold for single-tab limit **6. Widget Category Metadata (widgets/)** - Add category field to all widget definitions: - userInfo, userStats, userMood, userAttributes: 'user' - calendar, weather, temperature, clock, location: 'scene' - presentCharacters: 'social' - inventory: 'inventory' **7. Integration Improvements (dashboardIntegration.js)** - Set default layout on initialization for reset functionality - Add reset layout button to dashboard header - Wire up reset button event handler **8. Core State Management (index.js)** - Add getInfoBoxData() and setInfoBoxData() to state API - Ensure info box data persists across sessions **Technical Details:** - Rem units throughout for 1080p→4K→mobile responsive scaling - Reflow algorithm leverages existing gridEngine collision detection - Category-aware sorting preserves logical relationships - Multi-tab distribution prevents single-page scroll fatigue - All changes maintain backwards compatibility with existing layouts Fixes dashboard issues after rem unit conversion introduced massive positioning bugs. Users reported widgets overlapping on drag, visual inconsistency, and random auto-arrange behavior. Related: Epic 2 (Dashboard v2), Phase 3.2
This commit is contained in:
@@ -24,8 +24,9 @@ export function generateDefaultDashboard() {
|
||||
gridConfig: {
|
||||
// Columns calculated dynamically by GridEngine (2-4 based on panel width)
|
||||
// Mobile: always 2, Desktop: 2-4 based on width
|
||||
rowHeight: 80,
|
||||
gap: 12,
|
||||
columns: 2, // Default to 2 columns (will be recalculated on init)
|
||||
rowHeight: 5, // rem units for responsive scaling (1080p → 4K → mobile)
|
||||
gap: 0.75, // rem units (scales with screen DPI)
|
||||
snapToGrid: true,
|
||||
showGrid: true
|
||||
},
|
||||
@@ -37,25 +38,56 @@ export function generateDefaultDashboard() {
|
||||
icon: '📊',
|
||||
order: 0,
|
||||
widgets: [
|
||||
// Row 1: User Stats (full width)
|
||||
// === USER CLUSTER (Top) ===
|
||||
// Row 0: User Info (avatar, name, level) - AT TOP
|
||||
{
|
||||
id: 'widget-userinfo',
|
||||
type: 'userInfo',
|
||||
x: 0,
|
||||
y: 0,
|
||||
w: 2,
|
||||
h: 1,
|
||||
config: {}
|
||||
},
|
||||
// Row 1-2: User Stats (health/energy bars)
|
||||
{
|
||||
id: 'widget-userstats',
|
||||
type: 'userStats',
|
||||
x: 0,
|
||||
y: 0,
|
||||
y: 1,
|
||||
w: 2,
|
||||
h: 3,
|
||||
h: 2,
|
||||
config: {
|
||||
showClassicStats: true,
|
||||
statBarStyle: 'gradient'
|
||||
statBarGradient: true
|
||||
}
|
||||
},
|
||||
// Row 2: Calendar (left) + Weather (right)
|
||||
// Row 3-4: User Mood (left) + User Attributes (right)
|
||||
{
|
||||
id: 'widget-usermood',
|
||||
type: 'userMood',
|
||||
x: 0,
|
||||
y: 3,
|
||||
w: 1,
|
||||
h: 1,
|
||||
config: {}
|
||||
},
|
||||
{
|
||||
id: 'widget-userattributes',
|
||||
type: 'userAttributes',
|
||||
x: 1,
|
||||
y: 3,
|
||||
w: 1,
|
||||
h: 2,
|
||||
config: {}
|
||||
},
|
||||
|
||||
// === SCENE CLUSTER (Middle) ===
|
||||
// Row 5-6: Calendar (left) + Weather (right)
|
||||
{
|
||||
id: 'widget-calendar',
|
||||
type: 'calendar',
|
||||
x: 0,
|
||||
y: 3,
|
||||
y: 5,
|
||||
w: 1,
|
||||
h: 2,
|
||||
config: {}
|
||||
@@ -64,19 +96,19 @@ export function generateDefaultDashboard() {
|
||||
id: 'widget-weather',
|
||||
type: 'weather',
|
||||
x: 1,
|
||||
y: 3,
|
||||
y: 5,
|
||||
w: 1,
|
||||
h: 2,
|
||||
config: {
|
||||
compact: false
|
||||
}
|
||||
},
|
||||
// Row 3: Temperature (left) + Clock (right)
|
||||
// Row 7-8: Temperature (left) + Clock (right)
|
||||
{
|
||||
id: 'widget-temperature',
|
||||
type: 'temperature',
|
||||
x: 0,
|
||||
y: 5,
|
||||
y: 7,
|
||||
w: 1,
|
||||
h: 2,
|
||||
config: {
|
||||
@@ -87,29 +119,31 @@ export function generateDefaultDashboard() {
|
||||
id: 'widget-clock',
|
||||
type: 'clock',
|
||||
x: 1,
|
||||
y: 5,
|
||||
y: 7,
|
||||
w: 1,
|
||||
h: 2,
|
||||
config: {
|
||||
format: 'digital'
|
||||
}
|
||||
},
|
||||
// Row 4: Location (full width)
|
||||
// Row 9-10: Location (full width)
|
||||
{
|
||||
id: 'widget-location',
|
||||
type: 'location',
|
||||
x: 0,
|
||||
y: 7,
|
||||
y: 9,
|
||||
w: 2,
|
||||
h: 2,
|
||||
config: {}
|
||||
},
|
||||
// Row 5-6: Present Characters (full width)
|
||||
|
||||
// === SOCIAL CLUSTER (Bottom) ===
|
||||
// Row 11-13: Present Characters (full width)
|
||||
{
|
||||
id: 'widget-presentchars',
|
||||
type: 'presentCharacters',
|
||||
x: 0,
|
||||
y: 9,
|
||||
y: 11,
|
||||
w: 2,
|
||||
h: 3,
|
||||
config: {
|
||||
|
||||
Reference in New Issue
Block a user