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:
@@ -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');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user