@salmexio/ui 1.1.0 → 1.2.1

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 (40) hide show
  1. package/dist/dialogs/ContextMenu/ContextMenu.svelte +11 -1
  2. package/dist/dialogs/Modal/Modal.svelte +34 -1
  3. package/dist/feedback/Alert/Alert.svelte +54 -11
  4. package/dist/feedback/ProgressBar/ProgressBar.svelte +11 -8
  5. package/dist/feedback/ProgressBar/ProgressBar.svelte.d.ts +2 -2
  6. package/dist/feedback/ProgressBar/ProgressBar.svelte.d.ts.map +1 -1
  7. package/dist/feedback/Skeleton/Skeleton.svelte +7 -3
  8. package/dist/feedback/Spinner/Spinner.svelte +2 -0
  9. package/dist/feedback/Toast/Toaster.svelte +35 -3
  10. package/dist/forms/Checkbox/Checkbox.svelte +30 -7
  11. package/dist/forms/Select/Select.svelte +19 -3
  12. package/dist/forms/Slider/Slider.svelte +41 -13
  13. package/dist/forms/Slider/Slider.svelte.d.ts +1 -1
  14. package/dist/forms/Slider/Slider.svelte.d.ts.map +1 -1
  15. package/dist/forms/TextInput/TextInput.svelte +19 -1
  16. package/dist/forms/Textarea/Textarea.svelte +18 -3
  17. package/dist/forms/Toggle/Toggle.svelte +70 -11
  18. package/dist/layout/Card/Card.svelte +125 -4
  19. package/dist/layout/Card/Card.svelte.d.ts +3 -0
  20. package/dist/layout/Card/Card.svelte.d.ts.map +1 -1
  21. package/dist/layout/ThermalBackground/ThermalBackground.svelte +2 -40
  22. package/dist/layout/ThermalBackground/ThermalBackground.svelte.d.ts +0 -2
  23. package/dist/layout/ThermalBackground/ThermalBackground.svelte.d.ts.map +1 -1
  24. package/dist/navigation/CommandPalette/CommandPalette.svelte +37 -3
  25. package/dist/navigation/NavMenu/NavMenu.svelte +800 -0
  26. package/dist/navigation/NavMenu/NavMenu.svelte.d.ts +81 -0
  27. package/dist/navigation/NavMenu/NavMenu.svelte.d.ts.map +1 -0
  28. package/dist/navigation/NavMenu/index.d.ts +3 -0
  29. package/dist/navigation/NavMenu/index.d.ts.map +1 -0
  30. package/dist/navigation/NavMenu/index.js +1 -0
  31. package/dist/navigation/Tabs/Tabs.svelte +37 -8
  32. package/dist/navigation/index.d.ts +2 -0
  33. package/dist/navigation/index.d.ts.map +1 -1
  34. package/dist/navigation/index.js +1 -0
  35. package/dist/primitives/Badge/Badge.svelte +55 -10
  36. package/dist/primitives/Button/Button.svelte +220 -71
  37. package/dist/primitives/Tooltip/Tooltip.svelte +33 -1
  38. package/dist/primitives/Tooltip/Tooltip.svelte.d.ts.map +1 -1
  39. package/dist/styles/tokens.css +1 -0
  40. package/package.json +1 -1
@@ -13,7 +13,7 @@
13
13
  import { cn } from '../../utils/cn.js';
14
14
 
15
15
  type SliderSize = 'sm' | 'md' | 'lg';
16
- type SliderColor = 'cyan' | 'green' | 'gold' | 'red' | 'purple';
16
+ type SliderColor = 'primary' | 'green' | 'brass' | 'red' | 'teal';
17
17
 
18
18
  interface Props {
19
19
  /** Accessible label. */
@@ -61,7 +61,7 @@ let {
61
61
  formatValue,
62
62
  hideLabel = false,
63
63
  size = 'md',
64
- color = 'cyan',
64
+ color = 'primary',
65
65
  class: className = '',
66
66
  oninput,
67
67
  onchange,
@@ -207,7 +207,7 @@ function handleChange(e: Event) {
207
207
  box-shadow: 0 0 0 1px var(--sx-slider-accent, var(--sx-color-primary));
208
208
  }
209
209
 
210
- /* Track — WebKit */
210
+ /* Track — WebKit — recessed channel */
211
211
  .sx-slider-input::-webkit-slider-runnable-track {
212
212
  height: var(--sx-slider-track-h, 6px);
213
213
  border-radius: var(--sx-radius-full);
@@ -218,14 +218,20 @@ function handleChange(e: Event) {
218
218
  var(--sx-color-surface-2) var(--sx-slider-fill),
219
219
  var(--sx-color-surface-2) 100%
220
220
  );
221
+ box-shadow:
222
+ inset 0 1px 2px rgba(0, 0, 0, 0.3),
223
+ inset 0 0 0 1px rgba(0, 0, 0, 0.06);
221
224
  }
222
225
 
223
- /* Track — Firefox */
226
+ /* Track — Firefox — recessed channel */
224
227
  .sx-slider-input::-moz-range-track {
225
228
  height: var(--sx-slider-track-h, 6px);
226
229
  border-radius: var(--sx-radius-full);
227
230
  background: var(--sx-color-surface-2);
228
231
  border: none;
232
+ box-shadow:
233
+ inset 0 1px 2px rgba(0, 0, 0, 0.3),
234
+ inset 0 0 0 1px rgba(0, 0, 0, 0.06);
229
235
  }
230
236
 
231
237
  .sx-slider-input::-moz-range-progress {
@@ -234,15 +240,19 @@ function handleChange(e: Event) {
234
240
  background: var(--sx-slider-accent, var(--sx-color-primary));
235
241
  }
236
242
 
237
- /* Thumb — WebKit */
243
+ /* Thumb — WebKit — 3D raised knob */
238
244
  .sx-slider-input::-webkit-slider-thumb {
239
245
  -webkit-appearance: none;
240
246
  width: var(--sx-slider-thumb, 18px);
241
247
  height: var(--sx-slider-thumb, 18px);
242
248
  border-radius: var(--sx-radius-full);
243
- background: var(--sx-color-text);
249
+ background: linear-gradient(180deg, #E8E0D8 0%, #B8B0A8 100%);
244
250
  border: 2px solid var(--sx-slider-accent, var(--sx-color-primary));
245
251
  margin-top: calc((var(--sx-slider-track-h, 6px) - var(--sx-slider-thumb, 18px)) / 2);
252
+ box-shadow:
253
+ 0 1px 0 0 rgba(0, 0, 0, 0.2),
254
+ 0 2px 0 0 rgba(0, 0, 0, 0.12),
255
+ 0 3px 6px -1px rgba(0, 0, 0, 0.25);
246
256
  transition:
247
257
  box-shadow var(--sx-transition-fast),
248
258
  transform var(--sx-transition-fast),
@@ -252,24 +262,35 @@ function handleChange(e: Event) {
252
262
 
253
263
  .sx-slider-input::-webkit-slider-thumb:hover {
254
264
  transform: scale(1.15);
265
+ box-shadow:
266
+ 0 1px 0 0 rgba(0, 0, 0, 0.2),
267
+ 0 2px 0 0 rgba(0, 0, 0, 0.12),
268
+ 0 4px 8px -1px rgba(0, 0, 0, 0.3),
269
+ 0 0 8px -2px var(--sx-slider-glow, rgba(255, 107, 53, 0.25));
255
270
  }
256
271
 
257
272
  .sx-slider-input:focus-visible::-webkit-slider-thumb {
258
273
  box-shadow:
259
274
  0 0 0 3px var(--sx-slider-ring, rgba(255, 107, 53, 0.35)),
260
- 0 0 12px var(--sx-slider-glow, rgba(255, 107, 53, 0.25));
275
+ 0 0 12px var(--sx-slider-glow, rgba(255, 107, 53, 0.25)),
276
+ 0 1px 0 0 rgba(0, 0, 0, 0.2),
277
+ 0 2px 0 0 rgba(0, 0, 0, 0.12);
261
278
  transform: scale(1.2);
262
279
  background: var(--sx-slider-accent, var(--sx-color-primary));
263
280
  border-color: var(--sx-color-text);
264
281
  }
265
282
 
266
- /* Thumb — Firefox */
283
+ /* Thumb — Firefox — 3D raised knob */
267
284
  .sx-slider-input::-moz-range-thumb {
268
285
  width: var(--sx-slider-thumb, 18px);
269
286
  height: var(--sx-slider-thumb, 18px);
270
287
  border-radius: var(--sx-radius-full);
271
- background: var(--sx-color-text);
288
+ background: linear-gradient(180deg, #E8E0D8 0%, #B8B0A8 100%);
272
289
  border: 2px solid var(--sx-slider-accent, var(--sx-color-primary));
290
+ box-shadow:
291
+ 0 1px 0 0 rgba(0, 0, 0, 0.2),
292
+ 0 2px 0 0 rgba(0, 0, 0, 0.12),
293
+ 0 3px 6px -1px rgba(0, 0, 0, 0.25);
273
294
  transition:
274
295
  box-shadow var(--sx-transition-fast),
275
296
  transform var(--sx-transition-fast),
@@ -279,19 +300,26 @@ function handleChange(e: Event) {
279
300
 
280
301
  .sx-slider-input::-moz-range-thumb:hover {
281
302
  transform: scale(1.15);
303
+ box-shadow:
304
+ 0 1px 0 0 rgba(0, 0, 0, 0.2),
305
+ 0 2px 0 0 rgba(0, 0, 0, 0.12),
306
+ 0 4px 8px -1px rgba(0, 0, 0, 0.3),
307
+ 0 0 8px -2px var(--sx-slider-glow, rgba(255, 107, 53, 0.25));
282
308
  }
283
309
 
284
310
  .sx-slider-input:focus-visible::-moz-range-thumb {
285
311
  box-shadow:
286
312
  0 0 0 3px var(--sx-slider-ring, rgba(255, 107, 53, 0.35)),
287
- 0 0 12px var(--sx-slider-glow, rgba(255, 107, 53, 0.25));
313
+ 0 0 12px var(--sx-slider-glow, rgba(255, 107, 53, 0.25)),
314
+ 0 1px 0 0 rgba(0, 0, 0, 0.2),
315
+ 0 2px 0 0 rgba(0, 0, 0, 0.12);
288
316
  transform: scale(1.2);
289
317
  background: var(--sx-slider-accent, var(--sx-color-primary));
290
318
  border-color: var(--sx-color-text);
291
319
  }
292
320
 
293
321
  /* Color variants — accent + focus ring colors */
294
- .sx-slider-color-cyan {
322
+ .sx-slider-color-primary {
295
323
  --sx-slider-accent: var(--sx-color-primary);
296
324
  --sx-slider-ring: rgba(255, 107, 53, 0.35);
297
325
  --sx-slider-glow: rgba(255, 107, 53, 0.25);
@@ -301,7 +329,7 @@ function handleChange(e: Event) {
301
329
  --sx-slider-ring: rgba(74, 222, 128, 0.35);
302
330
  --sx-slider-glow: rgba(74, 222, 128, 0.25);
303
331
  }
304
- .sx-slider-color-gold {
332
+ .sx-slider-color-brass {
305
333
  --sx-slider-accent: var(--sx-color-secondary);
306
334
  --sx-slider-ring: rgba(200, 168, 78, 0.35);
307
335
  --sx-slider-glow: rgba(200, 168, 78, 0.25);
@@ -311,7 +339,7 @@ function handleChange(e: Event) {
311
339
  --sx-slider-ring: rgba(220, 38, 38, 0.35);
312
340
  --sx-slider-glow: rgba(220, 38, 38, 0.25);
313
341
  }
314
- .sx-slider-color-purple {
342
+ .sx-slider-color-teal {
315
343
  --sx-slider-accent: var(--sx-color-teal);
316
344
  --sx-slider-ring: rgba(61, 139, 139, 0.35);
317
345
  --sx-slider-glow: rgba(61, 139, 139, 0.25);
@@ -1,5 +1,5 @@
1
1
  type SliderSize = 'sm' | 'md' | 'lg';
2
- type SliderColor = 'cyan' | 'green' | 'gold' | 'red' | 'purple';
2
+ type SliderColor = 'primary' | 'green' | 'brass' | 'red' | 'teal';
3
3
  interface Props {
4
4
  /** Accessible label. */
5
5
  label: string;
@@ -1 +1 @@
1
- {"version":3,"file":"Slider.svelte.d.ts","sourceRoot":"","sources":["../../../src/forms/Slider/Slider.svelte.ts"],"names":[],"mappings":"AAMA,KAAK,UAAU,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AACrC,KAAK,WAAW,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,CAAC;AAEhE,UAAU,KAAK;IACd,wBAAwB;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,qBAAqB;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,qBAAqB;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,qBAAqB;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,sBAAsB;IACtB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,sBAAsB;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,8CAA8C;IAC9C,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,2CAA2C;IAC3C,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,gDAAgD;IAChD,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IACxC,8BAA8B;IAC9B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,oBAAoB;IACpB,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,oBAAoB;IACpB,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,4BAA4B;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,2BAA2B;IAC3B,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACjC,+CAA+C;IAC/C,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IAClC,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB;AAuED;;;;;;;;;;GAUG;AACH,QAAA,MAAM,MAAM,gDAAwC,CAAC;AACrD,KAAK,MAAM,GAAG,UAAU,CAAC,OAAO,MAAM,CAAC,CAAC;AACxC,eAAe,MAAM,CAAC"}
1
+ {"version":3,"file":"Slider.svelte.d.ts","sourceRoot":"","sources":["../../../src/forms/Slider/Slider.svelte.ts"],"names":[],"mappings":"AAMA,KAAK,UAAU,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AACrC,KAAK,WAAW,GAAG,SAAS,GAAG,OAAO,GAAG,OAAO,GAAG,KAAK,GAAG,MAAM,CAAC;AAElE,UAAU,KAAK;IACd,wBAAwB;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,qBAAqB;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,qBAAqB;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,qBAAqB;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,sBAAsB;IACtB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,sBAAsB;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,8CAA8C;IAC9C,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,2CAA2C;IAC3C,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,gDAAgD;IAChD,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IACxC,8BAA8B;IAC9B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,oBAAoB;IACpB,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,oBAAoB;IACpB,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,4BAA4B;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,2BAA2B;IAC3B,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACjC,+CAA+C;IAC/C,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IAClC,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB;AAuED;;;;;;;;;;GAUG;AACH,QAAA,MAAM,MAAM,gDAAwC,CAAC;AACrD,KAAK,MAAM,GAAG,UAAU,CAAC,OAAO,MAAM,CAAC,CAAC;AACxC,eAAe,MAAM,CAAC"}
@@ -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,31 +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
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);
345
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);
351
365
  animation: sx-error-shake 300ms ease-out;
352
366
  }
353
367
 
354
368
  .sx-input-valid {
355
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);
356
373
  }
357
374
 
358
375
  .sx-input-disabled-wrap {
359
376
  opacity: 0.5;
360
377
  cursor: not-allowed;
361
378
  background: var(--sx-color-surface-2);
379
+ box-shadow: none;
362
380
  }
363
381
 
364
382
  .sx-input-prefix,
@@ -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 {
@@ -392,22 +397,32 @@ onMount(() => {
392
397
 
393
398
  .sx-textarea-focused {
394
399
  border-color: var(--sx-color-primary);
395
- box-shadow: 0 0 0 3px var(--sx-color-primary-ring);
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 {
@@ -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-primary-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-primary);
147
- border-color: var(--sx-color-primary);
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-primary);
152
- background: var(--sx-color-primary);
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 — spring easing for a snappy, physical feel */
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 200ms var(--sx-ease-spring);
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) {
@@ -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,11 +148,25 @@ const currentPadding = $derived(paddingValues[padding]);
119
148
  }
120
149
 
121
150
  .sx-card-clickable:hover {
122
- transform: translateY(-2px);
123
- border-color: rgba(255, 107, 53, 0.15);
151
+ transform: translateY(-3px);
152
+ border-color: rgba(255, 107, 53, 0.18);
153
+
154
+ /* Hover lifts the panel — deeper extrusion + vermilion glow */
124
155
  box-shadow:
125
- var(--sx-shadow-md),
126
- 0 0 24px -6px rgba(255, 107, 53, 0.08);
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;
127
170
  }
128
171
 
129
172
  .sx-card-clickable:focus-visible {
@@ -131,6 +174,74 @@ const currentPadding = $derived(paddingValues[padding]);
131
174
  outline-offset: 2px;
132
175
  }
133
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
+
134
245
  @media (prefers-reduced-motion: reduce) {
135
246
  .sx-card {
136
247
  transition: none;
@@ -139,6 +250,10 @@ const currentPadding = $derived(paddingValues[padding]);
139
250
  .sx-card-clickable:hover {
140
251
  transform: none;
141
252
  }
253
+
254
+ .sx-card-clickable:active {
255
+ transform: none;
256
+ }
142
257
  }
143
258
 
144
259
  .sx-card-padding-sm {
@@ -157,13 +272,19 @@ const currentPadding = $derived(paddingValues[padding]);
157
272
  border-bottom: 1px solid var(--sx-color-border);
158
273
  font-weight: 700;
159
274
  letter-spacing: 0.3px;
275
+ position: relative;
276
+ z-index: 1;
160
277
  }
161
278
 
162
279
  .sx-card-footer {
163
280
  border-top: 1px solid var(--sx-color-border);
281
+ position: relative;
282
+ z-index: 1;
164
283
  }
165
284
 
166
285
  .sx-card-content {
167
286
  display: block;
287
+ position: relative;
288
+ z-index: 1;
168
289
  }
169
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;
@@ -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"}