Show save/error status inside the open widget dialog, not behind it
showStatus() always wrote to the page-level #result div, which sits behind a <dialog>'s backdrop -- a save inside a widget's gear-icon dialog produced a message the user couldn't see without closing the dialog first. It now prefers a .dialog-result element inside whichever <dialog> is currently open, falling back to #result everywhere else. The dialog is a flex column with its body scrolling independently so .dialog-result stays pinned as a visible footer regardless of scroll position -- otherwise a save message on a long form (e.g. the calendar dialog) could land off-screen below the fold with no visible feedback at all.
This commit is contained in:
@@ -59,7 +59,13 @@
|
|||||||
})();
|
})();
|
||||||
|
|
||||||
function showStatus(ok, message) {
|
function showStatus(ok, message) {
|
||||||
var el = document.getElementById('result');
|
// While a <dialog> is open, its own .dialog-result container gets the
|
||||||
|
// message instead of the page-level #result -- otherwise it lands
|
||||||
|
// behind the dialog's backdrop, invisible until the dialog closes
|
||||||
|
// (e.g. the widget config dialogs on the Layout tab, see
|
||||||
|
// frame_layout.js). Falls back to #result for everything else.
|
||||||
|
var openDialog = document.querySelector('dialog[open]');
|
||||||
|
var el = (openDialog && openDialog.querySelector('.dialog-result')) || document.getElementById('result');
|
||||||
if (!el) return;
|
if (!el) return;
|
||||||
el.innerHTML = '<div class="status ' + (ok ? 'ok' : 'err') + '"></div>';
|
el.innerHTML = '<div class="status ' + (ok ? 'ok' : 'err') + '"></div>';
|
||||||
el.firstChild.textContent = message;
|
el.firstChild.textContent = message;
|
||||||
|
|||||||
@@ -274,6 +274,7 @@ async function openWidgetDialog(widget) {
|
|||||||
const dialogEl = document.getElementById('widget-dialog');
|
const dialogEl = document.getElementById('widget-dialog');
|
||||||
const bodyEl = document.getElementById('widget-dialog-body');
|
const bodyEl = document.getElementById('widget-dialog-body');
|
||||||
bodyEl.innerHTML = '<p class="sub">Loading...</p>';
|
bodyEl.innerHTML = '<p class="sub">Loading...</p>';
|
||||||
|
dialogEl.querySelector('.dialog-result').innerHTML = ''; // clear any message left over from a previous dialog
|
||||||
openDialogWidgetType = widget.widget_type;
|
openDialogWidgetType = widget.widget_type;
|
||||||
dialogEl.showModal();
|
dialogEl.showModal();
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -402,6 +402,13 @@ button.secondary:hover { background: var(--surface-alt); }
|
|||||||
background: var(--surface);
|
background: var(--surface);
|
||||||
color: var(--text);
|
color: var(--text);
|
||||||
box-shadow: var(--shadow-hover);
|
box-shadow: var(--shadow-hover);
|
||||||
|
/* #widget-dialog-body scrolls on its own (min-height: 0 is what lets a
|
||||||
|
flex child actually shrink/scroll instead of forcing the dialog
|
||||||
|
past max-height) so .dialog-result stays pinned as a visible footer
|
||||||
|
regardless of scroll position -- otherwise a save message can land
|
||||||
|
off-screen below a long form with no visible feedback at all. */
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
#widget-dialog::backdrop { background: var(--overlay); }
|
#widget-dialog::backdrop { background: var(--overlay); }
|
||||||
#widget-dialog-close {
|
#widget-dialog-close {
|
||||||
@@ -414,8 +421,11 @@ button.secondary:hover { background: var(--surface-alt); }
|
|||||||
z-index: 1;
|
z-index: 1;
|
||||||
}
|
}
|
||||||
.dialog-title { margin: 0 40px 16px 0; font-size: 18px; }
|
.dialog-title { margin: 0 40px 16px 0; font-size: 18px; }
|
||||||
|
#widget-dialog-body { overflow-y: auto; min-height: 0; }
|
||||||
#widget-dialog-body .card { box-shadow: none; }
|
#widget-dialog-body .card { box-shadow: none; }
|
||||||
#widget-dialog-body .card:first-child { margin-top: 0; }
|
#widget-dialog-body .card:first-child { margin-top: 0; }
|
||||||
|
.dialog-result { flex: none; }
|
||||||
|
.dialog-result:not(:empty) { margin-top: 16px; padding-top: 16px; border-top: 1px solid var(--border); }
|
||||||
|
|
||||||
code {
|
code {
|
||||||
background: var(--surface-alt);
|
background: var(--surface-alt);
|
||||||
|
|||||||
@@ -38,6 +38,7 @@
|
|||||||
<dialog id="widget-dialog">
|
<dialog id="widget-dialog">
|
||||||
<button type="button" id="widget-dialog-close" class="icon-btn" aria-label="Close" title="Close">×</button>
|
<button type="button" id="widget-dialog-close" class="icon-btn" aria-label="Close" title="Close">×</button>
|
||||||
<div id="widget-dialog-body"><p class="sub">Loading...</p></div>
|
<div id="widget-dialog-body"><p class="sub">Loading...</p></div>
|
||||||
|
<div class="dialog-result"></div>
|
||||||
</dialog>
|
</dialog>
|
||||||
|
|
||||||
<div id="result"></div>
|
<div id="result"></div>
|
||||||
|
|||||||
Reference in New Issue
Block a user