This commit implements three major improvements to the dashboard system:
1. **Font Awesome Icons for Tabs**
- Replace emoji tab icons (📊, 🌍, 🎒) with Font Awesome classes
- Update defaultLayout.js with fa-solid icon classes
- Add automatic migration for existing saved dashboards with emoji icons
- Implement migrateEmojiIcons() to convert old emoji icons on load
- Update fallback icons throughout the system
2. **Custom Theme Support for Dashboard**
- Replace all --SmartTheme* variables with --rpg-* variables
- Ensure custom themes (sci-fi, fantasy, cyberpunk) apply to dashboard
- Update CSS for tabs, buttons, dropdowns, modals, and widget cards
- Dashboard now respects extension themes instead of main SillyTavern theme
3. **Styled Confirmation Dialogs**
- Create confirmDialog.js with showConfirmDialog() and showAlertDialog()
- Support three variants: danger (red), warning (yellow), info (blue)
- Add keyboard navigation (Enter/Escape) and accessibility features
- Replace all native confirm() and alert() calls with styled dialogs
- Add confirmation dialog modal to dashboardTemplate.html
Files Modified:
- src/systems/dashboard/confirmDialog.js (NEW)
- src/systems/dashboard/dashboardManager.js
- src/systems/dashboard/defaultLayout.js
- src/systems/dashboard/tabManager.js
- src/systems/dashboard/dashboardIntegration.js
- src/systems/dashboard/editModeManager.js
- src/systems/dashboard/widgets/inventoryWidget.js
- src/systems/dashboard/dashboardTemplate.html
- style.css
- Store button visibility state before hiding them in overflow/compact modes
- Use stored wasVisible data attribute to filter which buttons to show
- Prevents hidden buttons (like Done) from appearing inappropriately
- Also prevents visible buttons from being excluded when they're hidden by overflow manager
- Full mode now checks inline style to respect template display:none
Ensure contenteditable and input fields remain disabled when widgets
are re-rendered during edit mode (e.g., during auto-layout, cross-tab
moves, or tab switches). This prevents text editing from interfering
with drag operations.
Previously, disableContentEditing() was only called when entering edit
mode, so any widgets rendered afterward would have editable fields again.
Now, renderWidgetContent() checks if in edit mode and disables editing
on newly rendered widgets.
Mobile Inventory Improvements:
- Add icon-based sub-tabs (user/box/building) with responsive labels
- Desktop shows icon + label, mobile shows icon-only for compact layout
- Add proper scroll containers for inventory content with flex layout
- Increase touch drag delay from 150ms to 500ms to prevent accidental widget moves during scrolling
Widget Content Fixes:
- Add max-height constraint to .rpg-widget to prevent grid cell overflow
- Add flex properties (flex: 1, min-height: 0, overflow: auto) to all widget content
- Ensures content scrolls internally instead of expanding widget bounds
- Fix .rpg-inventory-widget to use flex properties instead of height: 100%
Layout Fixes:
- Change characters widget default size from 2x3 to 2x2 for better viewport fit
- Remove excess spacing from dashboard container (gap: 0.75rem)
- Remove vertical padding from dashboard header
- Eliminates desktop scrollbar caused by cumulative spacing
All widgets now fit properly within viewport on both desktop and mobile.
- Increase conditions font size from 0.45rem to 0.6rem (33% larger)
- Reduce mood emoji size from 1rem to 0.9rem for better proportion
- Add font-weight: 600 to mood for better hierarchy
- Improve line-height from 1 to 1.2 for readability
- Reduce -webkit-line-clamp from 3 to 2 lines for conditions
- Add slight opacity (0.9) to conditions for visual separation
- Update onResize scaling to maintain balanced proportions (1.4rem / 0.9rem for larger widgets)
- Increase mobile conditions size to 0.7rem with 1.3 line-height
Result: Conditions text is now much more readable while maintaining good visual balance
with the mood emoji in the compact 1x1 widget.
- Changed boundary check from >= to > to allow widgets to properly fill viewport
- Updated viewport calculation to use grid container's clientHeight directly
- Added gap compensation in row calculation to account for last row having no trailing gap
- Widgets now expand to use all available vertical space without leaving unused rows
The issue was that y + h represents the row AFTER the widget ends, not the last
occupied row, so >= was too conservative. With maxVisibleRows=7 (rows 0-6), a
widget at y=3 can now expand to h=4 (rows 3,4,5,6) instead of being blocked.
- Remove double left border accent on character cards by hiding inner border when inside widget container
- Increase maxAutoSize width from 3 to 4 columns to support large displays
- Fix viewport height calculation to use visible area instead of scrollable container height
- Change auto-layout boundary check from > to >= to prevent widgets extending beyond viewport
- Add Done button for cleaner edit mode exit UX
- Wire up Done button event listener in dashboardIntegration
- Disable contenteditable fields in edit widget mode to prevent keyboard popup
- Re-enable content editing when exiting edit mode
- Change button tooltip from 'Toggle Edit Mode' to 'Toggle Edit Widget Mode' for clarity
- Remove redundant 'WEATHER' subtitle from weather widget (only show single editable field)
- Prevents layout shift on mobile when keyboard appears during widget arrangement
- Add lock/unlock button to dashboard header (always visible)
- Lock state prevents dragging in both normal and edit modes
- Lock state prevents resizing in edit mode
- Icon changes: lock-open (unlocked) ↔ lock (locked)
- Hide resize handles and prevent grab cursor when locked
- Lock state persists across edit mode toggles
- Integrate lock checks in DragDropHandler and ResizeHandler
- Pass editManager reference to drag/resize handlers for lock state access
- Add 5px mouse movement threshold before drag starts
- Prevent dragging when clicking interactive elements (contenteditable, input, button, etc.)
- Store pending drag state and wait for movement before preventing default behavior
- Allow normal click/edit interactions on widget content
- Touch behavior unchanged (existing 150ms delay still works)
- Fixes issue where contenteditable fields and buttons were not clickable
- Change .rpg-widget overflow from hidden to visible to prevent handle clipping
- Reduce horizontal handle offset from -6px to -3px to prevent overlap
- Keep vertical offset at -6px (adequate gap between rows)
- Handles now have 6px clearance when widgets are side-by-side (12px gap - 3px - 3px)
- Convert rowHeight and gap from rem to pixels using gridEngine.remToPixels()
- Fix highlightGridCells() to use pixel values for positioning and sizing
- Fix showGridOverlay() to calculate container height in pixels
- Resolves issue where green highlight boxes rendered as tiny squished lines
- Follows same conversion pattern used in gridEngine.getPixelPosition()
DESKTOP LAYOUT OPTIMIZATION (3-4 columns):
- userInfo: Changed maxAutoSize from 2x1 to 1x2 (expands vertically)
- userStats: Changed to column-aware function, 3x3 in 3-4 col (full width horizontal)
- Layout: userInfo 1x2 (left) + mood 1x1 (top-right), stats 3x3 below (full width)
- Result: Better horizontal space utilization, less vertical stacking
MOBILE FIXES (Dashboard v2):
1. Refresh button visibility
- Added #rpg-dashboard-container to CSS selector
- Now shows with Dashboard v2, not just old panel UI
2. Stats widget Arousal bar clipping
- Added padding-bottom: 0.5rem to .rpg-stats-grid
- Prevents last stat bar from being cut off
3. Mood conditions text too small
- Increased from 0.45rem to 0.6rem with line-height 1.2
- "Focused, Awakening Qi" now readable under emoji
AFFECTED:
- userInfoWidget.js: maxAutoSize 1x2 for desktop vertical expansion
- userStatsWidget.js: Column-aware maxAutoSize function (2x2 mobile, 3x3 desktop)
- style.css: Mobile refresh visibility, stats padding, mood text size
PROBLEM:
- Mobile (2-col): userInfo defaulted to 2x1 (full width), pushed mood to row 2
- After mobile CSS fixes, 1x1 widgets display perfectly
- Want userInfo 1x1 + mood 1x1 side-by-side in top row on mobile
- Desktop (3-4 col): userInfo should still expand to 2x1 for better space usage
SOLUTION:
- gridEngine: Support maxAutoSize as function (receives column count)
- userInfoWidget:
- Changed defaultSize from 2x1 to 1x1 (starts compact)
- Changed maxAutoSize to column-aware function:
* 2 columns (mobile): maxAutoSize 1x1 (stays compact)
* 3-4 columns (desktop): maxAutoSize 2x1 (can expand)
BEHAVIOR:
- Auto-layout resets widgets to defaultSize (1x1)
- Expansion pass grows widgets up to maxAutoSize based on available space
- Mobile: userInfo stays 1x1, mood can fit beside it (row 0: [userInfo][mood])
- Desktop: userInfo can expand to 2x1 if space available
AFFECTED:
- gridEngine.js: getWidgetMaxSize() now calls maxAutoSize(columns) if function
- userInfoWidget.js: Column-aware maxAutoSize, compact 1x1 defaultSize
PROBLEM: 1x1 mobile widgets displayed poorly with excessive vertical spacing
ROOT CAUSE: Conflicting @media (max-width: 768px) set min-height: 2.75rem on all .rpg-editable
FIXES:
- Remove conflicting 768px media query min-height rule
- Add line-height: 1.2, min-height: 0, height: auto to .rpg-editable
- Use display: block for single-line fields instead of -webkit-box
- GridEngine detects mobile viewport (≤1000px) for 3.5rem rowHeight
- mobile.js skips old tab setup when Dashboard v2 exists
- Hide weather forecast label on mobile (shows icon text only)
- Fix weather text wrapping with white-space: nowrap
AFFECTED:
- style.css: Mobile contenteditable spacing, weather widget, widget scaling
- gridEngine.js: Mobile rowHeight detection (isMobileViewport)
- mobile.js: Skip mobile tabs when Dashboard v2 present
- Update onMessageReceived to populate extensionSettings.infoBoxData and characterThoughts for dashboard widgets
- Update updateRPGData (separate mode) with same extensionSettings population
- Add refreshDashboard() calls after data updates in both generation paths
- Fix onCharacterChanged to populate extensionSettings from loaded chat data
- Fix refreshDashboard() to use correct property name (registry not widgetRegistry)
- Reduce mood and weather widget font sizes to fit in 1x1 layout
This fixes Scene tab widgets not updating when receiving messages or loading chats from welcome screen.
Problem: Mood widget at 1x1 was cutting off subtext, only showing emoji
and main text (e.g., "🧘 Focused") but hiding conditions below.
Changes:
- Reduced emoji from 1.2rem → 1rem at 1x1 size
- Reduced conditions text from 0.55rem → 0.45rem
- Tightened spacing (gap: 0.1rem, padding: 0.25rem)
- Set line-height: 1 to minimize vertical space usage
- Allow up to 3 lines of conditions text with -webkit-line-clamp
- Added responsive scaling: larger sizes (2x2+) use bigger fonts
Now fits emoji, main text, and subtext comfortably in 1x1 grid cell.
Root cause: Widgets were using getUserAvatar() which returns bare
filenames like 'user-default.png'. These were being used directly as
image src URLs, causing 404 errors like /user-default.png.
Solution: Use getAvatarUrl() dependency which calls getThumbnailUrl()
to convert filenames to proper URLs like /thumbnail?type=persona&file=...
Changes:
- userInfoWidget.js: Use getAvatarUrl('persona', rawAvatar) instead of
raw avatar validation
- sillytavern.js: Simplify updatePersonaAvatar() to trust
getSafeThumbnailUrl() which already calls getThumbnailUrl()
This eliminates 404 errors on initial render and when switching tabs.
**Avatar 404 Fix:**
- Add fallback to getUserAvatar() call to use FALLBACK_AVATAR_DATA_URI when user avatar is missing
- Prevents 404 errors on app startup or when no character is selected
**Layout & Space Utilization Improvements:**
- Implement flexible hybrid layout system:
- 1 column (1x1): Centered large avatar (3rem) with text below
- 2+ columns (2x1+): Side-by-side (avatar 2.5rem left, text right)
- Replace rigid horizontal layout with adaptive container
- Add layout classes: rpg-layout-vertical, rpg-layout-horizontal
- Trigger onResize on initial render for correct layout
**Better Styling:**
- Increase avatar size: 2.5rem-3rem (was 1.2rem)
- Increase font sizes: 0.9rem name, 0.85rem level (was 0.75rem)
- Improve text hierarchy with proper containers
- Add proper spacing and alignment for both layouts
- Remove awkward vertical stacking of "Name | LVL 1"
- Text now stacks cleanly: "Name" on one line, "LVL X" on another
The widget now uses space efficiently, displays a prominent avatar,
and adapts intelligently to different widget sizes.
- Add resetWidgetSizesToDefault() to reset all widgets to default sizes before auto-arrange/reset
- Implement continuous expansion algorithm that fills available space up to maxAutoSize limits
- Add visible height detection to prevent widgets expanding beyond viewport (no forced scroll)
- Update all widget defaultSize and maxAutoSize for optimal 1x1 compact layouts
- Info widgets (calendar, weather, temp, clock): 1x1 default, 1x2 max
- Location: 2x2 max (was 3x3)
- Characters: 3x5 max, moved to 'scene' category (eliminates Social tab)
- User Info: 2x1 max (prevents expansion)
- User Mood: 1x1 default and max (compact top-right placement)
- User Attributes: 3x5 max (fills bottom space)
- User Stats: 3x3 max
- Fix CSS scaling for 1x1 widgets
- Replace viewport-based units with fixed rem values
- Reduce icon/graphic sizes to fit with visible text
- Add explicit gaps and padding for consistent spacing
- Set line-height: 1 to prevent text overflow
- Reorganize default layout
- Status tab: User Info (2x1) + Mood (1x1 top right) + Stats + Attributes
- Scene tab: Info widgets (1x1) + Location + Characters (all on one tab)
- Inventory tab: Full inventory widget
Auto-arrange and reset now properly size widgets to defaults and expand to fill
available space without exceeding visible area.
Moved the 'Enable Immersive HTML' toggle from main panel to settings:
- Added toggle to settings.html with descriptive notes
- Removed from template.html to free vertical space
- Checkbox ID remains the same so existing JS still works
Benefits:
- Frees up vertical space in dashboard (was causing scrollbars)
- Users can now use full 3x7 grid instead of being limited to 3x6
- Eliminates gap beneath last widget
- Toggle is still accessible but doesn't clutter main panel
- Settings panel is the appropriate place for infrequently-changed options
This commit implements 5 major improvements to the dashboard layout system:
**1. Improved Default Layout (defaultLayout.js)**
- Changed from 2 tabs to 3 tabs for better organization:
- Tab 1 (Status): User widgets only (userInfo, userStats, userMood, userAttributes)
- Tab 2 (Scene): Scene widgets + characters (calendar, weather, temp, clock, location, presentCharacters)
- Tab 3 (Inventory): Full inventory widget
- Cleaner separation prevents cramming all widgets on one tab
**2. Widget Max Size Limits (widget definition files)**
- Added maxAutoSize property to all widgets (enforced only during auto-arrange):
- Info widgets (calendar, weather, temp, clock): { w: 2, h: 3 }
- Location: { w: 3, h: 3 }
- presentCharacters: { w: 3, h: 6 } (can expand significantly)
- Inventory: { w: 3, h: 8 } (full tab)
- Prevents blind expansion while allowing intelligent space filling
**3. Smart Expansion Algorithm (gridEngine.js)**
- Added expansion pass after compaction in autoLayout():
- Sorts widgets top-to-bottom, left-to-right
- Tries to expand height first (fills vertical gaps)
- Then tries to expand width (fills horizontal gaps)
- Respects maxAutoSize limits from widget definitions
- Only expands if no collision with other widgets
- Widgets now fill available space instead of staying at default sizes
- Example: presentCharacters expands from 2x3 to 3x6 when space available
**4. Auto-Reflow on Column Change (dashboardManager.js)**
- Modified onColumnsChange callback to auto-layout after column count changes
- When grid transitions (2→3 or 3→2), automatically reflo ws widgets
- Prevents overlap and optimizes for new column count
- User experience: seamless adaptation when console opens/closes
**5. Fixed Grid Height/Scrollbar CSS (style.css)**
- Added flex: 1, overflow-y: auto, min-height: 0 to .rpg-dashboard-grid
- Grid now properly fills available space in dashboard container
- Accounts for bottom buttons (manual update, settings)
- Prevents "fingernail of extra height" that caused scrollbars
**Technical Changes:**
- Passed widget registry to GridEngine for maxAutoSize lookups
- getWidgetMaxSize() helper looks up definitions from registry
- Moved registry initialization before GridEngine construction
- Grid now uses flexbox to fill available vertical space
**User-Facing Improvements:**
- Reset layout creates logical 3-tab structure from the start
- Auto-arrange expands widgets to fill available space intelligently
- Resizing window/console automatically reflows layout
- No more unwanted scrollbars from slight overflow
Fixes cramped layouts, underutilized space, and scrollbar issues.
This commit resolves 6 critical dashboard issues reported by user:
1. **Persistent px values causing 264rem widget heights**
- Root cause: state.js had hardcoded rowHeight: 80, gap: 12 (px)
- Root cause: index.js double-loaded layout, overwriting migration
- Fix: Changed state.js gridConfig to rem units (5, 0.75)
- Fix: Removed redundant applyDashboardConfig in index.js
- Fix: Added migration in layoutPersistence.js for old saves
- Dashboard now uses rem consistently throughout
2. **Auto-layout on first load**
- Added auto-layout in loadLayout() when no saved layout exists
- Prevents overlap from hardcoded default positions
- Saves auto-laid-out result as initial layout
3. **Reset layout causes overlap**
- Added auto-layout loop in resetLayout() after applying config
- Each tab auto-lays out to prevent widget overlap
4. **Auto-arrange loses inventory/social widgets**
- Fixed autoLayoutWidgets to gather ALL widgets from ALL tabs
- Previously only gathered current tab, lost other tabs
- Now always uses multi-tab distribution to preserve all widgets
5. **Auto-arrange leaves 2x2 gaps**
- Added compact pass in gridEngine.js after bin-packing
- Moves widgets upward to fill gaps
- Eliminates empty spaces at bottom of layout
6. **Tabs not compact (icon-only)**
- Updated tab styling: icons only, names show on hover
- Allows more tabs in compact space
- min-width: 2.5rem, larger icon size
Also added debug logging to track config values through initialization.
Fixes refresh sizing bug, reset overlap, widget loss, and layout gaps.
Three critical fixes for dashboard layout:
**1. Fix Attributes Widget Overflow (style.css:1210)**
- Root cause: Default layout had attributes at w:1 but internal grid was 2 columns
- Widget was 1 dashboard column wide, but tried to display 2 internal columns
- Result: 2nd internal column overflowed off-screen to the right
- Fix: Internal grid already correct at 2 columns, just needed default layout fix
**2. Update Default Layout for Attributes (defaultLayout.js)**
- Changed attributes widget from w:1 to w:2 (full width in 2-column grid)
- Moved from x:1 (right column) to x:0 (left column, full width)
- Shifted from row 3 to row 4-5 (needs 2 rows height)
- Updated comment: now "full width, needs 2 columns for 3x2 grid"
- Shifted all scene widgets down by 1 row:
- Calendar/Weather: row 5→6
- Temperature/Clock: row 7→8
- Location: row 9→10
- Present Characters: row 11→12
- Mood stays at row 3 (left column only)
**3. Improve Multi-Tab Distribution (dashboardManager.js:725-779)**
- Status tab now contains user widgets ONLY (userInfo, stats, mood, attributes)
- Created new "Scene" tab for overflow scene widgets (calendar, weather, etc)
- Scene tab gets order:1, Social gets order:2, Inventory gets order:3
- Prioritizes character status on main tab instead of mixing with scene info
**Layout After Fix:**
```
Row 0: UserInfo (full width)
Row 1-2: UserStats (full width)
Row 3: UserMood (left column)
Row 4-5: UserAttributes (FULL WIDTH - 2 columns for 3x2 grid)
Row 6-7: Calendar + Weather
Row 8-9: Temperature + Clock
Row 10-11: Location
Row 12-14: Present Characters
```
**User-Reported Issues Fixed:**
✅ Attributes no longer overflow columns 3-5 off-screen
✅ Attributes widget properly sized at 2 dashboard columns wide
✅ Status tab prioritizes user widgets over scene info
✅ Scene widgets correctly overflow to separate "Scene" tab
Related: Dashboard v2, Epic 2, Phase 3.2
Implement responsive scaling for info widgets and fix sizing issues:
**1. Container-Responsive Info Widgets (style.css)**
**Calendar Widget:**
- Add flexbox layout (height: 100%, flex-direction: column)
- Change font sizes from vw to rem for better scaling
- Calendar day now uses clamp(1.5rem, 2.5rem, 3.5rem) to fill space
- Add flex-shrink: 0 to top/year, flex: 1 to day
**Weather Widget:**
- Add container wrapper (height: 100%, justify-content: space-around)
- Weather icon scales with container: clamp(2rem, 8vh, 4rem)
- Forecast text uses rem instead of vw
- Both elements marked flex-shrink: 0
**Temperature Widget:**
- Container fills height with flexbox centering
- Thermometer scales: clamp(4rem, 60%, 8rem) height
- Tube/bulb use percentages (40% width, 70% height)
- Text value uses rem units
**Clock Widget:**
- Container with space-around layout
- Clock scales with container: clamp(3rem, 60%, 6rem)
- Clock hands use percentages of clock size
- Time text uses rem units
**Location Widget:**
- Container flexbox with column layout
- Map background uses flex: 1 (was fixed 1.875rem)
- Map marker scales: clamp(1.5rem, 4vh, 3rem)
- Location text uses rem units
**2. Fix Attributes Widget Scrollbar (style.css)**
- Line 966: Change grid-auto-rows: 1fr to grid-auto-rows: minmax(0, 1fr)
- Allows rows to shrink below natural size to fit container
- Prevents overflow when widget manually positioned after auto-arrange
**3. Widget Size Constraints (widget files)**
- userAttributesWidget.js: Change minSize from {w:1, h:2} to {w:2, h:2}
- Enforces 2x2 minimum as requested
- Prevents cramped 1-column layout
- infoBoxWidgets.js: Change location minSize from {w:2, h:2} to {w:1, h:2}
- Allows narrow 1x2 layout for space-constrained dashboards
- Only widget that didn't fit on desktop screen
**Technical Details:**
- All info widgets now use rem units instead of vw for text
- Flexbox scaling ensures widgets fill their containers beautifully
- Percentage-based sizing for thermometer/clock internal elements
- clamp() used for min/preferred/max sizing across resolutions
- minmax(0, 1fr) fixes classic CSS grid overflow issue
**User-Reported Issues Fixed:**
✅ Info widgets scale to fill containers instead of fixed sizes
✅ Attributes widget no longer shows scrollbar in 2x2 (manual or auto-arranged)
✅ Location widget works in both 1x2 and 2x2 layouts
✅ All widgets maintain readability across different panel widths
Related: Dashboard v2, Epic 2, Phase 3.2
Stats widget into 4 modular widgets
- Create userInfoWidget (avatar, name, level)
- Refactor userStatsWidget (stats bars only with smart sizing)
- Create userMoodWidget (mood emoji, conditions)
- Create userAttributesWidget (STR/DEX/CON/INT/WIS/CHA)
- Add category field to widgets for auto-layout grouping
- Register all new modular widgets in dashboardIntegration.js
All widgets include getOptimalSize() for smart content-aware auto-layout.
Part of Phase 1 & 3.1 of dashboard modularization plan.
Multiple critical fixes for dashboard v2:
**1. ResizeHandler error - updateContainerWidth is not a function**
- resizeHandler.js:288 was calling non-existent method
- Removed call - containerWidth tracked by ResizeObserver
- Resizing now functional
**2. DragDrop bug - widgets can't be released**
- endDrag() destructured widgets, originalX, originalY from dragState
- These fields were never added in startDrag()
- Added widgets parameter to initWidget() and startDrag()
- Store originalX, originalY, widgets in dragState
- dashboardManager now passes current tab widgets
- Widgets can now be dropped properly
**3. Widget content overflow**
- Added base .rpg-widget CSS: overflow: hidden, box-sizing: border-box
- Prevents content extending beyond widget bounds
- max-width: 100% on children
**4. Automatic layout migration**
- Old 12-column layouts (w: 8, w: 12) cause 500%+ widths in 2-4 column grid
- Added migrateOldLayouts() method
- Detects widgets with w > current column count
- Runs auto-layout to reposition for responsive grid
- Clears and re-renders current tab with new positions
- Saves migrated layout automatically
**5. Tab rendering**
- Implemented renderTabs() method
- Displays tab buttons with icons and names
- Active state highlighting
- Click handlers to switch tabs
**6. Collision prevention**
- Modified dragDrop endDrag() to check collisions
- Same-size widgets: swap positions
- Different sizes: revert to original
- Prevents overlapping widgets
**7. Edit mode fixes**
- Fixed edit button to call toggleEditMode()
- Added CSS to hide resize handles when not in edit mode
- Handles only visible in edit mode
**8. Icon-only header buttons**
- Auto-Arrange and Edit buttons now icon-only
- Saves horizontal space in header
All issues from user testing resolved.
Fixed panel layout to properly position bottom buttons:
**Changes:**
1. #rpg-panel-content: Changed overflow-y from 'hidden' to 'auto'
- Allows panel to scroll when needed
2. .rpg-dashboard-container: Added flex properties
- flex: 1 - Grows to fill available space
- overflow-y: auto - Scrolls internally when content overflows
- min-height: 0 - Allows shrinking in flex context
**Result:**
Creates proper flex layout where:
- Dice display stays at top (fixed size)
- Dashboard container fills middle and scrolls (flex: 1)
- Toggle/Refresh/Settings buttons anchor at bottom (fixed size)
Fixes issue where buttons appeared in middle of panel instead of bottom.
Added missing CSS for dashboard v2 header and container:
- .rpg-dashboard-container: Flexbox column layout with gap
- .rpg-dashboard-header: Flexbox row with space-between
- .rpg-dashboard-header-left/right: Flex containers for button groups
- .rpg-dashboard-btn: Button styling with theme variables
- .rpg-dashboard-grid: Grid container styling
Also fixed dashboardManager.js to preserve template structure:
- Changed createContainerStructure() to query existing elements first
- Only creates elements if template didn't provide them
- Prevents clearing the entire container and losing the header
This fixes the issue where all components (header, buttons, widgets)
were stacking on top of each other due to missing layout CSS.
Implements intelligent auto-layout system that efficiently arranges widgets to maximize space usage while respecting panel width constraints.
**Key Features:**
- Smart packing algorithm that sorts by widget area and finds optimal positions
- Respects responsive column count (2-4 columns based on panel width)
- Prefers full-width widgets when possible to eliminate gaps
- Fallback to narrower widths for better vertical packing
- Maintains minimum widget sizes
**Implementation:**
- GridEngine.autoLayout() - Core packing algorithm with collision detection
- DashboardManager.autoLayoutWidgets() - High-level API that re-renders after layout
- Auto-Arrange button in dashboard header (uses fa-table-cells-large icon)
- Event handler wired to call autoLayoutWidgets with preferFullWidth=true
**Algorithm Strategy:**
1. Sort widgets by area (largest first) for efficient packing
2. For each widget, try full-width placement first
3. Find first available position using row-by-row scan
4. If position is too far down, try narrower widths
5. Mark cells as occupied to prevent overlaps
**Testing Notes:**
- Works with current responsive column system (2-4 columns)
- Respects minimum sizes and column constraints
- Re-renders all widgets after repositioning
- Auto-saves layout changes
Part of Epic 2: Dashboard Widget Library
- Add dashboard.tabs array and defaultTab to DashboardManager state
- Create default 'main' tab on initialization
- Pass dashboard object to TabManager instead of event handlers
- Register tab change listeners using onChange pattern
- Fix applyDashboardConfig to directly manipulate tabs array
- Fix getDashboardConfig to include all tab properties and defaultTab
- Remove non-existent deleteAllTabs() call
- Add dashboard initialization in initUI() after template load
- Inject all required dependencies for widgets:
- Data accessors (getContext, getExtensionSettings, getUserAvatar, etc.)
- Data setters (setCharacterThoughts)
- Event callbacks (onDataChange, onStatsChange, onDashboardChange)
- Create default layout on first load if no dashboard config exists
- Fallback to legacy rendering (renderUserStats, etc.) on error
- Comprehensive error handling with console logging
- Auto-save on all data changes
- Mark Tasks 2.1-2.4 as complete (code written, needs testing)
- Document architectural change (5 modular Info Box widgets)
- Add deliverables and commit hashes
- Add 'TESTING NEEDED' to all acceptance criteria
- Defer optional widgets (2.5-2.7) to post-v2.0
- Update Epic 2 status to 'In Progress (Testing Phase)'
- Note: Integration started prematurely - need to test first
- Create dashboardTemplate.html with dashboard container structure
- Dashboard header with tab navigation and control buttons
- Edit mode toggle, add widget, export/import layout buttons
- Add widget modal for selecting and adding widgets
- Widget configuration modal for widget settings
- Dashboard grid container for widget placement
- Create dashboardIntegration.js to handle dashboard initialization
- Initialize dashboard system and register all widgets
- Load dashboard template and inject into panel
- Set up event listeners for edit mode, add widget, export/import
- Create default layout with all core widgets
- Provide refreshDashboard() for updating widgets after data changes
- Support for fallback inline template if file load fails
- Comprehensive inventory management with 3 sub-tabs (On Person/Stored/Assets)
- List/Grid view modes per sub-tab with toggle buttons
- Storage locations with add/remove/collapse functionality
- Full CRUD operations for items (add/edit/remove)
- Inline forms for adding items and locations with Enter/Escape support
- Per-widget instance state management for tabs and view modes
- Import parseItems/serializeItems utilities for data handling
- Import sanitizeItemName/sanitizeLocationName for security
- Vanilla JS implementation, no jQuery dependencies
- All 4 core widgets now complete
Created modular, independently draggable Info Box widgets:
1. Calendar Widget (2x2):
- Date/weekday/month/year display
- Abbreviated display with full edit
- Editable date components
2. Weather Widget (3x2):
- Weather emoji + forecast text
- Fully editable emoji and text
3. Temperature Widget (2x2):
- Animated thermometer visualization
- Color-coded (blue < 10°C, green < 25°C, red ≥ 25°C)
- Editable temperature value
4. Clock Widget (2x2):
- Analog clock with hour/minute hands
- Real-time hand positioning based on time
- Editable time display
5. Location Widget (6x2):
- Map background with marker
- Editable location text
- Responsive width
All widgets:
- Share common infoBox data source
- Parse mixed emoji/text formats
- Handle missing data gracefully
- Update shared data on edit
- Vanilla JS (no jQuery)
- Mobile-friendly editable fields
Epic 2 progress: 2/4 core widget groups complete
Total widgets created: 6 (1 User Stats + 5 Info Box widgets)
- Created LayoutPersistence class with full save/load/import/export
- Implemented debounced auto-save (500ms after changes)
- Added manual save, export (JSON download), import (file picker)
- Added reset to default with confirmation
- Comprehensive dashboard validation
- Event-driven architecture with onChange listeners
- Save status indicator with real-time updates
- Event log for all persistence operations
- Auto-load saved layout on startup
- Complete integration test with all systems
Task 1.8 complete in <15 minutes (estimated 2-3 days)
EPIC 1: DASHBOARD INFRASTRUCTURE COMPLETE! 🎉
- Change resize handles from hover-only to always visible in edit mode
- Handles now show at 60% opacity in edit mode
- Brighten to 100% opacity on hover for visual feedback
- Update UI hint to explicitly mention green dots on corners/edges
- Makes resize functionality more discoverable
- Improves UX by showing affordances clearly
- Add event target check in DragDropHandler to ignore resize handles
- Add event target check to ignore widget edit controls
- Use e.target.closest() to check parent elements
- Add e.stopPropagation() in resize handle event handlers
- Replace simplified ResizeHandler with fully functional version
- Now resize handles work correctly without triggering drag
- Both mouse and touch events properly handled
- Fixes integration issue where resizing always triggered dragging