feat: add disabled state UI for Recent Events widget

Show helpful message when Recent Events tracking is disabled in tracker config.

Changes:
- Check if recentEvents is enabled in trackerConfig before rendering
- If disabled, show dimmed widget with overlay message:
  - Info icon + explanation text
  - "Enable in Tracker Settings" button
  - Button opens Tracker Settings and switches to Info Box tab

UX Improvements:
- Widget opacity reduced to 0.6 to indicate disabled state
- Message centered with clear visual hierarchy
- Button has hover/active states with elevation feedback
- Clicking button directly navigates to the right settings location

Technical Implementation:
- attachDisabledStateHandlers() opens Tracker Settings modal
- Auto-switches to Info Box tab after 100ms delay
- Graceful fallback if button not found (console warning)

CSS Additions:
- .rpg-widget-disabled: Dimmed overlay state
- .rpg-widget-disabled-message: Centered message container
- .rpg-widget-enable-btn: Styled action button with hover effects

Benefits:
- Users immediately understand why Recent Events isn't updating
- One-click access to fix the issue
- Clear visual feedback about widget state
- Pattern can be reused for other widgets (Skills, etc.)

Next Steps:
- Apply this pattern to other widgets that depend on tracker config
- Consider adding similar disabled states for Skills, Stats, etc.

Related: Recent Events widget implementation, tracker config system
This commit is contained in:
Lucas 'Paperboy' Rose-Winters
2025-11-06 22:29:53 +11:00
parent a9d98a3076
commit aa0dd55fb1
2 changed files with 128 additions and 1 deletions
@@ -550,7 +550,40 @@ export function registerRecentEventsWidget(registry, dependencies) {
* @param {Object} config - Widget configuration * @param {Object} config - Widget configuration
*/ */
render(container, config = {}) { render(container, config = {}) {
const { getInfoBoxData } = dependencies; const { getInfoBoxData, getExtensionSettings } = dependencies;
// Check if Recent Events is enabled in tracker config
const settings = getExtensionSettings();
const trackerConfig = settings.trackerConfig;
const isEnabled = trackerConfig?.infoBox?.widgets?.recentEvents?.enabled !== false;
// If disabled, show helpful message
if (!isEnabled) {
const html = `
<div class="rpg-dashboard-widget">
<div class="rpg-events-widget rpg-widget-disabled">
<div class="rpg-notebook-header">
<div class="rpg-notebook-ring"></div>
<div class="rpg-notebook-ring"></div>
<div class="rpg-notebook-ring"></div>
</div>
<div class="rpg-notebook-title">Recent Events</div>
<div class="rpg-widget-disabled-message">
<i class="fa-solid fa-circle-info"></i>
<p>Recent Events tracking is currently disabled.</p>
<button class="rpg-widget-enable-btn" data-widget-type="recentEvents">
<i class="fa-solid fa-toggle-on"></i>
Enable in Tracker Settings
</button>
</div>
</div>
</div>
`;
container.innerHTML = html;
attachDisabledStateHandlers(container);
return;
}
const data = parseInfoBoxData(getInfoBoxData()); const data = parseInfoBoxData(getInfoBoxData());
// Merge default config with user config // Merge default config with user config
@@ -767,3 +800,31 @@ function updateRecentEvent(eventIndex, value, dependencies) {
console.log(`[Recent Events Widget] Updated event ${eventIndex}: "${value}"`); console.log(`[Recent Events Widget] Updated event ${eventIndex}: "${value}"`);
} }
/**
* Attach handlers for disabled widget state
* Opens Tracker Settings when "Enable" button is clicked
* @private
*/
function attachDisabledStateHandlers(container) {
const enableBtn = container.querySelector('.rpg-widget-enable-btn');
if (enableBtn) {
enableBtn.addEventListener('click', () => {
// Open Tracker Settings modal
const trackerSettingsBtn = document.querySelector('#rpg-open-tracker-editor');
if (trackerSettingsBtn) {
trackerSettingsBtn.click();
// After modal opens, switch to Info Box tab
setTimeout(() => {
const infoBoxTab = document.querySelector('.rpg-editor-tab[data-tab="infoBox"]');
if (infoBoxTab) {
infoBoxTab.click();
}
}, 100);
} else {
console.warn('[Recent Events Widget] Tracker Settings button not found');
}
});
}
}
+66
View File
@@ -2776,6 +2776,72 @@ body:has(.rpg-panel.rpg-position-left) #sheld {
opacity: 1; opacity: 1;
} }
/* Widget Disabled State */
.rpg-widget-disabled {
position: relative;
opacity: 0.6;
pointer-events: none;
}
.rpg-widget-disabled-message {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
text-align: center;
padding: 1rem;
pointer-events: all;
z-index: 10;
width: 80%;
}
.rpg-widget-disabled-message i.fa-circle-info {
font-size: 2rem;
color: var(--rpg-highlight);
margin-bottom: 0.5rem;
display: block;
opacity: 0.8;
}
.rpg-widget-disabled-message p {
color: var(--rpg-text);
font-size: 0.875rem;
margin: 0.5rem 0;
opacity: 0.9;
line-height: 1.4;
}
.rpg-widget-enable-btn {
background: var(--rpg-accent);
color: white;
border: none;
border-radius: 0.375rem;
padding: 0.5rem 1rem;
font-size: 0.8125rem;
cursor: pointer;
transition: all 0.2s ease;
display: inline-flex;
align-items: center;
gap: 0.5rem;
margin-top: 0.5rem;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
}
.rpg-widget-enable-btn:hover {
background: var(--rpg-highlight);
transform: translateY(-1px);
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3);
}
.rpg-widget-enable-btn:active {
transform: translateY(0);
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
}
.rpg-widget-enable-btn i {
font-size: 1rem;
}
/* ============================================================================ /* ============================================================================
Scene Info Grid Widget Scene Info Grid Widget
Compact information-dense layout showing all scene data at once Compact information-dense layout showing all scene data at once