- Scope modal button selectors to prevent dashboard styles from overriding
- Use .rpg-modal and .rpg-confirm-modal prefixes for higher specificity
- Desktop modal buttons: 1rem (consistent, readable)
- Mobile modal buttons: 1.05rem (touch-friendly)
- Dashboard buttons unchanged: keep 1.4vw viewport-based sizing
- Fixes buttons being too large on desktop (~27px) and too small on mobile (~5px)
Add explicit font-size using rem units to confirmation dialog body text
to ensure it's readable on all screen sizes.
Changes:
- .rpg-confirm-body p: Add font-size: 1rem (base size)
- Mobile (@max-width: 768px): Override to 0.95rem for mobile screens
Previously, the body text had no explicit font-size and was inheriting
from parent, causing it to appear tiny on mobile devices. Now uses
proper rem-based sizing that scales appropriately.
Apply the same mobile modal fixes to the dice roller that were applied
to the confirmation dialogs:
1. Move modal to document.body on first open
2. Use dynamic viewport height (dvh) for mobile browsers
Changes:
1. src/systems/ui/modals.js - DiceModal.open():
- Check if modal parent is not already document.body
- Move modal to document.body to escape any container constraints
- Ensures proper viewport-level positioning and z-index stacking
2. style.css - Add mobile media query for dice popup:
- Set height: 100dvh on .rpg-dice-popup for mobile
- Update --modal-max-height to 70dvh (from 70vh)
- Apply dynamic height to .rpg-dice-popup-content
- Accounts for mobile browser chrome (address bar, toolbars)
Result:
- Dice roller modal now properly centered on mobile viewport
- Handles dynamic mobile browser toolbars correctly
- Consistent behavior with confirmation dialogs
Fix modal centering on mobile by adding flexbox properties to the
document-body-modals container and using dynamic viewport height.
Root cause: The container had position:fixed and inset:0 but was missing
display:flex, align-items:center, and justify-content:center. Without these,
the modal child wasn't being centered within the container.
Additionally, mobile browsers have dynamic toolbars (address bar, etc.) that
affect viewport height. Standard vh units don't account for this, causing
modals to appear off-center when toolbars are visible/hidden.
Changes:
1. confirmDialog.js - Both showConfirmDialog() and showAlertDialog():
- Add 'display: flex; align-items: center; justify-content: center;'
to bodyModalsContainer.style.cssText
- Container now properly centers its modal child
2. style.css - Mobile media query (@max-width: 768px):
- Add height: 100dvh to #document-body-modals and .rpg-modal
- Dynamic viewport height (dvh) adjusts for mobile browser chrome
- Add max-height: 85dvh fallback alongside 85vh
- Ensures modal uses full available viewport height
Result:
- Modals now properly centered in mobile viewport
- Accounts for dynamic mobile browser toolbars
- Works across different mobile browsers and orientations
Fix mobile modal positioning by moving modals to document.body on first use.
Root cause: Modals were nested inside .rpg-panel which has 'transform' in
its transition property (line 40 of style.css). This creates a containing
block that constrains position:fixed children to the panel viewport instead
of the document viewport, causing modals to be cut off on mobile.
Changes:
1. confirmDialog.js - Modified showConfirmDialog() and showAlertDialog():
- Check if modal is already in document.body container
- Create 'document-body-modals' container at body level (once)
- Move modal to body container to escape panel constraints
- Container has pointer-events: none to pass clicks through
- Individual modals have pointer-events: auto to receive clicks
2. style.css - Added pointer-events: auto to .rpg-modal:
- Ensures clicks work when modal is in pointer-events: none container
Result:
- Modals now render over entire SillyTavern viewport
- Properly centered with full z-index stacking
- No longer constrained by panel's transform/stacking context
- Works correctly on both desktop and mobile
Fix mobile modal issues where popups appeared too high, were cut off,
and didn't scale properly for small screens:
Changes:
1. Add 1rem padding to .rpg-modal overlay to prevent content from
touching screen edges
2. Update .rpg-confirm-content width calculation from 90% to
calc(100% - 2rem) to account for modal padding
3. Add comprehensive mobile media query (@max-width: 768px) with:
- Better max-height (85vh instead of 80vh) to account for mobile
browser chrome (URL bar, toolbars)
- Prevent horizontal overflow with calc(100vw - 2rem)
- Scale down padding (1rem → 0.75rem) for better space utilization
- Scale down icon (1.75rem → 1.5rem) and header fonts (1.5rem → 1rem)
- Touch-friendly button sizing (44px min-height for accessibility)
Both confirmation dialogs and dice roll popups now display properly
centered with appropriate spacing and scaling on mobile viewports.
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
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.
- 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
- 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
- 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: 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.
**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.
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
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
The mobile refresh button was always visible on mobile. It should only
appear when BOTH conditions are met:
- RPG panel is open
- Generation mode is Separate (not Together)
Changes:
- Added opacity: 0 and pointer-events: none to base .rpg-mobile-refresh
- CSS shows button when panel open AND not .rpg-hidden-mode class
- Updated updateGenerationModeUI() to toggle .rpg-hidden-mode on mobile button
- Together mode: adds .rpg-hidden-mode class (keeps button hidden)
- Separate mode: removes .rpg-hidden-mode class (allows CSS to show it)
Result: Mobile refresh FAB only appears when panel is open AND in
Separate mode. Stays hidden when panel closed OR in Together mode.
Reverted HTML replacement approach and restored the cleaner CSS-based
animation from commit 1855085.
Previous (wrong) approach:
- Replaced button HTML with spinner
- Modified both desktop and mobile buttons in apiClient.js
- Messy and inconsistent
Restored (correct) approach:
- Add/remove .spinning CSS class in click handler
- CSS animates only the icon inside the button
- Button itself stays unchanged
- Much cleaner implementation
Changes:
- Reverted apiClient.js changes from commit 9a49433
- Added .spinning CSS class and @keyframes rpg-spin
- Updated index.js click handler to bind both buttons
- Uses addClass/removeClass for clean animation control
- Includes drag detection to prevent accidental clicks
Now the mobile FAB icon spins smoothly when refreshing!
Mobile refresh button was created in HTML but had no CSS styling,
making it invisible. Desktop refresh button was showing on mobile
with wrong sizing.
Changes:
- Added .rpg-mobile-refresh FAB styles (44px, draggable, etc.)
- Show mobile refresh FAB on mobile viewports
- Hide desktop #rpg-manual-update button on mobile
- Added responsive icon sizing for mobile refresh button
Fixes issue where users only saw the desktop refresh button with
incorrect DPI/sizing on mobile devices.
PROBLEM:
- Existing users with saved off-screen FAB positions can't see buttons
- No way to reset positions without clearing all extension settings
- Salixfire and other users on Xiaomi/other devices need safe positions
SOLUTION:
Added "Reset Button Positions" button in Advanced settings section
IMPLEMENTATION:
1. template.html (lines 241-249):
- Added reset button in Advanced section after Clear Cache button
- Blue-styled button with rotate icon
- Help text explains it resets FAB positions to top-left
2. index.js (lines 361-390):
- Added click handler for reset button
- Resets all 3 FAB positions to safe top-left defaults:
* Mobile toggle: top + 20px, left: 12px
* Refresh: top + 80px, left: 12px
* Debug: top + 140px, left: 12px
- Saves settings immediately
- Applies CSS positions to visible buttons (no page refresh needed)
- Shows success toast notification
3. style.css (lines 2057-2083, 4123-4125):
- Added .rpg-btn-reset-fab styles matching clear cache pattern
- Blue color scheme (vs red for destructive clear cache)
- Same sizing, padding, transitions as other buttons
- Mobile responsive font-size with clamp()
USAGE:
Users experiencing off-screen buttons can now:
1. Open RPG Companion settings (gear icon)
2. Scroll to Advanced section
3. Click "Reset Button Positions"
4. All FAB buttons instantly move to safe top-left positions
This fixes the issue for Salixfire and any other users who:
- Have buttons saved in off-screen positions
- Can't scroll to find buttons
- Need to reset without clearing all settings
Works immediately without page refresh or extension reload.
PROBLEM:
- Debug logs only accessible via browser console (impractical on mobile)
- User (Salixfire) reporting parsing issues but can't debug on mobile device
- Need mobile-friendly debug mode for troubleshooting data display issues
SOLUTION:
Implemented debug toggle FAB button following exact pattern of existing mobile FABs:
Files Changed:
- src/core/state.js: Added debugFabPosition and debugMode to extensionSettings
- src/core/config.js: Added debugFabPosition to defaultSettings (reference)
- index.js: Created debug toggle button, imported setupDebugButtonDrag
- style.css: Added debug toggle CSS matching mobile FAB pattern (44px, grab cursor, theme colors)
- src/systems/ui/mobile.js: Added setupDebugButtonDrag() with drag-to-reposition
- src/systems/ui/debug.js: Removed button creation, added just-dragged check, updated visibility control
Implementation Details:
- Button created in index.js (not debug.js) following mobile FAB pattern
- CSS matches mobile toggle/refresh buttons (44px, theme colors, grab cursor, user-select: none)
- Drag support with touch/mouse handlers, 200ms/10px threshold
- Position saved to extensionSettings.debugFabPosition
- Just-dragged flag prevents accidental clicks after drag
- Mobile (≤1000px): slide from right with rpg-mobile-open/closing classes
- Desktop (>1000px): slide from bottom with rpg-debug-open class
- Event delegation for reliable click handling
- Default position: bottom 140px, left 20px (below other FABs)
Bug Fix:
- Initial implementation had debugFabPosition only in config.js
- extensionSettings uses state.js as source, not config.js
- Without debugFabPosition in state.js, button had no position and was invisible
- Now properly initialized in both files
The debug button is hidden by default (debugMode: false) and shown when user enables debug mode in RPG Companion settings. This allows Salixfire to view parser logs on mobile and troubleshoot the data display issues.
Added event.preventDefault() and event.stopPropagation() to close button handler
to prevent any interference from parent elements.
Also added pointer-events: none to button icons to ensure clicks on the icon
register on the button itself, not the <i> element.
Changes:
- src/systems/ui/debug.js: Added e.preventDefault/stopPropagation to close handler
- src/systems/ui/debug.js: Added console.log for debugging
- style.css: Added pointer-events: none to .rpg-debug-actions button i
Add comprehensive debug logging system that's accessible on mobile devices
where browser console is impractical.
**New Features:**
- Debug mode toggle in extension settings (🔍 Debug Mode)
- Mobile-friendly debug panel with slide-up UI
- Red bug FAB button to toggle debug log viewer
- Copy logs to clipboard functionality
- Auto-scrolling log display with timestamps
- Stores last 100 log entries to prevent memory issues
**Parser Enhancements:**
- All parser logs now use debugLog() helper function
- Logs only appear in UI when debug mode is enabled
- Console.log still works for desktop debugging
- Full visibility into parsing pipeline:
- Raw AI response preview
- Code blocks found and matched
- Stats extraction (health, energy, mood, etc.)
- Inventory parsing (v1 and v2)
- Final values saved to settings
**UI Components:**
- src/systems/ui/debug.js: Debug panel creation and management
- style.css: Mobile-first debug panel styles (FAB + slide-up panel)
- Desktop view: Smaller panel in bottom-right corner
**Settings:**
- src/core/config.js: Added debugMode default (false)
- src/core/state.js: Added debug logs storage array
- settings.html: Added debug mode checkbox
- index.js: Wire up debug toggle and initialize UI
**Usage for Mobile Users:**
1. Enable "Debug Mode" in RPG Companion settings
2. Red bug button appears (bottom-left)
3. Tap bug button to view logs
4. Use "Copy" to share logs for troubleshooting
5. Logs show exactly what AI generated and how parser handled it
This addresses the issue where users on mobile can't access browser
console to diagnose parsing problems (vanishing attributes, placeholder
characters, etc.). Now they can view and share logs directly.
- Reduced gap from 6px to 3px for more compact display
- Reduced vertical padding to 4px (from clamp(4px, 0.6vh, 6px))
- Tightened line-height from 1.3 to 1.2
- Reduced emoji size slightly (clamp(14px, 3.5vw, 18px))
- Frees up vertical space for attribute boxes and avatar on mobile
- Added min-height: 3em to rpg-calendar-day on mobile
- Increased vertical padding to 0.75em (from 0.25em default)
- Added line-height: 1.2 for tighter text
- Prevents date text from being pushed too high and cutting into box above
- Flexbox centering now has enough space to properly center content
- Moved refresh button creation from template.html to index.js (appended to body)
- Created new CSS class .rpg-mobile-refresh (exact copy of .rpg-mobile-toggle pattern)
- Uses opacity for show/hide instead of display (CSS controls visibility based on panel state)
- Show when panel open (body:has(.rpg-panel.rpg-mobile-open))
- Hide when panel closed (opacity: 0, pointer-events: none)
- Updated constrainFabToViewport() to accept optional button parameter
- Automatically detects which button and uses correct settings (mobileFabPosition or mobileRefreshPosition)
- Simplified updateGenerationModeUI() - CSS handles visibility
- Kept full drag functionality with touch and mouse support
- Button positioned via JavaScript with saved position
- z-index: 1001 (above panel, below toggle at 10002)
- Changed z-index from 99 to 1001
- Now properly layers: panel (1000) < refresh button (1001) < FAB toggle (10002)
- Refresh button is now visible when panel is open
- Changed .rpg-level-value padding from clamp(1px, 0.2vh, 2px) 0.375em to 0 0.375em
- Added mobile-specific override to prevent level value from inheriting large touch-friendly padding
- Level value now stays compact and properly aligned on mobile (no min-height, no vertical padding)
- Fixes misalignment and unwanted vertical space below level value
- Repositioned mobile refresh button to bottom-right (80px from bottom)
- Implemented full drag-to-reposition functionality
* Touch and mouse support with 200ms/10px threshold
* RequestAnimationFrame for smooth dragging
* Position saved to extensionSettings.mobileRefreshPosition
* Viewport constraints with 10px padding
- Fixed sticky tap highlight issue
* Added -webkit-tap-highlight-color: transparent
* Added blur() on click to remove focus
* Set user-select: none and touch-action: none
- Show/hide based on panel state
* Only visible when panel is expanded (rpg-mobile-open)
* Listens to rpg-panel-toggled events
* Auto-hides when panel closes
- Prevent accidental refresh after drag
* just-dragged flag prevents click for 100ms
* Click handler checks flag before executing
- Changed from absolute to fixed positioning for viewport-wide dragging
- Added mobileRefreshPosition to default settings (bottom: 80px, right: 20px)
- z-index: 99 (below FAB toggle at 100)
**Changes:**
1. Move button to float over all tabs (not just Stats)
- Removed from userStats.js HTML
- Added to template.html as floating absolute element
- Now visible on Status, Info, and Inventory tabs
2. Fix sticky black focus state
- Added :focus { outline: none } to CSS
- Call blur() after click to clear focus immediately
3. Add refresh animation
- Button spins during updateRPGData() call
- Smooth 0.8s rotation with @keyframes
- Uses .spinning class added/removed in JS
4. Improve theming and positioning
- Positioned absolute top-right (10px, 10px)
- Increased to 44px for better touch target
- z-index: 100 to float above content
- Already uses theme colors (--rpg-highlight, --rpg-text)
Mobile UX now:
✅ Button visible on all tabs (floating)
✅ Spins smoothly when refreshing
✅ No sticky black state after tap
✅ Properly themed across all themes