refactor: modals styles cleanup and subdirectories

Alessandro committed Oct 22, 2025 at 19:38 UTC e860b67eadbcb9af6fa2c84a1f37df2c995a0bab
18 files changed +312 -444
webui/components/chat/attachments/attachmentsStore.js
+1 -1
@@ -1,6 +1,6 @@
1 import { createStore } from "/js/AlpineStore.js";
2 import { fetchApi } from "/js/api.js";
3 -import { store as imageViewerStore } from "/components/modals/image-viewer-store.js";
3 +import { store as imageViewerStore } from "../../modals/image-viewer/image-viewer-store.js";
4
5 const model = {
6 // State properties
webui/components/chat/attachments/inputPreview.html
+1 -1
@@ -1,6 +1,6 @@
1 <script type="module">
2 import { store } from "/components/chat/attachments/attachmentsStore.js";
3 - import { store as imageViewerStore } from "/components/modals/image-viewer-store.js";
3 + import { store as imageViewerStore } from "/components/modals/image-viewer/image-viewer-store.js";
4 </script>
5
6 <div x-data>
webui/components/chat/input/bottom-actions.html
+3 -3
@@ -2,9 +2,9 @@
2 <head>
3 <script type="module">
4 import { store } from "/components/chat/input/input-store.js";
5 - import { store as historyStore } from "/components/modals/history-store.js";
6 - import { store as contextStore } from "/components/modals/context-store.js";
7 - import { store as fileBrowserStore } from "/components/modals/file-browser-store.js";
5 + import { store as historyStore } from "/components/modals/history/history-store.js";
6 + import { store as contextStore } from "/components/modals/context/context-store.js";
7 + import { store as fileBrowserStore } from "/components/modals/file-browser/file-browser-store.js";
8 </script>
9 </head>
10 <body>
webui/components/chat/input/chat-bar-input.html
+4 -1
@@ -3,7 +3,7 @@
3 <script type="module">
4 import { store as speechStore } from "/components/chat/speech/speech-store.js";
5 import { store as attachmentsStore } from "/components/chat/attachments/attachmentsStore.js";
6 - import { store as fullScreenStore } from "/components/modals/full-screen-store.js";
6 + import { store as fullScreenStore } from "/components/modals/full-screen-input/full-screen-store.js";
7 </script>
8 </head>
9 <body>
@@ -51,6 +51,9 @@
51 </div>
52 </div>
53
54 + <!-- Full Screen Input Modal -->
55 + <x-component path="modals/full-screen-input/full-screen-input.html"></x-component>
56 +
57
58 <style>
59 /* Layout rows */
webui/components/modals/context/context-store.js renamed
+1 -1
@@ -20,7 +20,7 @@ const model = {
20
21 try {
22 // Open modal FIRST (immediate UI feedback, but DON'T await)
23 - this.closePromise = window.openModal('modals/context.html');
23 + this.closePromise = window.openModal('modals/context/context.html');
24
25 // Setup cleanup on modal close
26 if (this.closePromise && typeof this.closePromise.then === 'function') {
webui/components/modals/context/context.html renamed
+1 -1
@@ -2,7 +2,7 @@
2 <head>
3 <title>Context Window</title>
4 <script type="module">
5 - import { store } from "/components/modals/context-store.js";
5 + import { store } from "/components/modals/context/context-store.js";
6 </script>
7 </head>
8 <body>
webui/components/modals/file-browser/file-browser-store.js renamed
+1 -1
@@ -33,7 +33,7 @@ const model = {
33
34 try {
35 // Open modal FIRST (immediate UI feedback)
36 - this.closePromise = window.openModal('modals/file-browser.html');
36 + this.closePromise = window.openModal('modals/file-browser/file-browser.html');
37
38 // Setup cleanup on modal close
39 if (this.closePromise && typeof this.closePromise.then === 'function') {
webui/components/modals/file-browser/file-browser.html renamed
+1 -1
@@ -2,7 +2,7 @@
2 <head>
3 <title>File Browser</title>
4 <script type="module">
5 - import { store } from "/components/modals/file-browser-store.js";
5 + import { store } from "/components/modals/file-browser/file-browser-store.js";
6 </script>
7 </head>
8 <body>
webui/components/modals/full-screen-input/full-screen-input.html renamed
+78 -2
@@ -1,7 +1,7 @@
1 <html>
2 <head>
3 <script type="module">
4 - import { store } from "/components/modals/full-screen-store.js";
4 + import { store } from "/components/modals/full-screen-input/full-screen-store.js";
5 </script>
6 </head>
7 <body>
@@ -70,7 +70,83 @@
70
71
72 <style>
73 - /* No component-specific styles needed; styles are provided by css/modals.css and css/modals2.css */
73 + /* Full Screen Input Modal Styles */
74 + .full-screen-input-modal {
75 + width: 90%;
76 + max-width: 800px;
77 + max-height: 80vh;
78 + position: relative;
79 + padding: 0;
80 + background-color: rgb(20, 20, 20, 0.96);
81 + border: 1.5px solid var(--color-border);
82 + }
83 + .full-screen-input-modal .modal-content {
84 + height: calc(80vh);
85 + padding: 0;
86 + margin: 0;
87 + overflow: hidden;
88 + }
89 + .full-screen-input-modal .modal-footer {
90 + background: transparent;
91 + max-height: 50px;
92 + }
93 + #full-screen-input {
94 + width: 100%;
95 + height: calc(100% - 50px);
96 + border: none;
97 + background-color: transparent;
98 + color: var(--color-text);
99 + font-family: "Roboto Mono", monospace;
100 + font-optical-sizing: auto;
101 + font-size: 0.955rem;
102 + padding: 1.2rem 1rem;
103 + resize: none;
104 + outline: none;
105 + }
106 + .light-mode .full-screen-input-modal {
107 + background-color: rgb(220, 220, 220, 0.86);
108 + }
109 + .full-screen-input-modal .modal-footer {
110 + padding: 1rem 0;
111 + border-top: none;
112 + background: transparent;
113 + }
114 + .full-screen-input-modal h2 {
115 + margin: 0;
116 + padding: 0;
117 + font-size: 1.1rem;
118 + color: var(--color-text);
119 + opacity: 0.8;
120 + }
121 + .full-screen-input-modal .modal-close {
122 + position: absolute;
123 + top: 1.2rem;
124 + right: 1rem;
125 + font-size: 1.5rem;
126 + padding: 0 0.5rem;
127 + line-height: 0.8;
128 + }
129 + .full-screen-input-modal .btn-ok {
130 + margin-right: 1rem;
131 + }
132 + #full-screen-input::-webkit-scrollbar {
133 + width: 6px;
134 + height: 6px;
135 + }
136 + #full-screen-input::-webkit-scrollbar-track {
137 + background: transparent;
138 + margin: 14px;
139 + border-radius: 6px;
140 + }
141 + #full-screen-input::-webkit-scrollbar-thumb {
142 + background-color: rgba(155, 155, 155, 0.5);
143 + border-radius: 6px;
144 + -webkit-transition: background-color 0.2s ease;
145 + transition: background-color 0.2s ease;
146 + }
147 + #full-screen-input::-webkit-scrollbar-thumb:hover {
148 + background-color: rgba(155, 155, 155, 0.7);
149 + }
150 </style>
151 </body>
152 </html>
webui/components/modals/full-screen-input/full-screen-store.js renamed
webui/components/modals/history/history-store.js renamed
+1 -1
@@ -20,7 +20,7 @@ const model = {
20
21 try {
22 // Open modal FIRST (immediate UI feedback, but DON'T await)
23 - this.closePromise = window.openModal('modals/history.html');
23 + this.closePromise = window.openModal('modals/history/history.html');
24
25 // Setup cleanup on modal close
26 if (this.closePromise && typeof this.closePromise.then === 'function') {
webui/components/modals/history/history.html renamed
+1 -1
@@ -2,7 +2,7 @@
2 <head>
3 <title>History</title>
4 <script type="module">
5 - import { store } from "/components/modals/history-store.js";
5 + import { store } from "/components/modals/history/history-store.js";
6 </script>
7 </head>
8 <body>
webui/components/modals/image-viewer/image-viewer-store.js renamed
+1 -1
@@ -40,7 +40,7 @@ const model = {
40
41 try {
42 // Open modal and track close promise for cleanup
43 - this.closePromise = window.openModal('modals/image-viewer.html');
43 + this.closePromise = window.openModal('modals/image-viewer/image-viewer.html');
44
45 // Setup cleanup on modal close
46 if (this.closePromise && typeof this.closePromise.finally === 'function') {
webui/components/modals/image-viewer/image-viewer.html renamed
+1 -1
@@ -4,7 +4,7 @@
4 <title>Image Viewer</title>
5
6 <script type="module">
7 - import { store } from "/components/modals/image-viewer-store.js";
7 + import { store } from "/components/modals/image-viewer/image-viewer-store.js";
8 </script>
9 </head>
10
webui/css/modals.css
+216 -215
@@ -1,6 +1,42 @@
1 /* Modal Styles */
2 +/* Until the full transition of A0 modals is complete,
3 +consider these classes as part of the old modal system that will be deprecated soon
4 +(currently used only by Settings modal). .modal-content, .modal-container, .modal-overlay
5
3 -/* Overlay */
6 +Do not maintain these classes, but be careful:
7 +some classes like modal-header are shared between the old and the new system */
8 +
9 +.modal {
10 + display: none;
11 + position: fixed;
12 + top: 0;
13 + left: 0;
14 + width: 100%;
15 + height: 100%;
16 + z-index: 2000;
17 +}
18 +.modal.show {
19 + display: block;
20 +}
21 +
22 +.modal-inner {
23 + display: flex;
24 + flex-direction: column;
25 + overflow: hidden;
26 + position: fixed;
27 + top: 50%;
28 + left: 50%;
29 + transform: translate(-50%, -50%);
30 + background-color: var(--color-background);
31 + width: 90%;
32 + max-width: 960px;
33 + max-height: 90vh;
34 + border-radius: 8px;
35 + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
36 + z-index: 2;
37 +}
38 +
39 +/* Overlay (old system) */
40 .modal-overlay {
41 position: fixed;
42 top: 0;
@@ -14,7 +50,19 @@
50 z-index: 2001;
51 }
52
17 -/* Modal Container */
53 +/* Modal Backdrop */
54 +.modal-backdrop {
55 + position: fixed;
56 + top: 0;
57 + left: 0;
58 + width: 100%;
59 + height: 100%;
60 + background-color: rgba(0, 0, 0, 0.5);
61 + z-index: 1;
62 + cursor: pointer;
63 +}
64 +
65 +/* Modal Container (old system) */
66 .modal-container {
67 background-color: var(--color-panel);
68 border-radius: 12px;
@@ -27,24 +75,6 @@
75 box-sizing: border-box;
76 }
77
30 -.light-mode .modal-container {
31 - background-color: var(--color-panel-light);
32 -}
33 -
34 -/* Mobile Viewport Behavior */
35 -@media (max-width: 1280px) {
36 - .modal-container {
37 - width: 95%; /* Take up most of the screen on mobile */
38 - min-width: unset; /* Remove min-width constraints */
39 - max-width: 95%; /* Ensure consistent width */
40 - }
41 -
42 - /* Ensure section content can scroll horizontally */
43 - .section {
44 - overflow-x: auto;
45 - }
46 -}
47 -
78 /* Modal Header */
79 .modal-header {
80 display: grid;
@@ -56,9 +86,7 @@
86 color: var(--color-primary);
87 border-bottom: 1px solid var(--color-border);
88 }
59 -
89 .modal-header h2 {
61 - /* font-size: var(--font-size-large); */
90 margin: 0;
91 }
92
@@ -106,123 +134,45 @@
134 box-sizing: border-box;
135 }
136
109 -.modal-content::-webkit-scrollbar {
110 - width: 6px;
111 - height: 6px;
112 -}
113 -
114 -.modal-content::-webkit-scrollbar-track {
115 - background: transparent;
116 - margin: 4px 0;
117 - border-radius: 6px;
118 -}
119 -
120 -.modal-content::-webkit-scrollbar-thumb {
121 - background-color: rgba(155, 155, 155, 0.5);
122 - border-radius: 6px;
123 - transition: background-color 0.2s ease;
124 -}
125 -
126 -.modal-content::-webkit-scrollbar-thumb:hover {
127 - background-color: rgba(155, 155, 155, 0.7);
128 -}
129 -
130 -/* Full Screen Input Modal Styles */
131 -.full-screen-input-modal {
132 - width: 90%;
133 - max-width: 800px;
134 - max-height: 80vh;
135 - position: relative;
136 - padding: 0;
137 - background-color: rgb(20, 20, 20, 0.96);
138 - border: 1.5px solid var(--color-border);
139 -}
140 -
141 -.full-screen-input-modal h2 {
142 - margin: 0;
143 - padding: 0;
144 - font-size: 1.1rem;
145 - color: var(--color-text);
146 - opacity: 0.8;
137 +.modal-scroll {
138 + max-height: 90vh;
139 + overflow-y: auto;
140 + padding: 0 1rem 1rem 1rem;
141 }
142
149 -.full-screen-input-modal .modal-close {
143 +.modal-x {
144 position: absolute;
151 - top: 1.2rem;
145 + top: 1rem;
146 right: 1rem;
153 - font-size: 1.5rem;
154 - padding: 0 0.5rem;
155 - line-height: 0.8;
156 -}
157 -
158 -.full-screen-input-modal .btn-ok {
159 - margin-right: 1rem;
160 -}
161 -
162 -.full-screen-input-modal .modal-content {
163 - height: calc(80vh);
164 - padding: 0;
165 - margin: 0;
166 - overflow: hidden;
167 -}
168 -
169 -.full-screen-input-modal .modal-footer {
170 - background: transparent;
171 - max-height: 50px;
172 -}
173 -
174 -#full-screen-input {
175 - width: 100%;
176 - height: calc(100% - 50px);
147 + background: none;
148 border: none;
178 - background-color: transparent;
149 + font-size: 1.5rem;
150 + cursor: pointer;
151 color: var(--color-text);
180 - font-family: "Roboto Mono", monospace;
181 - font-optical-sizing: auto;
182 - font-size: 0.955rem;
183 - padding: 1.2rem 1rem;
184 - resize: none;
185 - outline: none;
152 + padding: 0.5rem;
153 + line-height: 1;
154 + z-index: 3;
155 }
156
188 -#full-screen-input::-webkit-scrollbar {
157 +.modal-content::-webkit-scrollbar, .modal-scroll::-webkit-scrollbar {
158 width: 6px;
159 height: 6px;
160 }
192 -
193 -#full-screen-input::-webkit-scrollbar-track {
161 +.modal-content::-webkit-scrollbar-track, .modal-scroll::-webkit-scrollbar-track {
162 background: transparent;
195 - margin: 14px;
163 + margin: 4px 0;
164 border-radius: 6px;
165 }
198 -
199 -#full-screen-input::-webkit-scrollbar-thumb {
166 +.modal-content::-webkit-scrollbar-thumb, .modal-scroll::webkit-scrollbar-thumb {
167 background-color: rgba(155, 155, 155, 0.5);
168 border-radius: 6px;
202 - -webkit-transition: background-color 0.2s ease;
169 transition: background-color 0.2s ease;
170 }
205 -
206 -#full-screen-input::-webkit-scrollbar-thumb:hover {
171 +.modal-content::-webkit-scrollbar-thumb:hover, .modal-scroll::-webkit-scrollbar-thumb:hover {
172 background-color: rgba(155, 155, 155, 0.7);
173 }
174
210 -.light-mode .full-screen-input-modal {
211 - background-color: rgb(220, 220, 220, 0.86);
212 -}
213 -
214 -.full-screen-input-modal .modal-footer {
215 - padding: 1rem 0;
216 - border-top: none;
217 - background: transparent;
218 -}
219 -
220 -/* Buttons Container */
221 -#buttons-container {
222 - display: flex;
223 - gap: 0.875rem !important;
224 -}
225 -
175 +/* Modal with footer support */
176 .modal-footer {
177 display: flex;
178 justify-content: flex-end;
@@ -232,6 +182,20 @@
182 background: var(--color-background);
183 gap: 1rem;
184 }
185 +.modal-inner.modal-with-footer {
186 + display: flex;
187 + flex-direction: column;
188 +}
189 +.modal-inner.modal-with-footer .modal-scroll {
190 + flex: 1;
191 + min-height: 0;
192 + overflow-y: auto;
193 +}
194 +.modal-footer-slot {
195 + flex-shrink: 0;
196 + border-top: 1px solid var(--color-border);
197 + background: var(--color-background);
198 +}
199
200 /* Section Styles */
201 .section {
@@ -241,19 +205,41 @@
205 border: 1px solid var(--color-border);
206 border-radius: 0.5rem;
207 }
244 -
208 .section-title {
209 font-size: 1.25rem;
210 font-weight: bold;
211 color: var(--color-primary);
212 margin-bottom: 0.5rem;
213 }
251 -
214 .section-description {
215 color: var(--color-text);
216 margin-bottom: 1rem;
217 }
218
219 +/* Buttons Container */
220 +.modal-button-container {
221 + display: flex;
222 + justify-content: space-between;
223 + gap: 10px;
224 + width: 100%;
225 + margin-top: 20px;
226 +}
227 +.modal-button-container .button {
228 + flex: 1;
229 + min-width: 0;
230 + padding: 10px;
231 + text-align: center;
232 + white-space: nowrap;
233 + font-size: 0.9em;
234 + display: flex;
235 + justify-content: center;
236 + align-items: center;
237 +}
238 +#buttons-container {
239 + display: flex;
240 + gap: 0.875rem !important;
241 +}
242 +
243 /* Button Styles */
244 .btn {
245 font-weight: 500;
@@ -264,22 +250,17 @@
250 font-size: 0.875rem;
251 font-family: "Rubik", Arial, Helvetica, sans-serif;
252 }
267 -
253 .btn.slim {
254 padding: 0.2em 0.4em;
255 }
271 -
256 .btn.primary {
257 background: #2196f3;
258 color: white;
259 width: fit-content;
260 }
277 -
261 .btn:disabled {
279 - /* background: #ccc; */
262 cursor: not-allowed;
263 }
282 -
264 .btn-ok {
265 background: #4248f1;
266 color: white;
@@ -288,122 +269,47 @@
269 gap: 0.5rem;
270 transition: background 0.3s ease-in-out;
271 }
291 -
272 .btn-ok > svg {
273 max-width: 20px;
274 }
295 -
275 .btn-ok:hover {
276 background: #353bc5;
277 }
299 -
278 .btn-ok:active {
279 background: #2b309c;
280 }
303 -
281 .btn-cancel {
282 background: transparent;
283 color: var(--color-accent);
284 border: 0.15rem solid var(--color-accent);
285 transition: background 0.3s ease-in-out, color 0.3s ease-in-out;
286 }
310 -
287 .btn-cancel:hover {
288 background: var(--color-accent);
289 color: var(--color-text);
290 }
315 -
291 .btn-cancel:active {
292 background: #a94658;
293 color: var(--color-text);
294 }
320 -
295 .light-mode .btn-cancel:hover {
296 background: var(--color-accent);
297 color: var(--color-background);
298 }
325 -
299 .light-mode .btn-cancel:active {
300 background: #a94658;
301 color: var(--color-background);
302 }
330 -
303 .btn-field {
304 background: #2196f3;
305 color: white;
306 width: fit-content;
307 }
336 -
308 .btn-field:disabled {
309 background: #ccc;
310 cursor: not-allowed;
311 }
312
342 -/* Typography */
343 -/* h2 {
344 - color: var(--color-primary);
345 -} */
346 -
347 -/* Responsive Design */
348 -@media (max-width: 768px) {
349 - .modal-header {
350 - padding-left: 1.1rem;
351 - text-wrap: nowrap;
352 - }
353 -
354 - .modal-content {
355 - padding: 0.5rem;
356 - overflow-y: auto;
357 - flex-grow: 1;
358 - }
359 -
360 - .modal-footer {
361 - padding: var(--spacing-sm) 0 var(--spacing-sm) 0 !important;
362 - }
363 -
364 - .section {
365 - margin-bottom: 1.5rem;
366 - padding: 1rem;
367 - padding-bottom: 0;
368 - border: 1px solid var(--color-border);
369 - border-radius: 0.5rem;
370 - }
371 -
372 - #buttons-container {
373 - margin: 0 auto;
374 - }
375 -
376 - .btn {
377 - padding: 0.5rem 1.7rem;
378 - }
379 -}
380 -
381 -@media (max-width: 540px) {
382 - .modal-header h2 {
383 - font-size: var(--font-size-normal);
384 - margin: 0;
385 - }
386 -
387 - #buttons-container {
388 - max-height: 50px;
389 - }
390 -
391 - .btn {
392 - text-wrap: wrap;
393 - font-size: var(--font-size-small);
394 - }
395 -
396 - .btn-upload {
397 - margin: 0 auto;
398 - gap: 0.5rem;
399 - align-items: center;
400 - }
401 -
402 - .btn-upload > svg {
403 - width: 20px;
404 - }
405 -}
406 -
313 /* Editor Toolbar */
314 .editor-toolbar {
315 display: flex;
@@ -414,11 +320,9 @@
320 background-color: rgba(30, 30, 30, 0.95);
321 border-bottom: 1px solid var(--color-border);
322 }
417 -
323 .light-mode .editor-toolbar {
324 background-color: rgba(240, 240, 240, 0.95);
325 }
421 -
326 .toolbar-group {
327 display: flex;
328 align-items: center;
@@ -426,11 +330,9 @@
330 padding: 0 0.5rem;
331 border-right: 1px solid var(--color-border);
332 }
429 -
333 .toolbar-group:last-child {
334 border-right: none;
335 }
433 -
336 .toolbar-button {
337 display: flex;
338 align-items: center;
@@ -446,38 +348,31 @@
348 cursor: pointer;
349 transition: all 0.2s ease;
350 }
449 -
351 .toolbar-button svg {
352 width: 18px;
353 height: 18px;
354 }
454 -
355 .toolbar-button:hover {
356 opacity: 1;
357 background-color: rgba(255, 255, 255, 0.1);
358 }
459 -
359 .toolbar-button:active {
360 transform: translateY(1px);
361 }
463 -
362 .toolbar-button.active {
363 background-color: rgba(255, 255, 255, 0.15);
364 border-color: var(--color-border);
365 opacity: 1;
366 }
469 -
367 .toolbar-button:disabled {
368 opacity: 0.3;
369 cursor: not-allowed;
370 }
474 -
371 .toolbar-button:disabled:hover {
372 background-color: transparent;
373 }
374
375 /* Range Input Styles */
480 -
376 input[type="range"] {
377 width: 100%;
378 cursor: pointer;
@@ -488,7 +383,6 @@ input[type="range"] {
383 border-radius: 2px;
384 outline: none;
385 }
491 -
386 input[type="range"]::-webkit-slider-thumb {
387 -webkit-appearance: none;
388 appearance: none;
@@ -498,7 +392,6 @@ input[type="range"]::-webkit-slider-thumb {
392 border-radius: 50%;
393 cursor: pointer;
394 }
501 -
395 input[type="range"]::-moz-range-thumb {
396 width: 16px;
397 height: 16px;
@@ -507,8 +400,116 @@ input[type="range"]::-moz-range-thumb {
400 cursor: pointer;
401 border: none;
402 }
510 -
403 .range-value {
404 min-width: 3em;
405 text-align: right;
514 -}
\ No newline at end of file
406 +}
407 +
408 +/* Responsive Design */
409 +@media (max-width: 1280px) {
410 + .modal-container {
411 + width: 95%;
412 + min-width: unset; /* Remove min-width constraints */
413 + max-width: 95%;
414 + }
415 + .section {
416 + overflow-x: auto;
417 + }
418 +}
419 +@media (max-width: 768px) {
420 + .modal-header {
421 + padding-left: 1.1rem;
422 + text-wrap: nowrap;
423 + }
424 + .modal-content {
425 + padding: 0.5rem;
426 + overflow-y: auto;
427 + flex-grow: 1;
428 + }
429 + .modal-footer {
430 + padding: var(--spacing-sm) 0 var(--spacing-sm) 0 !important;
431 + }
432 + .section {
433 + margin-bottom: 1.5rem;
434 + padding: 1rem;
435 + padding-bottom: 0;
436 + border: 1px solid var(--color-border);
437 + border-radius: 0.5rem;
438 + }
439 + #buttons-container {
440 + margin: 0 auto;
441 + }
442 + .btn {
443 + padding: 0.5rem 1.7rem;
444 + }
445 +}
446 +@media (max-width: 540px) {
447 + .modal-header h2 {
448 + font-size: var(--font-size-normal);
449 + margin: 0;
450 + }
451 + #buttons-container {
452 + max-height: 50px;
453 + }
454 + .btn {
455 + text-wrap: wrap;
456 + font-size: var(--font-size-small);
457 + }
458 + .btn-upload {
459 + margin: 0 auto;
460 + gap: 0.5rem;
461 + align-items: center;
462 + }
463 + .btn-upload > svg {
464 + width: 20px;
465 + }
466 +}
467 +
468 +.loading {
469 + width: calc(100% - 4rem);
470 + max-width: 1200px;
471 + min-height: 50px;
472 + border-radius: 12px;
473 + background: var(--color-border);
474 + position: relative;
475 + overflow: hidden;
476 + margin: 2rem auto;
477 + opacity: 0;
478 + animation: fadeIn 500ms ease-out 500ms forwards;
479 +}
480 +
481 +@keyframes fadeIn {
482 + 0% {
483 + opacity: 0;
484 + }
485 + 100% {
486 + opacity: 1;
487 + }
488 +}
489 +
490 +.loading::before {
491 + content: "";
492 + position: absolute;
493 + top: 0;
494 + left: 0;
495 + width: 100%;
496 + height: 100%;
497 + background: linear-gradient(
498 + 90deg,
499 + var(--color-background),
500 + var(--color-border),
501 + var(--color-background)
502 + );
503 + animation: shimmer 2s infinite;
504 + animation-delay: 250ms;
505 + background-size: 200% 100%;
506 +}
507 +
508 +@keyframes shimmer {
509 + 0% {
510 + background-position: 200% 0;
511 + }
512 + 100% {
513 + background-position: -200% 0;
514 + }
515 +}
webui/css/modals2.css deleted
-208
@@ -1,208 +0,0 @@
1 -/* Modal Styles */
2 -.modal {
3 - display: none;
4 - position: fixed;
5 - top: 0;
6 - left: 0;
7 - width: 100%;
8 - height: 100%;
9 - z-index: 2000;
10 -}
11 -
12 -.modal.show {
13 - display: block;
14 -}
15 -
16 -.modal-backdrop {
17 - position: fixed;
18 - top: 0;
19 - left: 0;
20 - width: 100%;
21 - height: 100%;
22 - background-color: rgba(0, 0, 0, 0.5);
23 - z-index: 1;
24 - cursor: pointer;
25 -}
26 -
27 -.modal-inner {
28 -display: flex;
29 - flex-direction: column;
30 - overflow: hidden;
31 - position: fixed;
32 - top: 50%;
33 - left: 50%;
34 - transform: translate(-50%, -50%);
35 - background-color: var(--color-background-light);
36 - width: 90%;
37 - max-width: 960px;
38 - max-height: 90vh;
39 - border-radius: 8px;
40 - box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
41 - z-index: 2;
42 -}
43 -
44 -.dark-mode .modal-inner {
45 - background-color: var(--color-background-dark);
46 - box-shadow: 0 4px 6px rgba(0, 0, 0, 0.3);
47 -}
48 -
49 -/* Mobile Viewport Behavior */
50 -@media (max-width: 1280px) {
51 - .modal-inner {
52 - width: 95%; /* Take up most of the screen on mobile */
53 - min-width: unset; /* Remove min-width constraints */
54 - max-width: 95%; /* Ensure consistent width */
55 - }
56 -
57 - /* Ensure section content can scroll horizontally */
58 - .section {
59 - overflow-x: auto;
60 - }
61 - }
62 -
63 -.modal-scroll {
64 - max-height: 90vh;
65 - overflow-y: auto;
66 - padding: 0 1rem 1rem 1rem;
67 -}
68 -
69 -/* Modal with footer support */
70 -.modal-inner.modal-with-footer {
71 - display: flex;
72 - flex-direction: column;
73 -}
74 -
75 -.modal-inner.modal-with-footer .modal-scroll {
76 - flex: 1;
77 - min-height: 0;
78 - overflow-y: auto;
79 -}
80 -
81 -.modal-footer-slot {
82 - flex-shrink: 0;
83 - border-top: 1px solid var(--color-border);
84 - background: var(--color-background);
85 -}
86 -
87 -.modal-x {
88 - position: absolute;
89 - top: 1rem;
90 - right: 1rem;
91 - background: none;
92 - border: none;
93 - font-size: 1.5rem;
94 - cursor: pointer;
95 - color: var(--text-primary-light);
96 - padding: 0.5rem;
97 - line-height: 1;
98 - z-index: 3;
99 -}
100 -
101 -.dark-mode .modal-x {
102 - color: var(--text-primary-dark);
103 -}
104 -
105 -.modal-title {
106 - /* margin: 0 0 1.5rem 0;
107 - padding-right: 3rem;
108 - color: var(--text-primary-light);
109 - font-size: 1.75rem;
110 - border-bottom: 1px solid rgba(0, 0, 0, 0.1);
111 - padding-bottom: 1rem; */
112 -}
113 -
114 -.dark-mode .modal-title {
115 - color: var(--text-primary-dark);
116 - border-bottom-color: rgba(255, 255, 255, 0.1);
117 -}
118 -
119 -.modal-button-container {
120 - display: flex;
121 - justify-content: space-between;
122 - gap: 10px;
123 - width: 100%;
124 - margin-top: 20px;
125 -}
126 -
127 -.modal-button-container .button {
128 - flex: 1;
129 - min-width: 0;
130 - padding: 10px;
131 - text-align: center;
132 - white-space: nowrap;
133 - font-size: 0.9em;
134 - display: flex;
135 - justify-content: center;
136 - align-items: center;
137 -}
138 -
139 -.loading {
140 - width: calc(100% - 4rem);
141 - max-width: 1200px;
142 - min-height: 50px;
143 - border-radius: 12px;
144 - position: relative;
145 - overflow: hidden;
146 - margin: 2rem auto;
147 - opacity: 0;
148 - animation: fadeIn 500ms ease-out 500ms forwards;
149 -}
150 -
151 -.light-mode .loading {
152 - background: var(--color-border-light);
153 -}
154 -
155 -.dark-mode .loading {
156 - background: var(--color-border-dark);
157 -}
158 -
159 -@keyframes fadeIn {
160 - 0% {
161 - opacity: 0;
162 - }
163 - 100% {
164 - opacity: 1;
165 - }
166 -}
167 -
168 -.loading::before {
169 - content: "";
170 - position: absolute;
171 - top: 0;
172 - left: 0;
173 - width: 100%;
174 - height: 100%;
175 -}
176 -
177 -.dark-mode .loading::before {
178 - background: linear-gradient(
179 - 90deg,
180 - var(--color-background-dark),
181 - var(--color-border-dark),
182 - var(--color-background-dark)
183 - );
184 - animation: shimmer 2s infinite;
185 - animation-delay: 250ms;
186 - background-size: 200% 100%;
187 -}
188 -
189 -.light-mode .loading::before {
190 - background: linear-gradient(
191 - 90deg,
192 - var(--color-background-light),
193 - color-mix(in srgb, var(--color-border-light) 95%, black),
194 - var(--color-background-light)
195 - );
196 - animation: shimmer 2s infinite;
197 - animation-delay: 250ms;
198 - background-size: 200% 100%;
199 -}
200 -
201 -@keyframes shimmer {
202 - 0% {
203 - background-position: 200% 0;
204 - }
205 - 100% {
206 - background-position: -200% 0;
207 - }
208 -}
webui/index.html
-4
@@ -12,7 +12,6 @@
12 <link rel="stylesheet" href="css/toast.css">
13 <link rel="stylesheet" href="css/settings.css">
14 <link rel="stylesheet" href="css/modals.css">
15 - <link rel="stylesheet" href="css/modals2.css">
15 <link rel="stylesheet" href="css/speech.css">
16 <link rel="stylesheet" href="css/scheduler-datepicker.css">
17 <link rel="stylesheet" href="css/notification.css">
@@ -1181,9 +1180,6 @@
1180 </template>
1181 </div>
1182
1184 - <!-- Full Screen Input Modal -->
1185 - <x-component path="modals/full-screen-input.html"></x-component>
1186 -
1183 <!-- Drag and Drop Overlay Component -->
1184 <x-component path="chat/attachments/dragDropOverlay.html"></x-component>
1185
webui/js/messages.js
+1 -1
@@ -1,5 +1,5 @@
1 // message actions and components
2 -import { store as imageViewerStore } from "/components/modals/image-viewer-store.js";
2 +import { store as imageViewerStore } from "../components/modals/image-viewer/image-viewer-store.js";
3 import { marked } from "../vendor/marked/marked.esm.js";
4 import { store as _messageResizeStore } from "/components/messages/resize/message-resize-store.js"; // keep here, required in html
5 import { store as attachmentsStore } from "/components/chat/attachments/attachmentsStore.js";