@digiko-npm/designsystem 0.3.32 → 0.3.34

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 CHANGED
@@ -43,7 +43,7 @@ npm install @digiko-npm/designsystem
43
43
  <span class="ds-badge ds-badge--success">Active</span>
44
44
  ```
45
45
 
46
- ## Components (28)
46
+ ## Components (32)
47
47
 
48
48
  | Core | Essential | Common | Advanced |
49
49
  |------|-----------|--------|----------|
@@ -54,7 +54,10 @@ npm install @digiko-npm/designsystem
54
54
  | Nav | Tooltip | Accordion | Command |
55
55
  | Modal | Avatar | Drawer | |
56
56
  | Toast | Skeleton | Progress | |
57
- | Table | Empty State | | |
57
+ | Table | Empty State | Datepicker | |
58
+ | | | Drop Zone | |
59
+ | | | Custom Select | |
60
+ | | | Sortable | |
58
61
 
59
62
  All components use `ds-` prefix with BEM naming: `.ds-btn`, `.ds-btn--secondary`, `.ds-card__body`.
60
63
 
@@ -1,4 +1,4 @@
1
- /* @ds/designsystem v0.3.32 */
1
+ /* @ds/designsystem v0.3.34 */
2
2
  /* ==========================================================================
3
3
  @digiko-npm/designsystem
4
4
 
@@ -361,10 +361,39 @@
361
361
  --ds-ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1);
362
362
  --ds-ease-bounce: cubic-bezier(0.34, 1.56, 0.64, 1);
363
363
 
364
+ /* --- Backdrop Blur --- */
365
+ --ds-blur-sm: 4px;
366
+ --ds-blur-md: 12px;
367
+ --ds-blur-lg: 20px;
368
+
369
+ /* --- Indicator Sizes --- */
370
+ --ds-dot-size: 6px;
371
+
372
+ /* --- Accent Border --- */
373
+ --ds-accent-border-width: 3px;
374
+
375
+ /* --- Popover/Tooltip Offset --- */
376
+ --ds-offset-sm: 4px;
377
+ --ds-offset-md: 8px;
378
+
364
379
  /* --- Opacity --- */
365
380
  --ds-opacity-disabled: 0.5;
366
381
  }
367
382
 
383
+ /* --- Reduced Motion ---
384
+ Zero out duration tokens so every component that uses
385
+ var(--ds-duration-*) transitions instantly.
386
+ Keyframe animations are handled per-component.
387
+ -------------------------------------------------------- */
388
+ @media (prefers-reduced-motion: reduce) {
389
+ :root {
390
+ --ds-duration-fast: 0s;
391
+ --ds-duration-normal: 0s;
392
+ --ds-duration-slow: 0s;
393
+ --ds-duration-slower: 0s;
394
+ }
395
+ }
396
+
368
397
 
369
398
  /* ==========================================================================
370
399
  Base: Reset
@@ -470,14 +499,11 @@ input[type="number"]::-webkit-inner-spin-button {
470
499
  .ds-no-scrollbar::-webkit-scrollbar { display: none; }
471
500
  .ds-no-scrollbar { -ms-overflow-style: none; scrollbar-width: none; }
472
501
 
473
- /* Reduce motion */
502
+ /* Reduce motion — scroll only.
503
+ Transitions are handled via --ds-duration-* tokens in shadows.css.
504
+ Keyframe animations are handled per-component. */
474
505
  @media (prefers-reduced-motion: reduce) {
475
- *, *::before, *::after {
476
- animation-duration: 0.01ms !important;
477
- animation-iteration-count: 1 !important;
478
- transition-duration: 0.01ms !important;
479
- scroll-behavior: auto !important;
480
- }
506
+ html { scroll-behavior: auto !important; }
481
507
  }
482
508
 
483
509
  /* ==========================================================================
@@ -842,6 +868,10 @@ hr {
842
868
  to { transform: rotate(360deg); }
843
869
  }
844
870
 
871
+ @media (prefers-reduced-motion: reduce) {
872
+ .ds-btn--loading::after { animation: none; opacity: 0.6; }
873
+ }
874
+
845
875
  /* ==========================================================================
846
876
  Component: Card
847
877
  Surface + border, hover with shadow lift, rounded-xl.
@@ -864,6 +894,10 @@ hr {
864
894
  box-shadow: var(--ds-shadow-lg);
865
895
  transform: translateY(-4px);
866
896
  }
897
+ .ds-card--interactive:focus-visible {
898
+ outline: var(--ds-ring-width) solid var(--ds-ring-color);
899
+ outline-offset: var(--ds-ring-offset);
900
+ }
867
901
 
868
902
  /* Elevated card — visible shadow */
869
903
  .ds-card--elevated {
@@ -989,7 +1023,11 @@ hr {
989
1023
  background-color: var(--ds-color-surface);
990
1024
  border: 1px solid var(--ds-color-border);
991
1025
  border-radius: var(--ds-radius-lg);
992
- transition: all var(--ds-duration-fast) var(--ds-ease-default);
1026
+ outline: none;
1027
+ transition:
1028
+ border-color var(--ds-duration-fast) var(--ds-ease-default),
1029
+ box-shadow var(--ds-duration-fast) var(--ds-ease-default),
1030
+ background-color var(--ds-duration-fast) var(--ds-ease-default);
993
1031
  }
994
1032
 
995
1033
  .ds-input,
@@ -997,18 +1035,22 @@ hr {
997
1035
  height: var(--ds-size-3);
998
1036
  }
999
1037
 
1038
+ /* Hover */
1000
1039
  .ds-input:hover,
1001
1040
  .ds-textarea:hover,
1002
1041
  .ds-select:hover {
1003
1042
  border-color: var(--ds-color-border-hover);
1004
1043
  }
1005
1044
 
1006
- .ds-input:focus,
1007
- .ds-textarea:focus,
1008
- .ds-select:focus {
1009
- border-color: var(--ds-color-border-active);
1010
- box-shadow: inset 0 0 0 1px var(--ds-color-border-active);
1011
- outline: none;
1045
+ /* Focus — box-shadow ring instead of outline.
1046
+ Inputs always trigger :focus-visible (browser heuristic for text entry),
1047
+ so outline creates unavoidable double-border with offset.
1048
+ box-shadow follows border-radius perfectly and has no gap. */
1049
+ .ds-input:focus-visible,
1050
+ .ds-textarea:focus-visible,
1051
+ .ds-select:focus-visible {
1052
+ border-color: var(--ds-ring-color);
1053
+ box-shadow: 0 0 0 var(--ds-ring-width) var(--ds-ring-color);
1012
1054
  }
1013
1055
 
1014
1056
  .ds-input::placeholder,
@@ -1016,19 +1058,32 @@ hr {
1016
1058
  color: var(--ds-color-text-tertiary);
1017
1059
  }
1018
1060
 
1019
- /* States */
1061
+ /* States — error: border + ring match the semantic color */
1020
1062
  .ds-input--error,
1021
1063
  .ds-textarea--error {
1022
1064
  border-color: var(--ds-color-error);
1023
1065
  }
1024
- .ds-input--error:focus,
1025
- .ds-textarea--error:focus {
1026
- box-shadow: inset 0 0 0 1px var(--ds-color-error);
1066
+ .ds-input--error:hover,
1067
+ .ds-textarea--error:hover {
1068
+ border-color: var(--ds-color-error);
1069
+ }
1070
+ .ds-input--error:focus-visible,
1071
+ .ds-textarea--error:focus-visible {
1072
+ border-color: var(--ds-color-error);
1073
+ box-shadow: 0 0 0 var(--ds-ring-width) var(--ds-color-error);
1027
1074
  }
1028
1075
 
1076
+ /* States — success: border + ring match the semantic color */
1029
1077
  .ds-input--success {
1030
1078
  border-color: var(--ds-color-success);
1031
1079
  }
1080
+ .ds-input--success:hover {
1081
+ border-color: var(--ds-color-success);
1082
+ }
1083
+ .ds-input--success:focus-visible {
1084
+ border-color: var(--ds-color-success);
1085
+ box-shadow: 0 0 0 var(--ds-ring-width) var(--ds-color-success);
1086
+ }
1032
1087
 
1033
1088
  /* Sizes */
1034
1089
  .ds-input--xs,
@@ -1205,8 +1260,8 @@ hr {
1205
1260
  /* Dot indicator */
1206
1261
  .ds-badge--dot::before {
1207
1262
  content: '';
1208
- width: 6px;
1209
- height: 6px;
1263
+ width: var(--ds-dot-size);
1264
+ height: var(--ds-dot-size);
1210
1265
  border-radius: var(--ds-radius-full);
1211
1266
  background-color: currentColor;
1212
1267
  }
@@ -1236,8 +1291,8 @@ hr {
1236
1291
  height: 4rem;
1237
1292
  background-color: var(--ds-color-nav-bg);
1238
1293
  border-bottom: 1px solid var(--ds-color-nav-border);
1239
- backdrop-filter: blur(20px) saturate(1.5);
1240
- -webkit-backdrop-filter: blur(20px) saturate(1.5);
1294
+ backdrop-filter: blur(var(--ds-blur-lg)) saturate(1.5);
1295
+ -webkit-backdrop-filter: blur(var(--ds-blur-lg)) saturate(1.5);
1241
1296
  }
1242
1297
 
1243
1298
  .ds-nav--static {
@@ -1274,8 +1329,15 @@ hr {
1274
1329
  transition: color var(--ds-duration-normal) var(--ds-ease-default);
1275
1330
  }
1276
1331
 
1277
- .ds-nav__link:hover {
1278
- color: var(--ds-color-text);
1332
+ @media (hover: hover) {
1333
+ .ds-nav__link:hover {
1334
+ color: var(--ds-color-text);
1335
+ }
1336
+ }
1337
+
1338
+ .ds-nav__link:focus-visible {
1339
+ outline: var(--ds-ring-width) solid var(--ds-ring-color);
1340
+ outline-offset: var(--ds-ring-offset);
1279
1341
  }
1280
1342
 
1281
1343
  .ds-nav__link--active {
@@ -1300,9 +1362,16 @@ hr {
1300
1362
  color: var(--ds-color-text-secondary);
1301
1363
  transition: all var(--ds-duration-normal) var(--ds-ease-default);
1302
1364
  }
1303
- .ds-nav__icon-btn:hover {
1304
- color: var(--ds-color-text);
1305
- background-color: var(--ds-color-overlay-hover);
1365
+ @media (hover: hover) {
1366
+ .ds-nav__icon-btn:hover {
1367
+ color: var(--ds-color-text);
1368
+ background-color: var(--ds-color-overlay-hover);
1369
+ }
1370
+ }
1371
+
1372
+ .ds-nav__icon-btn:focus-visible {
1373
+ outline: var(--ds-ring-width) solid var(--ds-ring-color);
1374
+ outline-offset: var(--ds-ring-offset);
1306
1375
  }
1307
1376
 
1308
1377
  /* --- Mobile nav overlay --- */
@@ -1311,7 +1380,7 @@ hr {
1311
1380
  max-height: 0;
1312
1381
  border-bottom: 0 solid var(--ds-color-nav-border);
1313
1382
  background-color: var(--ds-color-nav-bg);
1314
- backdrop-filter: blur(20px);
1383
+ backdrop-filter: blur(var(--ds-blur-lg));
1315
1384
  transition: all var(--ds-duration-slow) var(--ds-ease-out-expo);
1316
1385
  }
1317
1386
 
@@ -1372,9 +1441,16 @@ hr {
1372
1441
  margin-top: var(--ds-space-1);
1373
1442
  }
1374
1443
 
1375
- .ds-sidebar__link:hover {
1376
- color: var(--ds-color-text);
1377
- background-color: var(--ds-color-overlay-hover);
1444
+ @media (hover: hover) {
1445
+ .ds-sidebar__link:hover {
1446
+ color: var(--ds-color-text);
1447
+ background-color: var(--ds-color-overlay-hover);
1448
+ }
1449
+ }
1450
+
1451
+ .ds-sidebar__link:focus-visible {
1452
+ outline: var(--ds-ring-width) solid var(--ds-ring-color);
1453
+ outline-offset: calc(-1 * var(--ds-ring-offset));
1378
1454
  }
1379
1455
 
1380
1456
  .ds-sidebar__link--active {
@@ -1396,8 +1472,8 @@ hr {
1396
1472
  justify-content: center;
1397
1473
  padding: var(--ds-space-4);
1398
1474
  background-color: var(--ds-color-overlay);
1399
- backdrop-filter: blur(4px);
1400
- -webkit-backdrop-filter: blur(4px);
1475
+ backdrop-filter: blur(var(--ds-blur-sm));
1476
+ -webkit-backdrop-filter: blur(var(--ds-blur-sm));
1401
1477
  opacity: 0;
1402
1478
  visibility: hidden;
1403
1479
  transition:
@@ -1466,6 +1542,10 @@ hr {
1466
1542
  .ds-modal__close:hover {
1467
1543
  color: var(--ds-color-text);
1468
1544
  }
1545
+ .ds-modal__close:focus-visible {
1546
+ outline: var(--ds-ring-width) solid var(--ds-ring-color);
1547
+ outline-offset: var(--ds-ring-offset);
1548
+ }
1469
1549
 
1470
1550
  .ds-modal__body {
1471
1551
  padding: var(--ds-space-5);
@@ -1523,10 +1603,10 @@ hr {
1523
1603
  animation: ds-toast-in var(--ds-duration-slow) var(--ds-ease-out-expo) forwards;
1524
1604
  }
1525
1605
 
1526
- .ds-toast--info { border-left: 3px solid var(--ds-color-info); }
1527
- .ds-toast--success { border-left: 3px solid var(--ds-color-success); }
1528
- .ds-toast--warning { border-left: 3px solid var(--ds-color-warning); }
1529
- .ds-toast--error { border-left: 3px solid var(--ds-color-error); }
1606
+ .ds-toast--info { border-left: var(--ds-accent-border-width) solid var(--ds-color-info); }
1607
+ .ds-toast--success { border-left: var(--ds-accent-border-width) solid var(--ds-color-success); }
1608
+ .ds-toast--warning { border-left: var(--ds-accent-border-width) solid var(--ds-color-warning); }
1609
+ .ds-toast--error { border-left: var(--ds-accent-border-width) solid var(--ds-color-error); }
1530
1610
 
1531
1611
  .ds-toast__message {
1532
1612
  flex: 1;
@@ -1543,6 +1623,10 @@ hr {
1543
1623
  .ds-toast__close:hover {
1544
1624
  color: var(--ds-color-text);
1545
1625
  }
1626
+ .ds-toast__close:focus-visible {
1627
+ outline: var(--ds-ring-width) solid var(--ds-ring-color);
1628
+ outline-offset: var(--ds-ring-offset);
1629
+ }
1546
1630
 
1547
1631
  @keyframes ds-toast-in {
1548
1632
  from { opacity: 0; transform: translateY(-8px); }
@@ -1557,6 +1641,11 @@ hr {
1557
1641
  to { opacity: 0; transform: translateX(100%); }
1558
1642
  }
1559
1643
 
1644
+ @media (prefers-reduced-motion: reduce) {
1645
+ .ds-toast { animation: none; }
1646
+ .ds-toast--exit { animation: none; opacity: 0; }
1647
+ }
1648
+
1560
1649
  /* ==========================================================================
1561
1650
  Component: Table
1562
1651
  ========================================================================== */
@@ -1786,7 +1875,7 @@ hr {
1786
1875
  border: 1px solid var(--ds-color-border);
1787
1876
  border-radius: var(--ds-radius-lg);
1788
1877
  background-color: var(--ds-color-surface);
1789
- border-left: 3px solid var(--ds-color-border);
1878
+ border-left: var(--ds-accent-border-width) solid var(--ds-color-border);
1790
1879
  }
1791
1880
 
1792
1881
  /* --- Semantic Variants --- */
@@ -2077,6 +2166,10 @@ hr {
2077
2166
  background-color: var(--ds-color-bg-elevated);
2078
2167
  color: var(--ds-color-text);
2079
2168
  }
2169
+ .ds-dropdown__item:focus-visible {
2170
+ outline: var(--ds-ring-width) solid var(--ds-ring-color);
2171
+ outline-offset: calc(-1 * var(--ds-ring-offset));
2172
+ }
2080
2173
 
2081
2174
  .ds-dropdown__item--active {
2082
2175
  background-color: var(--ds-color-bg-elevated);
@@ -2194,7 +2287,7 @@ hr {
2194
2287
 
2195
2288
  .ds-tooltip .ds-tooltip__content,
2196
2289
  .ds-tooltip--top .ds-tooltip__content {
2197
- bottom: calc(100% + 8px);
2290
+ bottom: calc(100% + var(--ds-offset-md));
2198
2291
  left: 50%;
2199
2292
  transform: translateX(-50%) translateY(4px);
2200
2293
  }
@@ -2218,7 +2311,7 @@ hr {
2218
2311
  ============================================= */
2219
2312
 
2220
2313
  .ds-tooltip--bottom .ds-tooltip__content {
2221
- top: calc(100% + 8px);
2314
+ top: calc(100% + var(--ds-offset-md));
2222
2315
  bottom: auto;
2223
2316
  left: 50%;
2224
2317
  transform: translateX(-50%) translateY(-4px);
@@ -2243,7 +2336,7 @@ hr {
2243
2336
  ============================================= */
2244
2337
 
2245
2338
  .ds-tooltip--left .ds-tooltip__content {
2246
- right: calc(100% + 8px);
2339
+ right: calc(100% + var(--ds-offset-md));
2247
2340
  left: auto;
2248
2341
  bottom: auto;
2249
2342
  top: 50%;
@@ -2270,7 +2363,7 @@ hr {
2270
2363
  ============================================= */
2271
2364
 
2272
2365
  .ds-tooltip--right .ds-tooltip__content {
2273
- left: calc(100% + 8px);
2366
+ left: calc(100% + var(--ds-offset-md));
2274
2367
  right: auto;
2275
2368
  bottom: auto;
2276
2369
  top: 50%;
@@ -2499,6 +2592,10 @@ hr {
2499
2592
  }
2500
2593
  }
2501
2594
 
2595
+ @media (prefers-reduced-motion: reduce) {
2596
+ .ds-skeleton { animation: none; }
2597
+ }
2598
+
2502
2599
  /* ==========================================================================
2503
2600
  Component: Empty State
2504
2601
  Centered message for when there's no data to display.
@@ -2630,11 +2727,16 @@ hr {
2630
2727
  line-height: 1;
2631
2728
  }
2632
2729
 
2730
+ .ds-datepicker__trigger:focus-visible {
2731
+ outline: var(--ds-ring-width) solid var(--ds-ring-color);
2732
+ outline-offset: var(--ds-ring-offset);
2733
+ }
2734
+
2633
2735
  /* Calendar panel */
2634
2736
  .ds-datepicker__panel {
2635
2737
  position: absolute;
2636
2738
  z-index: var(--ds-z-dropdown);
2637
- top: calc(100% + 4px);
2739
+ top: calc(100% + var(--ds-offset-sm));
2638
2740
  left: 0;
2639
2741
  background-color: var(--ds-color-surface);
2640
2742
  border: 1px solid var(--ds-color-border);
@@ -2646,8 +2748,8 @@ hr {
2646
2748
  visibility: hidden;
2647
2749
  transform: scale(0.96);
2648
2750
  transition:
2649
- opacity var(--ds-duration-fast) var(--ds-ease),
2650
- visibility var(--ds-duration-fast) var(--ds-ease),
2751
+ opacity var(--ds-duration-fast) var(--ds-ease-default),
2752
+ visibility var(--ds-duration-fast) var(--ds-ease-default),
2651
2753
  transform var(--ds-duration-fast) var(--ds-ease-out-expo);
2652
2754
  }
2653
2755
 
@@ -2668,7 +2770,7 @@ hr {
2668
2770
 
2669
2771
  .ds-datepicker__title {
2670
2772
  font-size: var(--ds-text-sm);
2671
- font-weight: 600;
2773
+ font-weight: var(--ds-weight-semibold);
2672
2774
  color: var(--ds-color-text);
2673
2775
  user-select: none;
2674
2776
  }
@@ -2685,13 +2787,17 @@ hr {
2685
2787
  color: var(--ds-color-text-secondary);
2686
2788
  cursor: pointer;
2687
2789
  font-size: var(--ds-text-base);
2688
- transition: all var(--ds-duration-fast) var(--ds-ease);
2790
+ transition: all var(--ds-duration-fast) var(--ds-ease-default);
2689
2791
  }
2690
2792
 
2691
2793
  .ds-datepicker__nav:hover {
2692
2794
  background-color: var(--ds-color-bg-elevated);
2693
2795
  color: var(--ds-color-text);
2694
2796
  }
2797
+ .ds-datepicker__nav:focus-visible {
2798
+ outline: var(--ds-ring-width) solid var(--ds-ring-color);
2799
+ outline-offset: calc(-1 * var(--ds-ring-offset));
2800
+ }
2695
2801
 
2696
2802
  /* Weekday header row */
2697
2803
  .ds-datepicker__weekdays {
@@ -2706,7 +2812,7 @@ hr {
2706
2812
  text-align: center;
2707
2813
  padding: var(--ds-space-1) 0;
2708
2814
  user-select: none;
2709
- font-weight: 500;
2815
+ font-weight: var(--ds-weight-medium);
2710
2816
  }
2711
2817
 
2712
2818
  /* Day grid */
@@ -2728,7 +2834,7 @@ hr {
2728
2834
  font-size: var(--ds-text-sm);
2729
2835
  color: var(--ds-color-text);
2730
2836
  cursor: pointer;
2731
- transition: all var(--ds-duration-fast) var(--ds-ease);
2837
+ transition: all var(--ds-duration-fast) var(--ds-ease-default);
2732
2838
  padding: 0;
2733
2839
  line-height: 1;
2734
2840
  user-select: none;
@@ -2737,18 +2843,22 @@ hr {
2737
2843
  .ds-datepicker__day:hover {
2738
2844
  background-color: var(--ds-color-bg-elevated);
2739
2845
  }
2846
+ .ds-datepicker__day:focus-visible {
2847
+ outline: var(--ds-ring-width) solid var(--ds-ring-color);
2848
+ outline-offset: calc(-1 * var(--ds-ring-offset));
2849
+ }
2740
2850
 
2741
2851
  /* Today — subtle ring */
2742
2852
  .ds-datepicker__day--today {
2743
2853
  box-shadow: inset 0 0 0 1px var(--ds-color-border-active);
2744
- font-weight: 600;
2854
+ font-weight: var(--ds-weight-semibold);
2745
2855
  }
2746
2856
 
2747
2857
  /* Selected — inverted fill */
2748
2858
  .ds-datepicker__day--selected {
2749
2859
  background-color: var(--ds-color-text);
2750
2860
  color: var(--ds-color-bg);
2751
- font-weight: 600;
2861
+ font-weight: var(--ds-weight-semibold);
2752
2862
  }
2753
2863
 
2754
2864
  .ds-datepicker__day--selected:hover {
@@ -2773,14 +2883,14 @@ hr {
2773
2883
 
2774
2884
  .ds-datepicker__today {
2775
2885
  font-size: var(--ds-text-xs);
2776
- font-weight: 500;
2886
+ font-weight: var(--ds-weight-medium);
2777
2887
  color: var(--ds-color-text-secondary);
2778
2888
  background: none;
2779
2889
  border: 1px solid var(--ds-color-border);
2780
2890
  border-radius: var(--ds-radius-full);
2781
2891
  padding: var(--ds-space-1) var(--ds-space-3);
2782
2892
  cursor: pointer;
2783
- transition: all var(--ds-duration-fast) var(--ds-ease);
2893
+ transition: all var(--ds-duration-fast) var(--ds-ease-default);
2784
2894
  }
2785
2895
 
2786
2896
  .ds-datepicker__today:hover {
@@ -2788,6 +2898,10 @@ hr {
2788
2898
  color: var(--ds-color-text);
2789
2899
  border-color: var(--ds-color-border-hover);
2790
2900
  }
2901
+ .ds-datepicker__today:focus-visible {
2902
+ outline: var(--ds-ring-width) solid var(--ds-ring-color);
2903
+ outline-offset: var(--ds-ring-offset);
2904
+ }
2791
2905
 
2792
2906
  /* Step arrows — prev/next day buttons beside the date text */
2793
2907
  .ds-datepicker__step {
@@ -2802,7 +2916,7 @@ hr {
2802
2916
  color: var(--ds-color-text-tertiary);
2803
2917
  cursor: pointer;
2804
2918
  font-size: var(--ds-text-xs);
2805
- transition: all var(--ds-duration-fast) var(--ds-ease);
2919
+ transition: all var(--ds-duration-fast) var(--ds-ease-default);
2806
2920
  padding: 0;
2807
2921
  flex-shrink: 0;
2808
2922
  }
@@ -2811,6 +2925,10 @@ hr {
2811
2925
  background-color: var(--ds-color-bg-elevated);
2812
2926
  color: var(--ds-color-text);
2813
2927
  }
2928
+ .ds-datepicker__step:focus-visible {
2929
+ outline: var(--ds-ring-width) solid var(--ds-ring-color);
2930
+ outline-offset: calc(-1 * var(--ds-ring-offset));
2931
+ }
2814
2932
 
2815
2933
  /* Compact mode — for inline table cells */
2816
2934
  .ds-datepicker--compact .ds-datepicker__panel {
@@ -2829,7 +2947,7 @@ hr {
2829
2947
  }
2830
2948
 
2831
2949
  .ds-datepicker--compact .ds-datepicker__weekday {
2832
- font-size: 0.625rem;
2950
+ font-size: var(--ds-text-2xs);
2833
2951
  }
2834
2952
 
2835
2953
  .ds-datepicker--compact .ds-datepicker__day {
@@ -2837,7 +2955,7 @@ hr {
2837
2955
  }
2838
2956
 
2839
2957
  .ds-datepicker--compact .ds-datepicker__today {
2840
- font-size: 0.625rem;
2958
+ font-size: var(--ds-text-2xs);
2841
2959
  padding: 2px var(--ds-space-2);
2842
2960
  }
2843
2961
 
@@ -3492,6 +3610,10 @@ button.ds-tag:focus-visible {
3492
3610
  .ds-accordion__trigger:hover {
3493
3611
  background-color: var(--ds-color-overlay);
3494
3612
  }
3613
+ .ds-accordion__trigger:focus-visible {
3614
+ outline: var(--ds-ring-width) solid var(--ds-ring-color);
3615
+ outline-offset: var(--ds-ring-offset);
3616
+ }
3495
3617
 
3496
3618
  /* Open state – rotate chevron */
3497
3619
  .ds-accordion__item--open .ds-accordion__trigger::after {
@@ -3752,6 +3874,10 @@ button.ds-tag:focus-visible {
3752
3874
  background-color: var(--ds-color-overlay);
3753
3875
  color: var(--ds-color-text);
3754
3876
  }
3877
+ .ds-drawer__close:focus-visible {
3878
+ outline: var(--ds-ring-width) solid var(--ds-ring-color);
3879
+ outline-offset: var(--ds-ring-offset);
3880
+ }
3755
3881
 
3756
3882
  /* ==========================================================================
3757
3883
  * Body
@@ -4036,6 +4162,10 @@ button.ds-tag:focus-visible {
4036
4162
  transition:
4037
4163
  background-color var(--ds-duration-fast) var(--ds-ease-default);
4038
4164
  }
4165
+ .ds-drop-zone:focus-visible {
4166
+ outline: var(--ds-ring-width) solid var(--ds-ring-color);
4167
+ outline-offset: var(--ds-ring-offset);
4168
+ }
4039
4169
 
4040
4170
  :root:not(.dark) .ds-drop-zone {
4041
4171
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='100%25' height='100%25'%3E%3Crect x='1' y='1' width='99%25' height='99%25' rx='16' ry='16' fill='none' stroke='%23d4d4d8' stroke-width='2' stroke-dasharray='10 8'/%3E%3C/svg%3E");
@@ -4167,6 +4297,12 @@ button.ds-tag:focus-visible {
4167
4297
  border-color: var(--ds-color-border-hover);
4168
4298
  }
4169
4299
 
4300
+ .ds-custom-select__trigger:focus-visible {
4301
+ border-color: var(--ds-color-border-active);
4302
+ outline: var(--ds-ring-width) solid var(--ds-ring-color);
4303
+ outline-offset: -1px;
4304
+ }
4305
+
4170
4306
  .ds-custom-select__trigger--open {
4171
4307
  border-color: var(--ds-color-border-active);
4172
4308
  box-shadow: inset 0 0 0 1px var(--ds-color-border-active);
@@ -4330,6 +4466,10 @@ button.ds-tag:focus-visible {
4330
4466
  background-color: var(--ds-color-bg-elevated);
4331
4467
  color: var(--ds-color-text);
4332
4468
  }
4469
+ .ds-custom-select__option:focus-visible {
4470
+ outline: var(--ds-ring-width) solid var(--ds-ring-color);
4471
+ outline-offset: calc(-1 * var(--ds-ring-offset));
4472
+ }
4333
4473
 
4334
4474
  .ds-custom-select__option--selected {
4335
4475
  background-color: var(--ds-color-bg-elevated);
@@ -4439,6 +4579,15 @@ button.ds-tag:focus-visible {
4439
4579
  }
4440
4580
  }
4441
4581
 
4582
+ @media (prefers-reduced-motion: reduce) {
4583
+ .ds-custom-select__panel {
4584
+ animation: none;
4585
+ opacity: 1;
4586
+ transform: scale(1);
4587
+ }
4588
+ .ds-custom-select__backdrop { animation: none; opacity: 1; }
4589
+ }
4590
+
4442
4591
  /* ==========================================================================
4443
4592
  Component: Sortable
4444
4593
  Optional drag-to-reorder styles for table rows or list items.
@@ -4551,7 +4700,7 @@ tr:hover .ds-sortable__handle,
4551
4700
  /* Placement: bottom (default) */
4552
4701
  .ds-popover__content,
4553
4702
  .ds-popover--bottom .ds-popover__content {
4554
- top: calc(100% + 8px);
4703
+ top: calc(100% + var(--ds-offset-md));
4555
4704
  left: 50%;
4556
4705
  transform: translateX(-50%) scale(0.96);
4557
4706
  }
@@ -4563,7 +4712,7 @@ tr:hover .ds-sortable__handle,
4563
4712
 
4564
4713
  /* Placement: top */
4565
4714
  .ds-popover--top .ds-popover__content {
4566
- bottom: calc(100% + 8px);
4715
+ bottom: calc(100% + var(--ds-offset-md));
4567
4716
  top: auto;
4568
4717
  left: 50%;
4569
4718
  transform: translateX(-50%) scale(0.96);
@@ -4575,7 +4724,7 @@ tr:hover .ds-sortable__handle,
4575
4724
 
4576
4725
  /* Placement: left */
4577
4726
  .ds-popover--left .ds-popover__content {
4578
- right: calc(100% + 8px);
4727
+ right: calc(100% + var(--ds-offset-md));
4579
4728
  top: 50%;
4580
4729
  left: auto;
4581
4730
  transform: translateY(-50%) scale(0.96);
@@ -4587,7 +4736,7 @@ tr:hover .ds-sortable__handle,
4587
4736
 
4588
4737
  /* Placement: right */
4589
4738
  .ds-popover--right .ds-popover__content {
4590
- left: calc(100% + 8px);
4739
+ left: calc(100% + var(--ds-offset-md));
4591
4740
  top: 50%;
4592
4741
  transform: translateY(-50%) scale(0.96);
4593
4742
  }
@@ -5065,6 +5214,10 @@ tr:hover .ds-sortable__handle,
5065
5214
  background-color: var(--ds-color-bg-elevated);
5066
5215
  color: var(--ds-color-text);
5067
5216
  }
5217
+ .ds-command__item:focus-visible {
5218
+ outline: var(--ds-ring-width) solid var(--ds-ring-color);
5219
+ outline-offset: calc(-1 * var(--ds-ring-offset));
5220
+ }
5068
5221
 
5069
5222
  /* Item icon */
5070
5223
  .ds-command__item-icon {
@@ -5298,11 +5451,15 @@ tr:hover .ds-sortable__handle,
5298
5451
  .ds-z-60 { z-index: var(--ds-z-sticky); }
5299
5452
 
5300
5453
  /* --- Inset / Position Values --- */
5301
- .ds-inset-0 { inset: 0; }
5302
- .ds-top-0 { top: 0; }
5303
- .ds-right-0 { right: 0; }
5304
- .ds-bottom-0 { bottom: 0; }
5305
- .ds-left-0 { left: 0; }
5454
+ .ds-inset-0 { inset: 0; }
5455
+ .ds-inset-x-0 { left: 0; right: 0; }
5456
+ .ds-inset-y-0 { top: 0; bottom: 0; }
5457
+ .ds-top-0 { top: 0; }
5458
+ .ds-top-full { top: 100%; }
5459
+ .ds-right-0 { right: 0; }
5460
+ .ds-bottom-0 { bottom: 0; }
5461
+ .ds-bottom-full { bottom: 100%; }
5462
+ .ds-left-0 { left: 0; }
5306
5463
  .ds-top-2 { top: var(--ds-space-2); }
5307
5464
  .ds-right-2 { right: var(--ds-space-2); }
5308
5465
  .ds-left-2 { left: var(--ds-space-2); }