add modal scroll stabilizer in modals.js
Alessandro committed
Mar 13, 2026 at 22:17 UTC
9b8db0e8c8d8fe6bbdc679d3221d27532f608eff
1 file changed
+33
webui/js/modals.js
+33
@@ -5,6 +5,32 @@ import { callJsExtensions } from "/js/extensions.js";
5
// Modal functionality
6
const modalStack = [];
7
8
+function getModalScrollElement(modal) {
9
+ return modal?.element?.querySelector(".modal-scroll");
10
+}
11
+
12
+function captureModalScrollSnapshot(modal) {
13
+ const modalScroll = getModalScrollElement(modal);
14
+ if (!modalScroll) return null;
15
+ return {
16
+ scrollTop: modalScroll.scrollTop,
17
+ scrollLeft: modalScroll.scrollLeft,
18
+ };
19
+}
20
+
21
+function restoreModalScrollSnapshot(modal) {
22
+ const snapshot = modal?.savedScrollSnapshot;
23
+ if (!snapshot) return;
24
+
25
+ requestAnimationFrame(() => {
26
+ const modalScroll = getModalScrollElement(modal);
27
+ if (!modalScroll) return;
28
+ modalScroll.scrollTop = snapshot.scrollTop;
29
+ modalScroll.scrollLeft = snapshot.scrollLeft;
30
+ modal.savedScrollSnapshot = null;
31
+ });
32
+}
33
+
34
// Create a single backdrop for all modals
35
const backdrop = document.createElement("div");
36
backdrop.className = "modal-backdrop";
@@ -103,6 +129,7 @@ function createModalElement(path) {
129
styles: [],
130
scripts: [],
131
beforeClose: null,
132
+ savedScrollSnapshot: null,
133
};
134
}
135
@@ -115,6 +142,11 @@ export async function openModal(modalPath, beforeClose = null) {
142
143
return new Promise((resolve) => {
144
try {
145
+ const currentTopModal = modalStack[modalStack.length - 1];
146
+ if (currentTopModal) {
147
+ currentTopModal.savedScrollSnapshot = captureModalScrollSnapshot(currentTopModal);
148
+ }
149
+
150
// Create new modal instance
151
const modal = createModalElement(modalPath);
152
modal.beforeClose = beforeClose;
@@ -271,6 +303,7 @@ export async function closeModal(modalPath = null) {
303
} else {
304
// Update modal z-indexes
305
updateModalZIndexes();
306
+ restoreModalScrollSnapshot(modalStack[modalStack.length - 1]);
307
}
308
309
return true;