feat(dashboard): move edit mode controls to menu permanently

Reduces header button crowding by keeping edit controls in menu at all screen sizes.

Changes:
- Add .rpg-menu-only-btn class to Add/Export/Import/Done buttons
- Remove display toggling from EditModeManager (simpler state machine)
- Update HeaderOverflowManager to:
  - Always hide menu-only buttons (never show inline)
  - Mark them as available for menu (wasVisible = 'true')
  - Filter menu items based on edit mode state
  - Add setEditModeManager() for edit state access
- Wire editModeManager to headerOverflowManager in integration

Result:
- Full mode: 6 visible buttons (was 10 with edit mode active)
- Overflow mode: 3 priority + menu with 3 standard + 4 edit (when active)
- Compact mode: 3 priority + hamburger with all actions (filtered by edit state)

Edit mode controls (Add Widget, Export, Import, Done) now only appear in
dropdown/hamburger menu, never inline. This creates cleaner visual hierarchy
and eliminates layout jumping when toggling edit mode.

Existing menu refresh on edit mode toggle (line 305) ensures menu updates
with correct items when entering/exiting edit mode.
This commit is contained in:
Lucas 'Paperboy' Rose-Winters
2025-11-02 19:43:16 +11:00
parent 2cdad81cb8
commit 64d0fe41dd
4 changed files with 61 additions and 35 deletions
@@ -127,6 +127,11 @@ export async function initializeDashboard(dependencies) {
if (headerRight) {
headerOverflowManager = new HeaderOverflowManager(headerRight);
headerOverflowManager.init();
// Wire up editModeManager for menu filtering
if (dashboardManager?.editManager) {
headerOverflowManager.setEditModeManager(dashboardManager.editManager);
}
}
console.log('[RPG Companion] Dashboard v2 initialized successfully');
+4 -4
View File
@@ -37,19 +37,19 @@
<i class="fa-solid fa-arrow-down-short-wide"></i>
</button>
<button id="rpg-dashboard-add-widget" class="rpg-dashboard-btn rpg-add-widget-btn rpg-overflow-btn" style="display: none;" title="Add Widget" aria-label="Add widget">
<button id="rpg-dashboard-add-widget" class="rpg-dashboard-btn rpg-add-widget-btn rpg-overflow-btn rpg-menu-only-btn" style="display: none;" title="Add Widget" aria-label="Add widget">
<i class="fa-solid fa-plus"></i>
</button>
<button id="rpg-dashboard-export-layout" class="rpg-dashboard-btn rpg-export-btn rpg-overflow-btn" style="display: none;" title="Export Layout" aria-label="Export layout">
<button id="rpg-dashboard-export-layout" class="rpg-dashboard-btn rpg-export-btn rpg-overflow-btn rpg-menu-only-btn" style="display: none;" title="Export Layout" aria-label="Export layout">
<i class="fa-solid fa-download"></i>
</button>
<button id="rpg-dashboard-import-layout" class="rpg-dashboard-btn rpg-import-btn rpg-overflow-btn" style="display: none;" title="Import Layout" aria-label="Import layout">
<button id="rpg-dashboard-import-layout" class="rpg-dashboard-btn rpg-import-btn rpg-overflow-btn rpg-menu-only-btn" style="display: none;" title="Import Layout" aria-label="Import layout">
<i class="fa-solid fa-upload"></i>
</button>
<button id="rpg-dashboard-done-edit" class="rpg-dashboard-btn rpg-done-edit-btn rpg-overflow-btn" style="display: none;" title="Exit Edit Widget Mode" aria-label="Done editing">
<button id="rpg-dashboard-done-edit" class="rpg-dashboard-btn rpg-done-edit-btn rpg-overflow-btn rpg-menu-only-btn" style="display: none;" title="Exit Edit Widget Mode" aria-label="Done editing">
<i class="fa-solid fa-check"></i>
</button>
+2 -18
View File
@@ -59,18 +59,10 @@ export class EditModeManager {
// Store original layout for cancel
this.originalLayout = this.captureLayout();
// Hide edit mode button, show done button and edit mode controls
// Hide edit mode button (menu-only controls managed by headerOverflowManager)
const editModeBtn = document.querySelector('#rpg-dashboard-edit-mode');
const doneBtn = document.querySelector('#rpg-dashboard-done-edit');
const addWidgetBtn = document.querySelector('#rpg-dashboard-add-widget');
const exportBtn = document.querySelector('#rpg-dashboard-export-layout');
const importBtn = document.querySelector('#rpg-dashboard-import-layout');
if (editModeBtn) editModeBtn.style.display = 'none';
if (doneBtn) doneBtn.style.display = '';
if (addWidgetBtn) addWidgetBtn.style.display = '';
if (exportBtn) exportBtn.style.display = '';
if (importBtn) importBtn.style.display = '';
// Disable content editing to prevent keyboard from messing up layout
this.disableContentEditing();
@@ -112,18 +104,10 @@ export class EditModeManager {
// Re-enable content editing
this.enableContentEditing();
// Show edit mode button, hide done button and edit controls
// Show edit mode button (menu-only controls managed by headerOverflowManager)
const editModeBtn = document.querySelector('#rpg-dashboard-edit-mode');
const doneBtn = document.querySelector('#rpg-dashboard-done-edit');
const addWidgetBtn = document.querySelector('#rpg-dashboard-add-widget');
const exportBtn = document.querySelector('#rpg-dashboard-export-layout');
const importBtn = document.querySelector('#rpg-dashboard-import-layout');
if (editModeBtn) editModeBtn.style.display = '';
if (doneBtn) doneBtn.style.display = 'none';
if (addWidgetBtn) addWidgetBtn.style.display = 'none';
if (exportBtn) exportBtn.style.display = 'none';
if (importBtn) importBtn.style.display = 'none';
// Remove edit class from container
this.container.classList.remove('edit-mode');
+41 -4
View File
@@ -27,6 +27,7 @@ export class HeaderOverflowManager {
this.menuOpen = false;
this.resizeObserver = null;
this.resizeTimeout = null;
this.editModeManager = null; // Reference to EditModeManager for menu filtering
// Element references
this.priorityButtons = null;
@@ -42,6 +43,14 @@ export class HeaderOverflowManager {
this.boundClickOutside = this.handleClickOutside.bind(this);
}
/**
* Set EditModeManager reference for menu filtering
* @param {EditModeManager} editModeManager - Edit mode manager instance
*/
setEditModeManager(editModeManager) {
this.editModeManager = editModeManager;
}
/**
* Initialize the overflow manager
*/
@@ -138,18 +147,24 @@ export class HeaderOverflowManager {
}
/**
* Full Mode: Show all buttons
* Full Mode: Show all buttons except menu-only
*/
setFullMode() {
// Show all overflow buttons
// Show all overflow buttons except menu-only ones
this.overflowButtons.forEach(btn => {
// Menu-only buttons always stay hidden (managed by menu)
if (btn.classList.contains('rpg-menu-only-btn')) {
btn.style.display = 'none';
btn.dataset.wasVisible = 'true'; // Mark as available for menu
} else {
// Only show buttons that don't have inline display:none in the template
const inlineStyle = btn.getAttribute('style');
if (!inlineStyle || !inlineStyle.includes('display: none')) {
btn.style.display = '';
}
// Clear the wasVisible flag
// Clear the wasVisible flag for non-menu-only buttons
delete btn.dataset.wasVisible;
}
});
// Hide menu buttons
@@ -164,8 +179,13 @@ export class HeaderOverflowManager {
// Hide overflow buttons (will be in dropdown)
// Store original visibility before hiding
this.overflowButtons.forEach(btn => {
// Menu-only buttons are always available in menu
if (btn.classList.contains('rpg-menu-only-btn')) {
btn.dataset.wasVisible = 'true';
} else {
const computedStyle = window.getComputedStyle(btn);
btn.dataset.wasVisible = computedStyle.display !== 'none' ? 'true' : 'false';
}
btn.style.display = 'none';
});
@@ -184,8 +204,13 @@ export class HeaderOverflowManager {
// Hide all overflow buttons
// Store original visibility before hiding
this.overflowButtons.forEach(btn => {
// Menu-only buttons are always available in menu
if (btn.classList.contains('rpg-menu-only-btn')) {
btn.dataset.wasVisible = 'true';
} else {
const computedStyle = window.getComputedStyle(btn);
btn.dataset.wasVisible = computedStyle.display !== 'none' ? 'true' : 'false';
}
btn.style.display = 'none';
});
@@ -209,8 +234,20 @@ export class HeaderOverflowManager {
: this.overflowButtons;
// Filter visible buttons (only include buttons that were visible before being hidden)
// Also filter menu-only buttons based on edit mode state
const isEditMode = this.editModeManager?.isEditMode || false;
const visibleButtons = buttonsToShow.filter(btn => {
return btn.dataset.wasVisible === 'true';
// Check if button was marked as visible
if (btn.dataset.wasVisible !== 'true') {
return false;
}
// Menu-only buttons only show when in edit mode
if (btn.classList.contains('rpg-menu-only-btn')) {
return isEditMode;
}
return true;
});
if (visibleButtons.length === 0) {