@salmexio/ui 1.0.0 → 1.2.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.
Files changed (64) hide show
  1. package/README.md +1 -1
  2. package/dist/dialogs/ContextMenu/ContextMenu.svelte +17 -7
  3. package/dist/dialogs/ContextMenu/ContextMenu.svelte.d.ts +1 -1
  4. package/dist/dialogs/Modal/Modal.svelte +37 -4
  5. package/dist/dialogs/Modal/Modal.svelte.d.ts +1 -1
  6. package/dist/feedback/Alert/Alert.svelte +67 -19
  7. package/dist/feedback/Alert/Alert.svelte.d.ts +1 -1
  8. package/dist/feedback/ProgressBar/ProgressBar.svelte +33 -11
  9. package/dist/feedback/ProgressBar/ProgressBar.svelte.d.ts +3 -3
  10. package/dist/feedback/ProgressBar/ProgressBar.svelte.d.ts.map +1 -1
  11. package/dist/feedback/Skeleton/Skeleton.svelte +12 -4
  12. package/dist/feedback/Skeleton/Skeleton.svelte.d.ts +1 -1
  13. package/dist/feedback/Spinner/Spinner.svelte +5 -3
  14. package/dist/feedback/Spinner/Spinner.svelte.d.ts +2 -2
  15. package/dist/feedback/Toast/Toaster.svelte +45 -13
  16. package/dist/feedback/Toast/Toaster.svelte.d.ts +1 -1
  17. package/dist/forms/Checkbox/Checkbox.svelte +37 -9
  18. package/dist/forms/Checkbox/Checkbox.svelte.d.ts +1 -1
  19. package/dist/forms/Select/Select.svelte +28 -12
  20. package/dist/forms/Select/Select.svelte.d.ts +1 -1
  21. package/dist/forms/Slider/Slider.svelte +66 -38
  22. package/dist/forms/Slider/Slider.svelte.d.ts +2 -2
  23. package/dist/forms/Slider/Slider.svelte.d.ts.map +1 -1
  24. package/dist/forms/TextInput/TextInput.svelte +35 -7
  25. package/dist/forms/TextInput/TextInput.svelte.d.ts +1 -1
  26. package/dist/forms/Textarea/Textarea.svelte +22 -7
  27. package/dist/forms/Textarea/Textarea.svelte.d.ts +1 -1
  28. package/dist/forms/Toggle/Toggle.svelte +71 -12
  29. package/dist/forms/Toggle/Toggle.svelte.d.ts +1 -1
  30. package/dist/layout/Card/Card.svelte +128 -5
  31. package/dist/layout/Card/Card.svelte.d.ts +4 -1
  32. package/dist/layout/Card/Card.svelte.d.ts.map +1 -1
  33. package/dist/layout/Container/Container.svelte +1 -1
  34. package/dist/layout/Container/Container.svelte.d.ts +1 -1
  35. package/dist/layout/ThermalBackground/ThermalBackground.svelte +275 -0
  36. package/dist/layout/ThermalBackground/ThermalBackground.svelte.d.ts +14 -0
  37. package/dist/layout/ThermalBackground/ThermalBackground.svelte.d.ts.map +1 -0
  38. package/dist/layout/ThermalBackground/index.d.ts +2 -0
  39. package/dist/layout/ThermalBackground/index.d.ts.map +1 -0
  40. package/dist/layout/ThermalBackground/index.js +1 -0
  41. package/dist/layout/index.d.ts +1 -0
  42. package/dist/layout/index.d.ts.map +1 -1
  43. package/dist/layout/index.js +1 -0
  44. package/dist/navigation/CommandPalette/CommandPalette.svelte +45 -11
  45. package/dist/navigation/CommandPalette/CommandPalette.svelte.d.ts +1 -1
  46. package/dist/navigation/NavMenu/NavMenu.svelte +800 -0
  47. package/dist/navigation/NavMenu/NavMenu.svelte.d.ts +81 -0
  48. package/dist/navigation/NavMenu/NavMenu.svelte.d.ts.map +1 -0
  49. package/dist/navigation/NavMenu/index.d.ts +3 -0
  50. package/dist/navigation/NavMenu/index.d.ts.map +1 -0
  51. package/dist/navigation/NavMenu/index.js +1 -0
  52. package/dist/navigation/Tabs/Tabs.svelte +73 -11
  53. package/dist/navigation/Tabs/Tabs.svelte.d.ts +1 -1
  54. package/dist/navigation/index.d.ts +2 -0
  55. package/dist/navigation/index.d.ts.map +1 -1
  56. package/dist/navigation/index.js +1 -0
  57. package/dist/primitives/Badge/Badge.svelte +68 -21
  58. package/dist/primitives/Badge/Badge.svelte.d.ts +1 -1
  59. package/dist/primitives/Button/Button.svelte +254 -34
  60. package/dist/primitives/Button/Button.svelte.d.ts +1 -1
  61. package/dist/primitives/Tooltip/Tooltip.svelte +10 -2
  62. package/dist/primitives/Tooltip/Tooltip.svelte.d.ts +1 -1
  63. package/dist/styles/tokens.css +202 -64
  64. package/package.json +3 -3
@@ -1,7 +1,7 @@
1
1
  <!--
2
2
  @component TextInput
3
3
 
4
- Neo-Brutalist Dark — Clean text field with subtle borders and cyan accents.
4
+ INFRARED — Clean text field with subtle borders and vermilion accents.
5
5
  Label, error, hint, prefix/suffix, clearable, password toggle. Full a11y.
6
6
  -->
7
7
  <script lang="ts">
@@ -326,6 +326,7 @@ function handleKeyDown(e: KeyboardEvent) {
326
326
  border: 0;
327
327
  }
328
328
 
329
+ /* Field wrapper — recessed channel carved into the surface */
329
330
  .sx-input-field-wrapper {
330
331
  position: relative;
331
332
  display: flex;
@@ -334,30 +335,48 @@ function handleKeyDown(e: KeyboardEvent) {
334
335
  border: 1px solid var(--sx-color-border-strong);
335
336
  border-radius: var(--sx-radius-md);
336
337
  transition: border-color var(--sx-transition-fast), box-shadow var(--sx-transition-fast);
338
+
339
+ /* Recessed inset — input sits below the surface */
340
+ box-shadow:
341
+ inset 0 1px 3px rgba(0, 0, 0, 0.3),
342
+ inset 0 0 0 1px rgba(0, 0, 0, 0.06);
337
343
  }
338
344
 
339
345
  .sx-input-field-wrapper:hover:not(.sx-input-disabled-wrap):not(.sx-input-focused):not(.sx-input-error) {
340
346
  border-color: var(--sx-color-border-hover);
341
347
  }
342
348
 
349
+ /* Focus — forge glow ring replaces flat ring */
343
350
  .sx-input-focused {
344
- border-color: var(--sx-color-cyan);
345
- box-shadow: 0 0 0 3px var(--sx-color-cyan-ring);
351
+ border-color: var(--sx-color-primary);
352
+ box-shadow:
353
+ inset 0 1px 2px rgba(0, 0, 0, 0.2),
354
+ 0 0 0 3px var(--sx-color-primary-ring),
355
+ 0 0 12px -4px rgba(255, 107, 53, 0.15);
356
+ animation: sx-focus-breathe 2s ease-in-out infinite;
346
357
  }
347
358
 
348
359
  .sx-input-error {
349
360
  border-color: var(--sx-color-red);
350
- box-shadow: 0 0 0 3px var(--sx-color-red-ring);
361
+ box-shadow:
362
+ inset 0 1px 2px rgba(0, 0, 0, 0.2),
363
+ 0 0 0 3px var(--sx-color-red-ring),
364
+ 0 0 10px -4px rgba(220, 38, 38, 0.15);
365
+ animation: sx-error-shake 300ms ease-out;
351
366
  }
352
367
 
353
368
  .sx-input-valid {
354
369
  border-color: var(--sx-color-green);
370
+ box-shadow:
371
+ inset 0 1px 2px rgba(0, 0, 0, 0.2),
372
+ 0 0 8px -4px rgba(74, 222, 128, 0.15);
355
373
  }
356
374
 
357
375
  .sx-input-disabled-wrap {
358
376
  opacity: 0.5;
359
377
  cursor: not-allowed;
360
378
  background: var(--sx-color-surface-2);
379
+ box-shadow: none;
361
380
  }
362
381
 
363
382
  .sx-input-prefix,
@@ -476,7 +495,7 @@ function handleKeyDown(e: KeyboardEvent) {
476
495
  .sx-input-loading {
477
496
  display: flex;
478
497
  align-items: center;
479
- color: var(--sx-color-cyan);
498
+ color: var(--sx-color-primary);
480
499
  }
481
500
 
482
501
  .sx-input-spinner {
@@ -513,7 +532,7 @@ function handleKeyDown(e: KeyboardEvent) {
513
532
 
514
533
  .sx-input-clear:focus-visible,
515
534
  .sx-input-password-toggle:focus-visible {
516
- outline: 2px solid var(--sx-color-cyan);
535
+ outline: 2px solid var(--sx-color-primary);
517
536
  outline-offset: 2px;
518
537
  }
519
538
 
@@ -549,12 +568,21 @@ function handleKeyDown(e: KeyboardEvent) {
549
568
  }
550
569
 
551
570
  .sx-input-charcount-warn {
552
- color: var(--sx-color-gold);
571
+ color: var(--sx-color-secondary);
553
572
  }
554
573
 
555
574
  @media (prefers-reduced-motion: reduce) {
556
575
  .sx-input-spinner {
557
576
  animation: none;
558
577
  }
578
+
579
+ .sx-input-focused {
580
+ animation: none;
581
+ box-shadow: 0 0 0 3px var(--sx-color-primary-ring);
582
+ }
583
+
584
+ .sx-input-error {
585
+ animation: none;
586
+ }
559
587
  }
560
588
  </style>
@@ -41,7 +41,7 @@ interface Props extends Omit<HTMLInputAttributes, 'class' | 'size' | 'inputmode'
41
41
  /**
42
42
  * TextInput
43
43
  *
44
- * Neo-Brutalist Dark — Clean text field with subtle borders and cyan accents.
44
+ * INFRARED — Clean text field with subtle borders and vermilion accents.
45
45
  * Label, error, hint, prefix/suffix, clearable, password toggle. Full a11y.
46
46
  */
47
47
  declare const TextInput: import("svelte").Component<Props, {}, "value">;
@@ -1,7 +1,7 @@
1
1
  <!--
2
2
  @component Textarea
3
3
 
4
- Neo-Brutalist Dark — Multi-line text input with custom resize handle,
4
+ INFRARED — Multi-line text input with custom resize handle,
5
5
  auto-resize, character count, validation states, and full accessibility.
6
6
  Follows TextInput visual patterns.
7
7
 
@@ -368,7 +368,7 @@ onMount(() => {
368
368
  border: 0;
369
369
  }
370
370
 
371
- /* Field wrapper */
371
+ /* Field wrapper — recessed channel carved into the surface */
372
372
  .sx-textarea-field-wrapper {
373
373
  position: relative;
374
374
  display: flex;
@@ -380,6 +380,11 @@ onMount(() => {
380
380
  transition:
381
381
  border-color var(--sx-transition-fast),
382
382
  box-shadow var(--sx-transition-fast);
383
+
384
+ /* Recessed inset */
385
+ box-shadow:
386
+ inset 0 1px 3px rgba(0, 0, 0, 0.3),
387
+ inset 0 0 0 1px rgba(0, 0, 0, 0.06);
383
388
  }
384
389
 
385
390
  .sx-textarea-resizable {
@@ -391,23 +396,33 @@ onMount(() => {
391
396
  }
392
397
 
393
398
  .sx-textarea-focused {
394
- border-color: var(--sx-color-cyan);
395
- box-shadow: 0 0 0 3px var(--sx-color-cyan-ring);
399
+ border-color: var(--sx-color-primary);
400
+ box-shadow:
401
+ inset 0 1px 2px rgba(0, 0, 0, 0.2),
402
+ 0 0 0 3px var(--sx-color-primary-ring),
403
+ 0 0 12px -4px rgba(255, 107, 53, 0.15);
396
404
  }
397
405
 
398
406
  .sx-textarea-error-state {
399
407
  border-color: var(--sx-color-red);
400
- box-shadow: 0 0 0 3px var(--sx-color-red-ring);
408
+ box-shadow:
409
+ inset 0 1px 2px rgba(0, 0, 0, 0.2),
410
+ 0 0 0 3px var(--sx-color-red-ring),
411
+ 0 0 10px -4px rgba(220, 38, 38, 0.15);
401
412
  }
402
413
 
403
414
  .sx-textarea-success-state {
404
415
  border-color: var(--sx-color-green);
416
+ box-shadow:
417
+ inset 0 1px 2px rgba(0, 0, 0, 0.2),
418
+ 0 0 8px -4px rgba(74, 222, 128, 0.15);
405
419
  }
406
420
 
407
421
  .sx-textarea-disabled {
408
422
  opacity: 0.5;
409
423
  cursor: not-allowed;
410
424
  background: var(--sx-color-surface-2);
425
+ box-shadow: none;
411
426
  }
412
427
 
413
428
  .sx-textarea-dragging {
@@ -480,7 +495,7 @@ onMount(() => {
480
495
  }
481
496
 
482
497
  .sx-textarea-handle-active {
483
- color: var(--sx-color-cyan);
498
+ color: var(--sx-color-primary);
484
499
  }
485
500
 
486
501
  /* Vertical: bar along the bottom edge */
@@ -580,7 +595,7 @@ onMount(() => {
580
595
  }
581
596
 
582
597
  .sx-textarea-charcount-warning {
583
- color: var(--sx-color-gold);
598
+ color: var(--sx-color-secondary);
584
599
  }
585
600
 
586
601
  .sx-textarea-charcount-exceeded {
@@ -32,7 +32,7 @@ interface Props {
32
32
  /**
33
33
  * Textarea
34
34
  *
35
- * Neo-Brutalist Dark — Multi-line text input with custom resize handle,
35
+ * INFRARED — Multi-line text input with custom resize handle,
36
36
  * auto-resize, character count, validation states, and full accessibility.
37
37
  * Follows TextInput visual patterns.
38
38
  *
@@ -1,7 +1,7 @@
1
1
  <!--
2
2
  @component Toggle
3
3
 
4
- Neo-Brutalist Dark — Accessible toggle switch with on/off states,
4
+ INFRARED — Accessible toggle switch with on/off states,
5
5
  label positioning, size variants, and keyboard support.
6
6
  Uses role="switch" with aria-checked for screen readers.
7
7
 
@@ -115,7 +115,7 @@ function toggle() {
115
115
  pointer-events: none;
116
116
  }
117
117
 
118
- /* Track */
118
+ /* Track — recessed channel for the physical switch */
119
119
  .sx-toggle-track {
120
120
  position: relative;
121
121
  flex-shrink: 0;
@@ -130,7 +130,13 @@ function toggle() {
130
130
  cursor: pointer;
131
131
  transition:
132
132
  background var(--sx-transition-fast),
133
- border-color var(--sx-transition-fast);
133
+ border-color var(--sx-transition-fast),
134
+ box-shadow var(--sx-transition-fast);
135
+
136
+ /* Recessed inset — the track sits below the surface */
137
+ box-shadow:
138
+ inset 0 1px 3px rgba(0, 0, 0, 0.4),
139
+ inset 0 0 0 1px rgba(0, 0, 0, 0.1);
134
140
  }
135
141
 
136
142
  .sx-toggle-track:hover:not(:disabled) {
@@ -139,32 +145,80 @@ function toggle() {
139
145
 
140
146
  .sx-toggle-track:focus-visible {
141
147
  outline: none;
142
- box-shadow: 0 0 0 3px var(--sx-color-cyan-ring);
148
+ box-shadow:
149
+ inset 0 1px 3px rgba(0, 0, 0, 0.4),
150
+ 0 0 0 3px var(--sx-color-primary-ring);
143
151
  }
144
152
 
153
+ /* Active track — forge glow fills the channel */
145
154
  .sx-toggle-checked {
146
- background: var(--sx-color-cyan);
147
- border-color: var(--sx-color-cyan);
155
+ background:
156
+ linear-gradient(
157
+ 135deg,
158
+ #FF6B35 0%,
159
+ #C8A84E 50%,
160
+ #3D8B8B 100%
161
+ );
162
+ background-size: 200% 200%;
163
+ border-color: rgba(255, 107, 53, 0.4);
164
+ animation: sx-toggle-drift 6s ease-in-out infinite;
165
+ box-shadow:
166
+ inset 0 1px 2px rgba(0, 0, 0, 0.2),
167
+ 0 0 12px -3px rgba(255, 107, 53, 0.3);
148
168
  }
149
169
 
150
170
  .sx-toggle-checked:hover:not(:disabled) {
151
- border-color: var(--sx-color-cyan);
152
- background: var(--sx-color-cyan-bright, var(--sx-color-cyan));
171
+ border-color: rgba(255, 107, 53, 0.5);
172
+ }
173
+
174
+ @keyframes sx-toggle-drift {
175
+ 0%, 100% { background-position: 0% 50%; }
176
+ 50% { background-position: 100% 50%; }
153
177
  }
154
178
 
155
- /* Thumb */
179
+ /* Thumb — physical raised knob with 3D depth */
156
180
  .sx-toggle-thumb {
157
181
  display: block;
158
182
  width: var(--sx-toggle-thumb, 18px);
159
183
  height: var(--sx-toggle-thumb, 18px);
160
184
  border-radius: var(--sx-radius-full);
161
- background: var(--sx-color-text);
162
- transition: transform var(--sx-transition-fast);
163
- box-shadow: var(--sx-shadow-sm);
185
+ background:
186
+ linear-gradient(
187
+ 180deg,
188
+ rgba(255, 255, 255, 0.15) 0%,
189
+ transparent 50%,
190
+ rgba(0, 0, 0, 0.1) 100%
191
+ ),
192
+ var(--sx-gray-200);
193
+ transition: transform 200ms var(--sx-ease-spring),
194
+ box-shadow 200ms var(--sx-ease-spring);
195
+ position: relative;
196
+
197
+ /* 3D extrusion — raised knob */
198
+ box-shadow:
199
+ 0 1px 0 0 rgba(255, 255, 255, 0.2),
200
+ 0 1px 0 0 rgba(0, 0, 0, 0.15),
201
+ 0 2px 0 0 rgba(0, 0, 0, 0.1),
202
+ 0 3px 4px -1px rgba(0, 0, 0, 0.3);
164
203
  }
165
204
 
166
205
  .sx-toggle-checked .sx-toggle-thumb {
167
206
  transform: translateX(calc(var(--sx-toggle-w, 44px) - var(--sx-toggle-thumb, 18px) - 6px));
207
+
208
+ /* Active knob glows with forge warmth */
209
+ box-shadow:
210
+ 0 1px 0 0 rgba(255, 200, 150, 0.3),
211
+ 0 1px 0 0 rgba(0, 0, 0, 0.15),
212
+ 0 2px 0 0 rgba(0, 0, 0, 0.1),
213
+ 0 3px 4px -1px rgba(0, 0, 0, 0.3),
214
+ 0 0 8px -2px rgba(255, 107, 53, 0.25);
215
+ }
216
+
217
+ /* Press — knob pushes down */
218
+ .sx-toggle-track:active:not(:disabled) .sx-toggle-thumb {
219
+ box-shadow:
220
+ 0 1px 0 0 rgba(0, 0, 0, 0.1),
221
+ 0 1px 2px -1px rgba(0, 0, 0, 0.2);
168
222
  }
169
223
 
170
224
  /* Size variants */
@@ -216,6 +270,11 @@ function toggle() {
216
270
  .sx-toggle-thumb {
217
271
  transition: none;
218
272
  }
273
+
274
+ .sx-toggle-checked {
275
+ animation: none;
276
+ background: var(--sx-color-primary);
277
+ }
219
278
  }
220
279
 
221
280
  @media (forced-colors: active) {
@@ -24,7 +24,7 @@ interface Props {
24
24
  /**
25
25
  * Toggle
26
26
  *
27
- * Neo-Brutalist Dark — Accessible toggle switch with on/off states,
27
+ * INFRARED — Accessible toggle switch with on/off states,
28
28
  * label positioning, size variants, and keyboard support.
29
29
  * Uses role="switch" with aria-checked for screen readers.
30
30
  *
@@ -1,7 +1,7 @@
1
1
  <!--
2
2
  @component Card
3
3
 
4
- Neo-Brutalist Dark — Glassmorphic panel with frosted background, subtle borders.
4
+ INFRARED — Glassmorphic panel with frosted background, subtle borders.
5
5
  Optional header/footer, semantic element support.
6
6
 
7
7
  @example
@@ -13,9 +13,12 @@ import type { Snippet } from 'svelte';
13
13
  import { cn } from '../../utils/cn.js';
14
14
 
15
15
  type CardPadding = 'sm' | 'md' | 'lg';
16
+ type CardAccent = 'none' | 'primary' | 'success' | 'warning' | 'error' | 'info' | 'neutral';
16
17
 
17
18
  interface Props {
18
19
  padding?: CardPadding;
20
+ /** Left accent border color */
21
+ accent?: CardAccent;
19
22
  as?: 'div' | 'article' | 'section';
20
23
  id?: string;
21
24
  ariaLabelledby?: string;
@@ -30,6 +33,7 @@ interface Props {
30
33
 
31
34
  let {
32
35
  padding = 'md',
36
+ accent = 'none',
33
37
  as = 'div',
34
38
  id,
35
39
  ariaLabelledby,
@@ -82,6 +86,7 @@ const currentPadding = $derived(paddingValues[padding]);
82
86
  class={cn(
83
87
  'sx-card',
84
88
  `sx-card-padding-${padding}`,
89
+ accent !== 'none' && `sx-card-accent sx-card-accent-${accent}`,
85
90
  onclick && 'sx-card-clickable',
86
91
  className
87
92
  )}
@@ -112,6 +117,30 @@ const currentPadding = $derived(paddingValues[padding]);
112
117
  -webkit-backdrop-filter: var(--sx-glass-blur);
113
118
  transition: var(--sx-transition-base);
114
119
  transition-property: transform, border-color, box-shadow;
120
+
121
+ /* 3D extrusion — subtle panel depth */
122
+ box-shadow:
123
+ 0 1px 0 0 rgba(255, 255, 255, 0.03),
124
+ 0 1px 0 0 rgba(0, 0, 0, 0.2),
125
+ 0 2px 0 0 rgba(0, 0, 0, 0.15),
126
+ 0 4px 8px -2px rgba(0, 0, 0, 0.3);
127
+ }
128
+
129
+ /* Top-lit bevel — overhead light simulation */
130
+ .sx-card::before {
131
+ content: '';
132
+ position: absolute;
133
+ inset: 0;
134
+ border-radius: inherit;
135
+ pointer-events: none;
136
+ z-index: 0;
137
+ background:
138
+ linear-gradient(
139
+ 180deg,
140
+ rgba(255, 255, 255, 0.04) 0%,
141
+ transparent 40%,
142
+ rgba(0, 0, 0, 0.06) 100%
143
+ );
115
144
  }
116
145
 
117
146
  .sx-card-clickable {
@@ -119,16 +148,100 @@ const currentPadding = $derived(paddingValues[padding]);
119
148
  }
120
149
 
121
150
  .sx-card-clickable:hover {
122
- transform: translateY(-2px);
123
- border-color: var(--sx-color-cyan-active);
124
- box-shadow: var(--sx-shadow-md);
151
+ transform: translateY(-3px);
152
+ border-color: rgba(255, 107, 53, 0.18);
153
+
154
+ /* Hover lifts the panel — deeper extrusion + vermilion glow */
155
+ box-shadow:
156
+ 0 1px 0 0 rgba(255, 255, 255, 0.04),
157
+ 0 1px 0 0 rgba(0, 0, 0, 0.2),
158
+ 0 2px 0 0 rgba(0, 0, 0, 0.15),
159
+ 0 3px 0 0 rgba(0, 0, 0, 0.1),
160
+ 0 8px 20px -4px rgba(0, 0, 0, 0.4),
161
+ 0 0 28px -8px rgba(255, 107, 53, 0.1);
162
+ }
163
+
164
+ .sx-card-clickable:active {
165
+ transform: translateY(0);
166
+ box-shadow:
167
+ 0 1px 0 0 rgba(0, 0, 0, 0.15),
168
+ 0 2px 4px -1px rgba(0, 0, 0, 0.2);
169
+ transition: transform 60ms ease, box-shadow 60ms ease;
125
170
  }
126
171
 
127
172
  .sx-card-clickable:focus-visible {
128
- outline: 2px solid var(--sx-color-cyan);
173
+ outline: 2px solid var(--sx-color-primary);
129
174
  outline-offset: 2px;
130
175
  }
131
176
 
177
+ /* ========================================
178
+ ACCENT — Left colored border with tinted extrusion
179
+ ======================================== */
180
+
181
+ .sx-card-accent {
182
+ border-left: 3px solid var(--sx-color-border-strong);
183
+ }
184
+
185
+ /* Primary — vermilion */
186
+ .sx-card-accent-primary {
187
+ border-left-color: var(--sx-color-primary);
188
+ box-shadow:
189
+ 0 1px 0 0 rgba(255, 255, 255, 0.03),
190
+ 0 1px 0 0 rgba(200, 85, 30, 0.2),
191
+ 0 2px 0 0 rgba(160, 65, 20, 0.12),
192
+ 0 4px 8px -2px rgba(0, 0, 0, 0.3),
193
+ 0 0 8px -4px rgba(255, 107, 53, 0.1);
194
+ }
195
+
196
+ /* Success — green */
197
+ .sx-card-accent-success {
198
+ border-left-color: var(--sx-color-green);
199
+ box-shadow:
200
+ 0 1px 0 0 rgba(255, 255, 255, 0.03),
201
+ 0 1px 0 0 rgba(34, 120, 69, 0.2),
202
+ 0 2px 0 0 rgba(34, 120, 69, 0.12),
203
+ 0 4px 8px -2px rgba(0, 0, 0, 0.3),
204
+ 0 0 8px -4px rgba(34, 197, 94, 0.1);
205
+ }
206
+
207
+ /* Warning — brass */
208
+ .sx-card-accent-warning {
209
+ border-left-color: var(--sx-color-secondary);
210
+ box-shadow:
211
+ 0 1px 0 0 rgba(255, 255, 255, 0.03),
212
+ 0 1px 0 0 rgba(160, 134, 62, 0.2),
213
+ 0 2px 0 0 rgba(130, 108, 50, 0.12),
214
+ 0 4px 8px -2px rgba(0, 0, 0, 0.3),
215
+ 0 0 8px -4px rgba(200, 168, 78, 0.1);
216
+ }
217
+
218
+ /* Error — crimson */
219
+ .sx-card-accent-error {
220
+ border-left-color: var(--sx-color-red);
221
+ box-shadow:
222
+ 0 1px 0 0 rgba(255, 255, 255, 0.03),
223
+ 0 1px 0 0 rgba(180, 30, 30, 0.2),
224
+ 0 2px 0 0 rgba(140, 20, 20, 0.12),
225
+ 0 4px 8px -2px rgba(0, 0, 0, 0.3),
226
+ 0 0 8px -4px rgba(220, 38, 38, 0.1);
227
+ }
228
+
229
+ /* Info — teal */
230
+ .sx-card-accent-info {
231
+ border-left-color: var(--sx-color-teal);
232
+ box-shadow:
233
+ 0 1px 0 0 rgba(255, 255, 255, 0.03),
234
+ 0 1px 0 0 rgba(30, 80, 80, 0.2),
235
+ 0 2px 0 0 rgba(30, 80, 80, 0.12),
236
+ 0 4px 8px -2px rgba(0, 0, 0, 0.3),
237
+ 0 0 8px -4px rgba(61, 139, 139, 0.1);
238
+ }
239
+
240
+ /* Neutral */
241
+ .sx-card-accent-neutral {
242
+ border-left-color: var(--sx-color-border-strong);
243
+ }
244
+
132
245
  @media (prefers-reduced-motion: reduce) {
133
246
  .sx-card {
134
247
  transition: none;
@@ -137,6 +250,10 @@ const currentPadding = $derived(paddingValues[padding]);
137
250
  .sx-card-clickable:hover {
138
251
  transform: none;
139
252
  }
253
+
254
+ .sx-card-clickable:active {
255
+ transform: none;
256
+ }
140
257
  }
141
258
 
142
259
  .sx-card-padding-sm {
@@ -155,13 +272,19 @@ const currentPadding = $derived(paddingValues[padding]);
155
272
  border-bottom: 1px solid var(--sx-color-border);
156
273
  font-weight: 700;
157
274
  letter-spacing: 0.3px;
275
+ position: relative;
276
+ z-index: 1;
158
277
  }
159
278
 
160
279
  .sx-card-footer {
161
280
  border-top: 1px solid var(--sx-color-border);
281
+ position: relative;
282
+ z-index: 1;
162
283
  }
163
284
 
164
285
  .sx-card-content {
165
286
  display: block;
287
+ position: relative;
288
+ z-index: 1;
166
289
  }
167
290
  </style>
@@ -1,7 +1,10 @@
1
1
  import type { Snippet } from 'svelte';
2
2
  type CardPadding = 'sm' | 'md' | 'lg';
3
+ type CardAccent = 'none' | 'primary' | 'success' | 'warning' | 'error' | 'info' | 'neutral';
3
4
  interface Props {
4
5
  padding?: CardPadding;
6
+ /** Left accent border color */
7
+ accent?: CardAccent;
5
8
  as?: 'div' | 'article' | 'section';
6
9
  id?: string;
7
10
  ariaLabelledby?: string;
@@ -16,7 +19,7 @@ interface Props {
16
19
  /**
17
20
  * Card
18
21
  *
19
- * Neo-Brutalist Dark — Glassmorphic panel with frosted background, subtle borders.
22
+ * INFRARED — Glassmorphic panel with frosted background, subtle borders.
20
23
  * Optional header/footer, semantic element support.
21
24
  *
22
25
  * @example
@@ -1 +1 @@
1
- {"version":3,"file":"Card.svelte.d.ts","sourceRoot":"","sources":["../../../src/layout/Card/Card.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAItC,KAAK,WAAW,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAEtC,UAAU,KAAK;IACd,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,EAAE,CAAC,EAAE,KAAK,GAAG,SAAS,GAAG,SAAS,CAAC;IACnC,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;IACtC,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;IAC3C,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB;AAqED;;;;;;;;;GASG;AACH,QAAA,MAAM,IAAI,2CAAwC,CAAC;AACnD,KAAK,IAAI,GAAG,UAAU,CAAC,OAAO,IAAI,CAAC,CAAC;AACpC,eAAe,IAAI,CAAC"}
1
+ {"version":3,"file":"Card.svelte.d.ts","sourceRoot":"","sources":["../../../src/layout/Card/Card.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAItC,KAAK,WAAW,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AACtC,KAAK,UAAU,GAAG,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,GAAG,MAAM,GAAG,SAAS,CAAC;AAE5F,UAAU,KAAK;IACd,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,+BAA+B;IAC/B,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,EAAE,CAAC,EAAE,KAAK,GAAG,SAAS,GAAG,SAAS,CAAC;IACnC,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;IACtC,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;IAC3C,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB;AAwED;;;;;;;;;GASG;AACH,QAAA,MAAM,IAAI,2CAAwC,CAAC;AACnD,KAAK,IAAI,GAAG,UAAU,CAAC,OAAO,IAAI,CAAC,CAAC;AACpC,eAAe,IAAI,CAAC"}
@@ -1,7 +1,7 @@
1
1
  <!--
2
2
  @component Container
3
3
 
4
- Neo-Brutalist Dark — Responsive layout wrapper. Max-width, padding, optional centering.
4
+ INFRARED — Responsive layout wrapper. Max-width, padding, optional centering.
5
5
  Pure layout utility; supports semantic elements.
6
6
  -->
7
7
  <script lang="ts">
@@ -16,7 +16,7 @@ interface Props extends Omit<HTMLAttributes<HTMLDivElement>, 'class'> {
16
16
  /**
17
17
  * Container
18
18
  *
19
- * Neo-Brutalist Dark — Responsive layout wrapper. Max-width, padding, optional centering.
19
+ * INFRARED — Responsive layout wrapper. Max-width, padding, optional centering.
20
20
  * Pure layout utility; supports semantic elements.
21
21
  */
22
22
  declare const Container: import("svelte").Component<Props, {}, "">;