@salmexio/ui 0.4.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +52 -3
- package/dist/dialogs/ContextMenu/ContextMenu.svelte +97 -94
- package/dist/dialogs/ContextMenu/ContextMenu.svelte.d.ts +3 -2
- package/dist/dialogs/ContextMenu/ContextMenu.svelte.d.ts.map +1 -1
- package/dist/dialogs/Modal/Modal.svelte +112 -116
- package/dist/dialogs/Modal/Modal.svelte.d.ts +1 -1
- package/dist/feedback/Alert/Alert.svelte +115 -221
- package/dist/feedback/Alert/Alert.svelte.d.ts +1 -1
- package/dist/feedback/ProgressBar/ProgressBar.svelte +246 -0
- package/dist/feedback/ProgressBar/ProgressBar.svelte.d.ts +40 -0
- package/dist/feedback/ProgressBar/ProgressBar.svelte.d.ts.map +1 -0
- package/dist/feedback/ProgressBar/index.d.ts +2 -0
- package/dist/feedback/ProgressBar/index.d.ts.map +1 -0
- package/dist/feedback/ProgressBar/index.js +1 -0
- package/dist/feedback/Skeleton/Skeleton.svelte +153 -0
- package/dist/feedback/Skeleton/Skeleton.svelte.d.ts +37 -0
- package/dist/feedback/Skeleton/Skeleton.svelte.d.ts.map +1 -0
- package/dist/feedback/Skeleton/index.d.ts +2 -0
- package/dist/feedback/Skeleton/index.d.ts.map +1 -0
- package/dist/feedback/Skeleton/index.js +1 -0
- package/dist/feedback/Spinner/Spinner.svelte +86 -151
- package/dist/feedback/Spinner/Spinner.svelte.d.ts +5 -3
- package/dist/feedback/Spinner/Spinner.svelte.d.ts.map +1 -1
- package/dist/feedback/Toast/Toaster.svelte +431 -0
- package/dist/feedback/Toast/Toaster.svelte.d.ts +22 -0
- package/dist/feedback/Toast/Toaster.svelte.d.ts.map +1 -0
- package/dist/feedback/Toast/index.d.ts +4 -0
- package/dist/feedback/Toast/index.d.ts.map +1 -0
- package/dist/feedback/Toast/index.js +2 -0
- package/dist/feedback/Toast/toastStore.d.ts +34 -0
- package/dist/feedback/Toast/toastStore.d.ts.map +1 -0
- package/dist/feedback/Toast/toastStore.js +43 -0
- package/dist/feedback/index.d.ts +4 -0
- package/dist/feedback/index.d.ts.map +1 -1
- package/dist/feedback/index.js +3 -0
- package/dist/forms/Checkbox/Checkbox.svelte +82 -104
- package/dist/forms/Checkbox/Checkbox.svelte.d.ts +1 -1
- package/dist/forms/Select/Select.svelte +137 -179
- package/dist/forms/Select/Select.svelte.d.ts +1 -1
- package/dist/forms/Slider/Slider.svelte +356 -0
- package/dist/forms/Slider/Slider.svelte.d.ts +50 -0
- package/dist/forms/Slider/Slider.svelte.d.ts.map +1 -0
- package/dist/forms/Slider/index.d.ts +2 -0
- package/dist/forms/Slider/index.d.ts.map +1 -0
- package/dist/forms/Slider/index.js +1 -0
- package/dist/forms/TextInput/TextInput.svelte +151 -167
- package/dist/forms/TextInput/TextInput.svelte.d.ts +1 -1
- package/dist/forms/Textarea/Textarea.svelte +615 -0
- package/dist/forms/Textarea/Textarea.svelte.d.ts +47 -0
- package/dist/forms/Textarea/Textarea.svelte.d.ts.map +1 -0
- package/dist/forms/Textarea/index.d.ts +2 -0
- package/dist/forms/Textarea/index.d.ts.map +1 -0
- package/dist/forms/Textarea/index.js +1 -0
- package/dist/forms/Toggle/Toggle.svelte +239 -0
- package/dist/forms/Toggle/Toggle.svelte.d.ts +39 -0
- package/dist/forms/Toggle/Toggle.svelte.d.ts.map +1 -0
- package/dist/forms/Toggle/index.d.ts +2 -0
- package/dist/forms/Toggle/index.d.ts.map +1 -0
- package/dist/forms/Toggle/index.js +1 -0
- package/dist/forms/index.d.ts +3 -0
- package/dist/forms/index.d.ts.map +1 -1
- package/dist/forms/index.js +3 -0
- package/dist/index.d.ts +0 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -1
- package/dist/layout/Card/Card.svelte +64 -39
- package/dist/layout/Card/Card.svelte.d.ts +1 -1
- package/dist/layout/Card/Card.svelte.d.ts.map +1 -1
- package/dist/layout/Container/Container.svelte +71 -71
- package/dist/layout/Container/Container.svelte.d.ts +2 -2
- package/dist/navigation/CommandPalette/CommandPalette.svelte +407 -189
- package/dist/navigation/CommandPalette/CommandPalette.svelte.d.ts +8 -3
- package/dist/navigation/CommandPalette/CommandPalette.svelte.d.ts.map +1 -1
- package/dist/navigation/Tabs/Tabs.svelte +95 -181
- package/dist/navigation/Tabs/Tabs.svelte.d.ts +2 -2
- package/dist/primitives/Badge/Badge.svelte +83 -220
- package/dist/primitives/Badge/Badge.svelte.d.ts +2 -2
- package/dist/primitives/Badge/Badge.svelte.d.ts.map +1 -1
- package/dist/primitives/Button/Button.svelte +144 -195
- package/dist/primitives/Button/Button.svelte.d.ts +3 -3
- package/dist/primitives/Button/Button.svelte.d.ts.map +1 -1
- package/dist/primitives/Tooltip/Tooltip.svelte +260 -0
- package/dist/primitives/Tooltip/Tooltip.svelte.d.ts +36 -0
- package/dist/primitives/Tooltip/Tooltip.svelte.d.ts.map +1 -0
- package/dist/primitives/Tooltip/index.d.ts +2 -0
- package/dist/primitives/Tooltip/index.d.ts.map +1 -0
- package/dist/primitives/Tooltip/index.js +1 -0
- package/dist/primitives/index.d.ts +1 -0
- package/dist/primitives/index.d.ts.map +1 -1
- package/dist/primitives/index.js +1 -0
- package/dist/styles/tokens.css +197 -265
- package/package.json +5 -5
- package/dist/windowing/Window/Window.svelte +0 -637
- package/dist/windowing/Window/Window.svelte.d.ts +0 -65
- package/dist/windowing/Window/Window.svelte.d.ts.map +0 -1
- package/dist/windowing/Window/index.d.ts +0 -2
- package/dist/windowing/Window/index.d.ts.map +0 -1
- package/dist/windowing/Window/index.js +0 -1
- package/dist/windowing/WindowManager/WindowManager.svelte +0 -425
- package/dist/windowing/WindowManager/WindowManager.svelte.d.ts +0 -38
- package/dist/windowing/WindowManager/WindowManager.svelte.d.ts.map +0 -1
- package/dist/windowing/WindowManager/index.d.ts +0 -2
- package/dist/windowing/WindowManager/index.d.ts.map +0 -1
- package/dist/windowing/WindowManager/index.js +0 -1
- package/dist/windowing/index.d.ts +0 -5
- package/dist/windowing/index.d.ts.map +0 -1
- package/dist/windowing/index.js +0 -3
- package/dist/windowing/windowStore.svelte.d.ts +0 -49
- package/dist/windowing/windowStore.svelte.d.ts.map +0 -1
- package/dist/windowing/windowStore.svelte.js +0 -170
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<!--
|
|
2
2
|
@component Modal
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
Neo-Brutalist Dark — Dialog with glass surface, subtle border, clean header.
|
|
5
5
|
Follows WAI-ARIA Dialog (Modal) pattern: focus trap, restore focus on close,
|
|
6
6
|
aria-labelledby, aria-describedby, aria-modal. Escape and backdrop close.
|
|
7
7
|
For full inert support (background not focusable), render modal in a portal
|
|
@@ -88,10 +88,10 @@ function setInitialFocus() {
|
|
|
88
88
|
return;
|
|
89
89
|
}
|
|
90
90
|
if (!dialogElement) return;
|
|
91
|
-
const titleEl = dialogElement.querySelector<HTMLElement>('.
|
|
92
|
-
const body = dialogElement.querySelector('.
|
|
91
|
+
const titleEl = dialogElement.querySelector<HTMLElement>('.sx-modal-title-wrap');
|
|
92
|
+
const body = dialogElement.querySelector('.sx-modal-body');
|
|
93
93
|
const first = body?.querySelector<HTMLElement>(FOCUSABLE);
|
|
94
|
-
const closeBtn = dialogElement.querySelector<HTMLElement>('.
|
|
94
|
+
const closeBtn = dialogElement.querySelector<HTMLElement>('.sx-modal-close');
|
|
95
95
|
|
|
96
96
|
if (initialFocusStrategy === 'title' && titleEl) {
|
|
97
97
|
titleEl.focus();
|
|
@@ -163,7 +163,7 @@ const closeLabel = $derived(closeBtnAriaLabel ?? 'Close dialog');
|
|
|
163
163
|
{#if open}
|
|
164
164
|
<!-- Backdrop -->
|
|
165
165
|
<div
|
|
166
|
-
class="
|
|
166
|
+
class="sx-modal-backdrop sx-modal-position-{position}"
|
|
167
167
|
role="presentation"
|
|
168
168
|
onclick={handleBackdropClick}
|
|
169
169
|
onkeydown={() => {}}
|
|
@@ -171,7 +171,7 @@ const closeLabel = $derived(closeBtnAriaLabel ?? 'Close dialog');
|
|
|
171
171
|
<div
|
|
172
172
|
bind:this={dialogElement}
|
|
173
173
|
id={modalId}
|
|
174
|
-
class="
|
|
174
|
+
class="sx-modal-container sx-modal-{size} sx-modal-scroll-{scrollBehavior} {className}"
|
|
175
175
|
role="dialog"
|
|
176
176
|
aria-modal="true"
|
|
177
177
|
aria-labelledby={titleId}
|
|
@@ -179,18 +179,18 @@ const closeLabel = $derived(closeBtnAriaLabel ?? 'Close dialog');
|
|
|
179
179
|
data-testid={testId}
|
|
180
180
|
>
|
|
181
181
|
{#if header || title || showCloseButton}
|
|
182
|
-
<div class="
|
|
183
|
-
<div id={titleId} class="
|
|
182
|
+
<div class="sx-modal-header">
|
|
183
|
+
<div id={titleId} class="sx-modal-title-wrap" tabindex="-1">
|
|
184
184
|
{#if header}
|
|
185
185
|
{@render header()}
|
|
186
186
|
{:else if title}
|
|
187
|
-
<h2 class="
|
|
187
|
+
<h2 class="sx-modal-title">{title}</h2>
|
|
188
188
|
{/if}
|
|
189
189
|
</div>
|
|
190
190
|
{#if showCloseButton && !preventClose}
|
|
191
191
|
<button
|
|
192
192
|
type="button"
|
|
193
|
-
class="
|
|
193
|
+
class="sx-modal-close"
|
|
194
194
|
onclick={handleClose}
|
|
195
195
|
aria-label={closeLabel}
|
|
196
196
|
>
|
|
@@ -203,12 +203,12 @@ const closeLabel = $derived(closeBtnAriaLabel ?? 'Close dialog');
|
|
|
203
203
|
</div>
|
|
204
204
|
{/if}
|
|
205
205
|
{#if children}
|
|
206
|
-
<div id={descriptionId} class="
|
|
206
|
+
<div id={descriptionId} class="sx-modal-body">
|
|
207
207
|
{@render children()}
|
|
208
208
|
</div>
|
|
209
209
|
{/if}
|
|
210
210
|
{#if footer}
|
|
211
|
-
<div class="
|
|
211
|
+
<div class="sx-modal-footer">
|
|
212
212
|
{@render footer()}
|
|
213
213
|
</div>
|
|
214
214
|
{/if}
|
|
@@ -217,28 +217,32 @@ const closeLabel = $derived(closeBtnAriaLabel ?? 'Close dialog');
|
|
|
217
217
|
{/if}
|
|
218
218
|
|
|
219
219
|
<style>
|
|
220
|
-
|
|
220
|
+
/* ========================================
|
|
221
|
+
BACKDROP
|
|
222
|
+
======================================== */
|
|
223
|
+
.sx-modal-backdrop {
|
|
221
224
|
position: fixed;
|
|
222
225
|
inset: 0;
|
|
223
|
-
z-index: var(--
|
|
226
|
+
z-index: var(--sx-z-modal-backdrop, 1040);
|
|
224
227
|
display: flex;
|
|
225
228
|
justify-content: center;
|
|
226
|
-
padding: var(--
|
|
227
|
-
background:
|
|
229
|
+
padding: var(--sx-space-6);
|
|
230
|
+
background: rgba(10, 10, 15, 0.7);
|
|
231
|
+
backdrop-filter: blur(4px);
|
|
228
232
|
overflow-y: auto;
|
|
229
|
-
animation:
|
|
233
|
+
animation: sx-modal-fade-in var(--sx-transition-base);
|
|
230
234
|
}
|
|
231
235
|
|
|
232
|
-
.
|
|
236
|
+
.sx-modal-position-center {
|
|
233
237
|
align-items: center;
|
|
234
238
|
}
|
|
235
239
|
|
|
236
|
-
.
|
|
240
|
+
.sx-modal-position-top {
|
|
237
241
|
align-items: flex-start;
|
|
238
242
|
padding-top: 3rem;
|
|
239
243
|
}
|
|
240
244
|
|
|
241
|
-
@keyframes
|
|
245
|
+
@keyframes sx-modal-fade-in {
|
|
242
246
|
from {
|
|
243
247
|
opacity: 0;
|
|
244
248
|
}
|
|
@@ -247,192 +251,184 @@ const closeLabel = $derived(closeBtnAriaLabel ?? 'Close dialog');
|
|
|
247
251
|
}
|
|
248
252
|
}
|
|
249
253
|
|
|
250
|
-
|
|
254
|
+
/* ========================================
|
|
255
|
+
CONTAINER
|
|
256
|
+
======================================== */
|
|
257
|
+
.sx-modal-container {
|
|
251
258
|
position: relative;
|
|
252
259
|
display: flex;
|
|
253
260
|
flex-direction: column;
|
|
254
261
|
width: 100%;
|
|
255
262
|
max-height: calc(100vh - 2rem);
|
|
256
|
-
background:
|
|
257
|
-
border:
|
|
258
|
-
border-radius: var(--
|
|
259
|
-
box-shadow:
|
|
260
|
-
|
|
261
|
-
inset -1px -1px 0 rgb(var(--salmex-button-shadow)),
|
|
262
|
-
var(--salmex-shadow-lg);
|
|
263
|
-
animation: salmex-modal-scale-in var(--salmex-transition-slow) ease-out;
|
|
263
|
+
background: var(--sx-color-surface);
|
|
264
|
+
border: 1px solid var(--sx-color-border-strong);
|
|
265
|
+
border-radius: var(--sx-radius-lg);
|
|
266
|
+
box-shadow: var(--sx-shadow-xl);
|
|
267
|
+
animation: sx-modal-scale-in 200ms ease-out;
|
|
264
268
|
overflow: hidden;
|
|
265
269
|
}
|
|
266
270
|
|
|
267
|
-
|
|
268
|
-
box-shadow:
|
|
269
|
-
inset 1px 1px 0 rgb(var(--salmex-button-highlight)),
|
|
270
|
-
inset -1px -1px 0 rgb(var(--salmex-button-shadow)),
|
|
271
|
-
4px 4px 3px rgb(0 0 0 / 0.5);
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
@keyframes salmex-modal-scale-in {
|
|
271
|
+
@keyframes sx-modal-scale-in {
|
|
275
272
|
from {
|
|
276
273
|
opacity: 0;
|
|
277
|
-
transform: scale(0.
|
|
274
|
+
transform: scale(0.95);
|
|
278
275
|
}
|
|
279
276
|
to {
|
|
280
277
|
opacity: 1;
|
|
281
|
-
transform: scale(1)
|
|
278
|
+
transform: scale(1);
|
|
282
279
|
}
|
|
283
280
|
}
|
|
284
281
|
|
|
285
|
-
|
|
282
|
+
/* ========================================
|
|
283
|
+
SIZES
|
|
284
|
+
======================================== */
|
|
285
|
+
.sx-modal-sm {
|
|
286
286
|
max-width: 24rem;
|
|
287
287
|
}
|
|
288
|
-
.
|
|
288
|
+
.sx-modal-md {
|
|
289
289
|
max-width: 28rem;
|
|
290
290
|
}
|
|
291
|
-
.
|
|
291
|
+
.sx-modal-lg {
|
|
292
292
|
max-width: 32rem;
|
|
293
293
|
}
|
|
294
|
-
.
|
|
294
|
+
.sx-modal-xl {
|
|
295
295
|
max-width: 40rem;
|
|
296
296
|
}
|
|
297
|
-
.
|
|
297
|
+
.sx-modal-full {
|
|
298
298
|
max-width: 56rem;
|
|
299
299
|
}
|
|
300
300
|
|
|
301
|
-
|
|
301
|
+
/* ========================================
|
|
302
|
+
SCROLL BEHAVIOR
|
|
303
|
+
======================================== */
|
|
304
|
+
.sx-modal-scroll-inside {
|
|
302
305
|
max-height: calc(100vh - 4rem);
|
|
303
306
|
}
|
|
304
307
|
|
|
305
|
-
.
|
|
308
|
+
.sx-modal-scroll-inside .sx-modal-body {
|
|
306
309
|
overflow-y: auto;
|
|
307
310
|
}
|
|
308
311
|
|
|
309
|
-
/*
|
|
310
|
-
|
|
312
|
+
/* ========================================
|
|
313
|
+
HEADER
|
|
314
|
+
======================================== */
|
|
315
|
+
.sx-modal-header {
|
|
311
316
|
display: flex;
|
|
312
317
|
align-items: center;
|
|
313
318
|
justify-content: space-between;
|
|
314
|
-
gap: var(--
|
|
315
|
-
padding: var(--
|
|
316
|
-
background:
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
rgb(var(--salmex-titlebar-bold))
|
|
320
|
-
);
|
|
321
|
-
color: rgb(var(--salmex-chalk-white));
|
|
322
|
-
border-bottom: 2px solid rgb(var(--salmex-button-dark-edge));
|
|
323
|
-
border-radius: calc(var(--salmex-radius-md) - 2px) calc(var(--salmex-radius-md) - 2px) 0 0;
|
|
319
|
+
gap: var(--sx-space-4);
|
|
320
|
+
padding: var(--sx-space-4);
|
|
321
|
+
background: var(--sx-color-surface-2);
|
|
322
|
+
border-bottom: 1px solid var(--sx-color-border);
|
|
323
|
+
border-radius: calc(var(--sx-radius-lg) - 1px) calc(var(--sx-radius-lg) - 1px) 0 0;
|
|
324
324
|
flex-shrink: 0;
|
|
325
|
-
font-family: var(--salmex-font-display);
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
:global([data-theme='dark']) .salmex-modal-header {
|
|
329
|
-
background: linear-gradient(
|
|
330
|
-
90deg,
|
|
331
|
-
rgb(0 75 180),
|
|
332
|
-
rgb(0 105 210)
|
|
333
|
-
);
|
|
334
325
|
}
|
|
335
326
|
|
|
336
|
-
.
|
|
327
|
+
.sx-modal-title-wrap {
|
|
337
328
|
flex: 1;
|
|
338
329
|
min-width: 0;
|
|
339
330
|
outline: none;
|
|
340
331
|
}
|
|
341
332
|
|
|
342
|
-
.
|
|
343
|
-
outline: 2px solid
|
|
333
|
+
.sx-modal-title-wrap:focus-visible {
|
|
334
|
+
outline: 2px solid var(--sx-color-cyan);
|
|
344
335
|
outline-offset: 2px;
|
|
345
336
|
}
|
|
346
337
|
|
|
347
|
-
.
|
|
338
|
+
.sx-modal-title {
|
|
348
339
|
margin: 0;
|
|
349
|
-
font-
|
|
350
|
-
font-
|
|
351
|
-
|
|
340
|
+
font-family: var(--sx-font-display);
|
|
341
|
+
font-size: var(--sx-text-lg);
|
|
342
|
+
font-weight: 600;
|
|
352
343
|
line-height: 1.3;
|
|
353
|
-
|
|
344
|
+
color: var(--sx-color-text);
|
|
354
345
|
}
|
|
355
346
|
|
|
356
|
-
|
|
347
|
+
/* ========================================
|
|
348
|
+
CLOSE BUTTON
|
|
349
|
+
======================================== */
|
|
350
|
+
.sx-modal-close {
|
|
357
351
|
display: flex;
|
|
358
352
|
align-items: center;
|
|
359
353
|
justify-content: center;
|
|
360
354
|
width: 32px;
|
|
361
355
|
height: 32px;
|
|
362
356
|
padding: 0;
|
|
363
|
-
background:
|
|
364
|
-
border: 1px solid
|
|
365
|
-
border-radius: var(--
|
|
366
|
-
color:
|
|
357
|
+
background: transparent;
|
|
358
|
+
border: 1px solid transparent;
|
|
359
|
+
border-radius: var(--sx-radius-sm);
|
|
360
|
+
color: var(--sx-color-text-secondary);
|
|
367
361
|
cursor: pointer;
|
|
368
362
|
flex-shrink: 0;
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
2px 2px 0 rgb(0 0 0 / 0.3);
|
|
373
|
-
transition: all var(--salmex-transition-fast);
|
|
363
|
+
transition:
|
|
364
|
+
color var(--sx-transition-fast),
|
|
365
|
+
background var(--sx-transition-fast);
|
|
374
366
|
}
|
|
375
367
|
|
|
376
|
-
.
|
|
377
|
-
background:
|
|
368
|
+
.sx-modal-close:hover {
|
|
369
|
+
background: var(--sx-color-surface-3);
|
|
370
|
+
color: var(--sx-color-text);
|
|
378
371
|
}
|
|
379
372
|
|
|
380
|
-
.
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
inset 1px 1px 0 rgb(var(--salmex-button-shadow)),
|
|
384
|
-
1px 1px 0 rgb(0 0 0 / 0.3);
|
|
385
|
-
transform: translate(1px, 1px);
|
|
373
|
+
.sx-modal-close:active {
|
|
374
|
+
background: var(--sx-color-surface-3);
|
|
375
|
+
color: var(--sx-color-text);
|
|
386
376
|
}
|
|
387
377
|
|
|
388
|
-
.
|
|
389
|
-
outline:
|
|
390
|
-
|
|
391
|
-
inset 1px 1px 0 rgb(var(--salmex-button-highlight)),
|
|
392
|
-
inset -1px -1px 0 rgb(var(--salmex-button-shadow)),
|
|
393
|
-
2px 2px 0 rgb(0 0 0 / 0.3),
|
|
394
|
-
0 0 0 2px rgb(var(--salmex-midnight-black)),
|
|
395
|
-
0 0 2px 4px rgb(var(--salmex-crown-yellow));
|
|
378
|
+
.sx-modal-close:focus-visible {
|
|
379
|
+
outline: 2px solid var(--sx-color-cyan);
|
|
380
|
+
outline-offset: 2px;
|
|
396
381
|
}
|
|
397
382
|
|
|
398
|
-
|
|
399
|
-
|
|
383
|
+
/* ========================================
|
|
384
|
+
BODY
|
|
385
|
+
======================================== */
|
|
386
|
+
.sx-modal-body {
|
|
387
|
+
padding: var(--sx-space-6);
|
|
400
388
|
flex: 1;
|
|
401
389
|
min-height: 0;
|
|
402
|
-
|
|
403
|
-
color: rgb(var(--salmex-text-primary));
|
|
390
|
+
color: var(--sx-color-text-secondary);
|
|
404
391
|
}
|
|
405
392
|
|
|
406
|
-
|
|
393
|
+
/* ========================================
|
|
394
|
+
FOOTER
|
|
395
|
+
======================================== */
|
|
396
|
+
.sx-modal-footer {
|
|
407
397
|
display: flex;
|
|
408
398
|
align-items: center;
|
|
409
399
|
justify-content: flex-end;
|
|
410
|
-
gap: var(--
|
|
411
|
-
padding: var(--
|
|
412
|
-
border-top:
|
|
413
|
-
border-radius: 0 0 calc(var(--
|
|
414
|
-
background:
|
|
400
|
+
gap: var(--sx-space-3);
|
|
401
|
+
padding: var(--sx-space-4);
|
|
402
|
+
border-top: 1px solid var(--sx-color-border);
|
|
403
|
+
border-radius: 0 0 calc(var(--sx-radius-lg) - 1px) calc(var(--sx-radius-lg) - 1px);
|
|
404
|
+
background: var(--sx-color-surface-2);
|
|
415
405
|
flex-shrink: 0;
|
|
416
406
|
}
|
|
417
407
|
|
|
408
|
+
/* ========================================
|
|
409
|
+
REDUCED MOTION
|
|
410
|
+
======================================== */
|
|
418
411
|
@media (prefers-reduced-motion: reduce) {
|
|
419
|
-
.
|
|
420
|
-
.
|
|
412
|
+
.sx-modal-backdrop,
|
|
413
|
+
.sx-modal-container {
|
|
421
414
|
animation: none;
|
|
422
415
|
}
|
|
423
416
|
}
|
|
424
417
|
|
|
418
|
+
/* ========================================
|
|
419
|
+
MOBILE
|
|
420
|
+
======================================== */
|
|
425
421
|
@media (max-width: 640px) {
|
|
426
|
-
.
|
|
422
|
+
.sx-modal-backdrop {
|
|
427
423
|
padding: 0;
|
|
428
424
|
align-items: flex-end;
|
|
429
425
|
}
|
|
430
426
|
|
|
431
|
-
.
|
|
427
|
+
.sx-modal-position-top {
|
|
432
428
|
padding-top: 0;
|
|
433
429
|
}
|
|
434
430
|
|
|
435
|
-
.
|
|
431
|
+
.sx-modal-container {
|
|
436
432
|
max-width: 100%;
|
|
437
433
|
max-height: 90vh;
|
|
438
434
|
margin: 0;
|
|
@@ -31,7 +31,7 @@ interface Props {
|
|
|
31
31
|
/**
|
|
32
32
|
* Modal
|
|
33
33
|
*
|
|
34
|
-
*
|
|
34
|
+
* Neo-Brutalist Dark — Dialog with glass surface, subtle border, clean header.
|
|
35
35
|
* Follows WAI-ARIA Dialog (Modal) pattern: focus trap, restore focus on close,
|
|
36
36
|
* aria-labelledby, aria-describedby, aria-modal. Escape and backdrop close.
|
|
37
37
|
* For full inert support (background not focusable), render modal in a portal
|