Commit Graph

410 Commits

Author SHA1 Message Date
Lucas 'Paperboy' Rose-Winters 9f92c4af87 feat(dashboard): add quest widget + fix 4-tab header layout
Quest Widget Integration:
- Created questsWidget.js with Main/Optional quest sub-tabs
- Added dedicated Quests tab (4th tab after Inventory)
- Registered quest widget in dashboardIntegration.js
- Widget features: inline editing, add/remove quests, contenteditable
- Fixed tab switching to use inline re-rendering (not full widget render)

Header Layout Fixes (4+ Tabs):
- Changed header flex-wrap from wrap to nowrap (prevents button wrapping)
- Added icon-only mode for 4+ tabs (disables hover expansion)
- Tab count detection in renderTabs() adds rpg-tabs-icon-only class
- Prevents layout breaking when tabs expand on hover

Technical Details:
- Quest widget follows inventory widget pattern (sub-tabs, per-instance state)
- Split event handlers: attachQuestHandlers (tabs) + attachQuestContentHandlers (buttons)
- Tab switching updates innerHTML inline and re-attaches content handlers
- Default size: 2w × 5h, category: 'scene'

Benefits:
- Quest tracking fully integrated with Dashboard v2 drag/drop
- No header wrapping issues with 4 tabs
- Cleaner icon-only UX when space is constrained
- Horizontal scrolling handles overflow gracefully
2025-10-30 08:40:46 +11:00
Lucas 'Paperboy' Rose-Winters ad2efa55f0 merge: resolve conflicts with upstream/main
Merged upstream/main into feat/v2-widget-dashboard-system branch.

Key conflict resolutions:
- index.js: Added renderQuests() to Dashboard v2 fallback rendering
- state.js: Combined memoryMessagesToProcess with Dashboard v2 config
- apiClient.js: Combined refreshDashboard() and renderQuests() calls
- style.css: Kept Dashboard v2 mobile refresh button styles

New features from upstream:
- Quest tracking system (renderQuests, quests.js)
- Memory recollection system
- Lorebook limiter feature
- Various parser and prompt builder improvements
2025-10-30 08:26:19 +11:00
Lucas 'Paperboy' Rose-Winters e5e3e43aa1 perf(dashboard): disable console logging in hot-path files
Add DEBUG flag to disable console.log/warn in critical performance paths
while preserving console.error for actual errors. This eliminates ~80ms
of logging overhead during tab switches on mobile devices.

Modified files (hot-path only):
- dashboardManager.js (orchestrator, called for every widget)
- editModeManager.js (disableContentEditing on tab switch)
- gridEngine.js (positioning calculations for every widget)
- dragDrop.js (initWidget called for every widget)
- resizeHandler.js (initWidget called for every widget)

Performance impact:
- Before: ~40 console.log calls per tab switch (10 widgets)
- After: 0 console calls (no-op functions)
- Measured improvement: Tab switching now fast enough on mobile
  (slight slowdown during screen recording is expected overhead)

The DEBUG flag can be set to true for debugging when needed.
This approach avoids syntax errors from commenting multi-line statements.

Total optimization across all commits:
- Phase 1: Removed redundant global disable (2 queries saved)
- Phase 2: Replaced inline disabling with single global pass (18 queries saved)
- Phase 3: Disabled console logging (80ms saved on mobile)
- Result: ~200ms improvement on mobile devices
2025-10-30 08:07:53 +11:00
Lucas 'Paperboy' Rose-Winters 8abaa740c7 perf(dashboard): optimize content editing disable to use single global pass
Replace per-widget inline disabling (2N queries) with single global
disable pass after all widgets rendered (2 queries total). This reduces
DOM queries from 20 to 2 for a typical 10-widget tab, providing a 10x
performance improvement on mobile devices.

Changes:
- Remove inline querySelectorAll from renderWidgetContent()
  (was running 2 queries per widget during render loop)
- Add single synchronous disableContentEditing() call in onTabChange()
  after all widgets rendered (2 queries total)
- Remove redundant disableContentEditing() call from syncAllControls()
  (was duplicate of enterEditMode() call)

Performance impact:
- Before: 22 queries (20 inline + 2 global redundant)
- Phase 1: 20 queries (20 inline only, removed redundant global)
- Phase 2: 2 queries (2 global only, removed inline)
- Result: 10x reduction in DOM queries per tab switch

On mobile devices with 2-4x slower DOM performance, this should
reduce tab switching delay from 200-500ms to 20-50ms.
2025-10-30 07:42:26 +11:00
Lucas 'Paperboy' Rose-Winters 4984c02fd1 perf(dashboard): remove redundant content editing disable on tab switch
Remove global disableContentEditing() call in onTabChange() as it's
redundant - inline disabling in renderWidgetContent() already handles
all newly rendered widgets. This eliminates 2 global DOM queries per
tab switch, improving mobile performance by ~30ms.

The double-disable pattern was causing 22 DOM queries per tab switch
(20 inline + 2 global), which on mobile devices (2-4x slower DOM)
resulted in 200-500ms delays.

Root cause analysis:
- Commit a330ea9 added inline disabling per widget (necessary)
- Commit acb6da0 added global disabling in onTabChange (redundant)
- Mobile DOM queries are 2-4x slower than desktop
- querySelectorAll() on entire container is expensive

Fix removes the redundant global disable while keeping the necessary
inline disabling that runs when each widget is rendered.
2025-10-29 23:00:10 +11:00
Lucas 'Paperboy' Rose-Winters d3b0eccfe8 fix(resize): fix excessive sensitivity by converting rem to pixels
The resize handler was mixing rem and pixel units without proper conversion,
causing widgets to fly wildly off screen with small mouse movements.

Root cause:
- rowHeight and gap were stored as rem values (e.g., 5 rem, 0.75 rem)
- Delta calculations divided pixel movements by rem values directly
- This caused ~14x excessive sensitivity

Fix:
- Add remToPixels() conversions for gap and rowHeight before calculations
- Use pixel values (gapPx, rowHeightPx) in all delta-to-grid-unit conversions
- Matches the correct pattern used in drag handler and gridEngine.snapToCell()

Example:
- Before: 20px movement / 5 rem = 3.48 grid units (way too much!)
- After: 20px movement / 80px = 0.22 grid units (smooth and predictable)

Fixes both desktop and mobile resize sensitivity issues.

File: src/systems/dashboard/resizeHandler.js
Lines: 333-343 (updateResizeSize method)
2025-10-29 22:15:34 +11:00
Lucas 'Paperboy' Rose-Winters acb6da023a feat(dashboard): add confirmations, fix UX issues, and optimize grid rendering
BREAKING CHANGE: applyDashboardConfig() now accepts optional second parameter for optimization

Add auto-arrange confirmation dialog:
- Add warning popup before auto-arranging widgets across all tabs
- Follows same pattern as reset layout confirmation
- Prevents accidental destructive operations

Fix text selection interference:
- Apply user-select: none to entire .rpg-widget in edit mode
- Previously only applied to .rpg-widget-content
- Prevents text selection when dragging widgets, especially in attribute boxes
- Improves drag interaction on both desktop and mobile

Fix edit controls visibility:
- Add CSS rule to completely hide edit controls outside edit mode
- Controls now properly hidden when not in edit mode
- Settings button (⚙) kept for future widget configuration

Fix input disabling in edit mode:
- Call disableContentEditing() after tab switches in onTabChange()
- Call disableContentEditing() in syncAllControls()
- Ensures text fields remain non-editable in edit mode after all operations

Fix resize grid background rendering:
- Copy drag handler grid logic EXACTLY to resize handler
- Use gridEngine.calculateGridHeight(widgets) instead of manual calculation
- Add proper remToPixels() conversions for gap and rowHeight
- Pass widgets array through initWidget() and startResize()
- Grid now renders correctly during resize, matching drag behavior

Optimize layout operations:
- Add skipInitialSwitch option to applyDashboardConfig()
- Prevents redundant clearGrid() calls during resetLayout()
- Defers rendering until after layout calculations complete

Files modified:
- dashboardIntegration.js: Auto-arrange confirmation
- dashboardManager.js: skipInitialSwitch option, input disabling, widgets array
- editModeManager.js: Input disabling in syncAllControls()
- resizeHandler.js: Grid rendering fixes with proper unit conversions
- style.css: Text selection prevention, edit controls visibility
2025-10-29 21:17:48 +11:00
Spicy_Marinara 87cfcb6946 Fix: Use custom stat names in AI prompt instructions
- Updated generateTrackerInstructions() to use extensionSettings.statNames
- AI now receives custom stat names in format specification
- Ensures consistency between displayed names, tracker data, and AI instructions
2025-10-29 10:17:00 +01:00
Lucas 'Paperboy' Rose-Winters 79d6fcbfe7 chore: remove investigation documentation file 2025-10-29 19:34:18 +11:00
Lucas 'Paperboy' Rose-Winters 9fbc35dbd9 refactor(dashboard): move controls to overlays and fix mobile/positioning issues
BREAKING CHANGES:
- Resize handles and edit controls now render in separate overlay containers
- This prevents widget overflow and scrollbar issues

Major Changes:

Overlay System Refactor:
- Create overlay containers for resize handles and edit controls
- Append handles/controls to overlays instead of widget DOM
- Fix position calculations using offsetLeft/Top instead of getBoundingClientRect
- Add position sync after resize/drag/reposition operations
- Add cleanup methods when switching tabs

Mobile Fixes:
- Add pointer/touch event support for Add Widget button
- Fix file upload trigger for iOS/Android compatibility
- Move modals to document.body with flex centering
- Fix modal button font-sizes (rem-based instead of vw)
- Add mobile-responsive styling for widget dialog

Bug Fixes:
- Fix getActiveTabId() calls (use activeTabId property instead)
- Fix file input disabled state (exclude type="file" from edit mode disable)
- Fix Add Widget modal registry.getAll() destructuring (objects not arrays)
- Fix edit/delete button hover (keep visible when hovering buttons)
- Fix reset layout to restore deleted widgets (regenerate default layout)

UI Improvements:
- No more scrollbars from resize handles
- Consistent button visibility in edit mode
- Touch-friendly button sizes on mobile (44px min-height)
- Single-column widget grid on mobile
- Proper z-index stacking for overlays

Files Changed:
- dashboardManager.js: Overlay container management, sync methods
- resizeHandler.js: Append to overlay, update positioning
- editModeManager.js: Append to overlay, hover behavior, sync/cleanup
- dashboardIntegration.js: Mobile touch events, file upload, modal fixes
- dashboardTemplate.html: File input accessibility
- style.css: Modal button font-sizes, mobile optimizations
- RESIZE_HANDLES_INVESTIGATION.md: Technical investigation documentation
2025-10-29 19:07:01 +11:00
Spicy_Marinara 13019c65ee Fix: Strip thinking tags from parser and persist tracker data on page refresh
- Added removal of <think> and <thinking> tags from AI responses before parsing
- Fixed Info Box display to use committedTrackerData as fallback after page refresh
- Fixed Present Characters display to use committedTrackerData as fallback after page refresh
- Fixed 4-part character format handling in updateCharacterField to preserve thoughts
- Ensures Recent Events and all tracker data persist correctly across page reloads
2025-10-28 18:07:15 +01:00
Lucas 'Paperboy' Rose-Winters ddb2f8c222 fix(modal): resolve button font-size CSS cascade conflict
- 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)
2025-10-28 18:45:47 +11:00
Lucas 'Paperboy' Rose-Winters ded1b62963 fix(mobile): add explicit font-size to confirmation dialog body text
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.
2025-10-28 15:12:58 +11:00
Lucas 'Paperboy' Rose-Winters a888c5ccd6 fix(mobile): apply same centering and viewport fixes to dice roller modal
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
2025-10-28 14:55:59 +11:00
Lucas 'Paperboy' Rose-Winters 9e09b57618 fix(mobile): add flex centering to modal container and use dvh for viewport
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
2025-10-28 11:14:51 +11:00
Lucas 'Paperboy' Rose-Winters 0fbdf41678 fix(mobile): move modals to document.body to escape panel DOM constraints
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
2025-10-28 10:34:49 +11:00
Lucas 'Paperboy' Rose-Winters 92af1a4942 fix(mobile): improve modal positioning and scaling on mobile devices
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.
2025-10-27 23:05:11 +11:00
Lucas 'Paperboy' Rose-Winters fb25277db4 fix(dashboard): replace all hardcoded emoji icons with Font Awesome
Fix inconsistent tab icon rendering by replacing hardcoded emoji icons
throughout the codebase with Font Awesome equivalents:

- distributeWidgetsByCategory(): Replace emojis in auto-layout tab creation
  - Status tab: 📊 → fa-solid fa-user
  - Scene tab: 🌍 → fa-solid fa-map
  - Social tab: 👥 → fa-solid fa-users
  - Inventory tab: 🎒 → fa-solid fa-bag-shopping

- applyDashboardConfig(): Update fallback icon from 📄 → fa-solid fa-file

These hardcoded emojis bypassed the migration system, causing icons to
disappear after operations like auto-arrange, reset layout, or page refresh.

Resolves inconsistent icon rendering across all dashboard operations.
2025-10-27 22:25:03 +11:00
Lucas 'Paperboy' Rose-Winters 7628bb84c1 feat(dashboard): replace emojis with Font Awesome, add theme support, and styled dialogs
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
2025-10-27 20:41:36 +11:00
Lucas 'Paperboy' Rose-Winters c39d348a81 fix(dashboard): properly filter dropdown menu buttons based on pre-hidden visibility
- 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
2025-10-27 20:06:25 +11:00
Spicy_Marinara a063ae780b Add editable stat names, fix clear cache for quests, update tracker text to use custom stat names 2025-10-27 09:45:50 +01:00
Lucas 'Paperboy' Rose-Winters a330ea9b98 fix(dashboard): disable text editing on widget re-renders in edit mode
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.
2025-10-27 16:10:08 +11:00
Lucas 'Paperboy' Rose-Winters f566ad1d93 feat(dashboard): implement responsive header with tab scrolling and overflow menus
Add comprehensive responsive header system with Google-quality UX:

Tab Navigation:
- Add TabScrollManager for horizontal scrolling tabs
- Left/Right navigation arrows appear when scrollable
- Edge fade indicators show more content exists
- Smooth scroll behavior with momentum
- Progressive sizing: full → icon+name → icon-only
- Automatic scroll position tracking

Button Overflow System:
- Add HeaderOverflowManager with ResizeObserver
- Three responsive modes based on container width:
  * Full mode (>900px): all buttons visible
  * Overflow mode (500-900px): priority + "More" (⋮) menu
  * Compact mode (<500px): priority + hamburger (☰) menu
- Priority buttons (Lock + Edit) always visible
- Smooth transitions between modes

Dropdown Menu:
- Professional slide-down animation
- Full keyboard navigation (arrows, Home, End, Escape)
- Click-outside-to-close behavior
- ARIA attributes for accessibility
- Focus management and trap
- Auto-refresh on edit mode changes
- High z-index (10003) ensures visibility above all UI

Cross-Tab Widget Dragging:
- Add collision detection for widget placement
- Implement moveWidgetToTab() with collision avoidance
- Find available positions in target tab automatically
- Update dragDrop.js to detect tab hover
- Visual feedback with tab highlight on hover
- Proper widget positioning after cross-tab move

Additional Features:
- Sort Tab button for current-tab-only auto-layout
- Mobile optimizations with compact buttons
- Responsive breakpoints at 768px and 480px
- Hardware-accelerated animations
- Touch-friendly 44px minimum targets

Files changed:
- New: tabScrollManager.js, headerOverflowManager.js
- Modified: dashboardTemplate.html, dashboardIntegration.js
- Modified: dashboardManager.js, dragDrop.js, style.css
- Modified: editModeManager.js (lock state default)
2025-10-27 14:48:38 +11:00
Lucas 'Paperboy' Rose-Winters 45c5853dcb feat(dashboard): improve mobile inventory UX and fix desktop viewport overflow
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.
2025-10-27 10:18:07 +11:00
Spicy_Marinara e0164a9ca9 Fix tracker commit logic to prevent overwriting on refresh 2025-10-26 23:25:05 +01:00
Spicy_Marinara 141a3f4bec Fix extension loading, enhance theming, add horizontal scrolling, improve emoji parsing, rename to Main Quests 2025-10-26 22:31:21 +01:00
Lucas 'Paperboy' Rose-Winters 04bb52ed71 feat(dashboard): improve mood widget readability with balanced two-line layout
- 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.
2025-10-26 21:23:11 +11:00
Lucas 'Paperboy' Rose-Winters bd56f24c45 fix(dashboard): correct auto-layout boundary check to eliminate empty space at bottom
- 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.
2025-10-26 16:45:49 +11:00
Lucas 'Paperboy' Rose-Winters 6af499b07a fix(dashboard): resolve presentCharacters widget styling and auto-layout issues
- 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
2025-10-26 14:52:02 +11:00
Lucas 'Paperboy' Rose-Winters 8317471922 fix(dashboard): improve edit mode UX and remove redundant weather subtitle
- 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
2025-10-26 10:29:55 +11:00
Lucas 'Paperboy' Rose-Winters f84cbf794a feat(dashboard): add lock button to prevent accidental widget movement
- 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
2025-10-25 19:50:17 +11:00
Lucas 'Paperboy' Rose-Winters d6c5101a7e feat(dashboard): implement movement threshold for widget dragging to allow clicks
- 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
2025-10-25 19:32:29 +11:00
Lucas 'Paperboy' Rose-Winters 101404d617 fix(dashboard): prevent resize handle overlap and clipping
- 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)
2025-10-25 19:04:36 +11:00
Lucas 'Paperboy' Rose-Winters 4ea1c55a75 fix(dashboard): correct rem-to-pixel conversion for drag overlay grid cells
- 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()
2025-10-25 18:51:20 +11:00
Lucas 'Paperboy' Rose-Winters e031643cd5 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
2025-10-24 18:55:38 +11:00
Lucas 'Paperboy' Rose-Winters ac5bd22e55 feat(dashboard): optimize 3-4 column desktop layout + fix mobile widget issues
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
2025-10-24 16:36:18 +11:00
Lucas 'Paperboy' Rose-Winters 4994c09563 feat(dashboard): implement column-aware widget sizing for optimal mobile/desktop layouts
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
2025-10-24 15:50:55 +11:00
Lucas 'Paperboy' Rose-Winters 77b5092e57 fix(mobile): eliminate contenteditable bottom padding in dashboard v2 widgets
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
2025-10-24 15:31:19 +11:00
Lucas 'Paperboy' Rose-Winters 63a02fd197 fix(dashboard): sync widget data and fix refresh on chat load
- 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.
2025-10-24 12:44:11 +11:00
Lucas 'Paperboy' Rose-Winters 0d179d22fc fix(mood): reduce font sizes to fit emoji and conditions in 1x1 widget
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.
2025-10-24 11:52:35 +11:00
Lucas 'Paperboy' Rose-Winters eb4ac57dae fix(avatars): use proper getThumbnailUrl API to eliminate 404 errors
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.
2025-10-24 00:26:51 +11:00
Lucas 'Paperboy' Rose-Winters f0f04297f7 fix(userInfo): fix avatar 404 errors and improve layout/scaling
**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.
2025-10-23 22:18:02 +11:00
Lucas 'Paperboy' Rose-Winters 3dd7b017a6 feat(dashboard): implement smart widget scaling and improved auto-layout
- 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.
2025-10-23 22:08:04 +11:00
Lucas 'Paperboy' Rose-Winters f61e6390fb refactor(ui): move 'Enable Immersive HTML' toggle to settings panel
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
2025-10-23 20:06:54 +11:00
Lucas 'Paperboy' Rose-Winters 380d717b30 feat(dashboard): implement smart auto-layout with expansion and better defaults
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.
2025-10-23 20:03:19 +11:00
Lucas 'Paperboy' Rose-Winters c4485971fa fix(dashboard): fix persistent px values, auto-layout, widget loss, gaps, and tabs
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.
2025-10-23 19:32:27 +11:00
Lucas 'Paperboy' Rose-Winters 79582070f0 fix(dashboard): fix attributes overflow and improve tab distribution
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
2025-10-23 18:48:25 +11:00
Lucas 'Paperboy' Rose-Winters 5dd7dcb27b feat(dashboard): improve widget scaling and fix attribute scrollbar
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
2025-10-23 18:33:01 +11:00
Lucas 'Paperboy' Rose-Winters b3a86d4609 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
2025-10-23 18:06:44 +11:00
Lucas 'Paperboy' Rose-Winters aeb3ad1b9b feat(dashboard): split user
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.
2025-10-23 15:48:02 +11:00