@digiko-npm/designsystem 0.4.0 → 0.7.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 (57) hide show
  1. package/README.md +7 -7
  2. package/dist/designsystem.css +2559 -777
  3. package/dist/designsystem.min.css +2 -2
  4. package/package.json +12 -1
  5. package/src/base/typography.css +8 -8
  6. package/src/components/accordion.css +21 -14
  7. package/src/components/alert.css +25 -19
  8. package/src/components/avatar.css +16 -16
  9. package/src/components/bottom-nav.css +125 -0
  10. package/src/components/breadcrumb.css +7 -0
  11. package/src/components/button.css +10 -2
  12. package/src/components/card.css +6 -42
  13. package/src/components/chip.css +79 -0
  14. package/src/components/collapsible.css +116 -0
  15. package/src/components/command.css +17 -7
  16. package/src/components/custom-select.css +123 -7
  17. package/src/components/datepicker.css +9 -9
  18. package/src/components/description-list.css +98 -0
  19. package/src/components/divider.css +1 -1
  20. package/src/components/drawer.css +28 -19
  21. package/src/components/drop-zone.css +10 -3
  22. package/src/components/dropdown.css +17 -8
  23. package/src/components/empty-state.css +3 -3
  24. package/src/components/field.css +77 -0
  25. package/src/components/icon-btn.css +102 -0
  26. package/src/components/index.css +11 -0
  27. package/src/components/input.css +26 -16
  28. package/src/components/kbd.css +1 -1
  29. package/src/components/modal.css +30 -3
  30. package/src/components/nav.css +20 -10
  31. package/src/components/pagination.css +9 -0
  32. package/src/components/popover.css +10 -10
  33. package/src/components/progress.css +2 -2
  34. package/src/components/result.css +84 -0
  35. package/src/components/search.css +294 -0
  36. package/src/components/skeleton.css +4 -4
  37. package/src/components/slider.css +13 -6
  38. package/src/components/sortable.css +9 -0
  39. package/src/components/spinner.css +60 -0
  40. package/src/components/stat-card.css +41 -0
  41. package/src/components/table.css +3 -3
  42. package/src/components/tabs.css +26 -18
  43. package/src/components/tag.css +11 -3
  44. package/src/components/timeline.css +14 -14
  45. package/src/components/toast.css +19 -7
  46. package/src/components/toggle.css +10 -2
  47. package/src/components/toolbar.css +189 -0
  48. package/src/components/tooltip.css +34 -28
  49. package/src/index.css +6 -4
  50. package/src/tokens/colors.css +18 -6
  51. package/src/tokens/spacing.css +7 -0
  52. package/src/utilities/a11y.css +102 -0
  53. package/src/utilities/index.css +2 -0
  54. package/src/utilities/interactive.css +116 -0
  55. package/src/utilities/layout.css +26 -26
  56. package/src/utilities/spacing.css +52 -52
  57. package/src/utilities/text.css +8 -8
@@ -0,0 +1,60 @@
1
+ /* ==========================================================================
2
+ Component: Spinner
3
+ CSS-only loading spinner using border animation.
4
+
5
+ Usage:
6
+ <span class="ds-spinner"></span>
7
+ <span class="ds-spinner ds-spinner--sm"></span>
8
+ <span class="ds-spinner ds-spinner--muted"></span>
9
+
10
+ Sizes:
11
+ .ds-spinner--sm — 1.25rem (20px)
12
+ (default) — 1.5rem (24px)
13
+ .ds-spinner--lg — 2rem (32px)
14
+
15
+ Variants:
16
+ (default) — Border + interactive top
17
+ .ds-spinner--muted — Inverted colors (for dark backgrounds)
18
+ .ds-spinner--light — Light colors (for inverted/colored backgrounds)
19
+ ========================================================================== */
20
+
21
+ .ds-spinner {
22
+ display: inline-block;
23
+ width: 1.5rem;
24
+ height: 1.5rem;
25
+ border: 2px solid var(--ds-color-border);
26
+ border-top-color: var(--ds-color-interactive);
27
+ border-radius: var(--ds-radius-full);
28
+ animation: ds-spin 0.8s linear infinite;
29
+ }
30
+
31
+ @keyframes ds-spin {
32
+ to { transform: rotate(360deg); }
33
+ }
34
+
35
+ /* Sizes */
36
+ .ds-spinner--sm {
37
+ width: 1rem;
38
+ height: 1rem;
39
+ }
40
+
41
+ .ds-spinner--md {
42
+ width: 1.25rem;
43
+ height: 1.25rem;
44
+ }
45
+
46
+ .ds-spinner--lg {
47
+ width: 2rem;
48
+ height: 2rem;
49
+ }
50
+
51
+ /* Color variants */
52
+ .ds-spinner--muted {
53
+ border-color: var(--ds-color-inverted);
54
+ border-top-color: transparent;
55
+ }
56
+
57
+ .ds-spinner--light {
58
+ border-color: var(--ds-color-on-inverted);
59
+ border-top-color: transparent;
60
+ }
@@ -0,0 +1,41 @@
1
+ /* ==========================================================================
2
+ Component: Stat Card
3
+ Compact metric display with label, value, detail, and optional icon.
4
+ ========================================================================== */
5
+
6
+ .ds-stat-card {
7
+ background-color: var(--ds-color-surface);
8
+ border: 1px solid var(--ds-color-border);
9
+ border-radius: var(--ds-radius-xl);
10
+ padding: var(--ds-space-5);
11
+ }
12
+
13
+ .ds-stat-card__label {
14
+ font-size: var(--ds-text-sm);
15
+ color: var(--ds-color-text-tertiary);
16
+ }
17
+
18
+ .ds-stat-card__value {
19
+ font-family: var(--ds-font-display);
20
+ font-weight: var(--ds-font-display-weight);
21
+ font-size: var(--ds-text-2xl);
22
+ color: var(--ds-color-text);
23
+ margin-block-start: var(--ds-space-1);
24
+ }
25
+
26
+ .ds-stat-card__detail {
27
+ font-size: var(--ds-text-xs);
28
+ color: var(--ds-color-text-tertiary);
29
+ margin-block-start: var(--ds-space-0-5);
30
+ }
31
+
32
+ .ds-stat-card__icon {
33
+ width: 2.5rem;
34
+ height: 2.5rem;
35
+ border-radius: var(--ds-radius-xl);
36
+ display: flex;
37
+ align-items: center;
38
+ justify-content: center;
39
+ background-color: var(--ds-color-bg-elevated);
40
+ color: var(--ds-color-text-secondary);
41
+ }
@@ -4,7 +4,7 @@
4
4
 
5
5
  .ds-table {
6
6
  width: 100%;
7
- text-align: left;
7
+ text-align: start;
8
8
  font-size: var(--ds-text-sm);
9
9
  }
10
10
 
@@ -15,13 +15,13 @@
15
15
  color: var(--ds-color-text-tertiary);
16
16
  text-transform: uppercase;
17
17
  letter-spacing: var(--ds-tracking-wide);
18
- border-bottom: 1px solid var(--ds-color-border);
18
+ border-block-end: 1px solid var(--ds-color-border);
19
19
  }
20
20
 
21
21
  .ds-table td {
22
22
  padding: var(--ds-space-3) var(--ds-space-4);
23
23
  color: var(--ds-color-text);
24
- border-bottom: 1px solid var(--ds-color-border-subtle);
24
+ border-block-end: 1px solid var(--ds-color-border-subtle);
25
25
  }
26
26
 
27
27
  .ds-table tbody tr {
@@ -1,20 +1,27 @@
1
1
  /* ==========================================================================
2
2
  Component: Tabs
3
3
  Horizontal/vertical tab navigation with pill, small, and full-width variants.
4
+
5
+ ARIA requirements (consumer responsibility):
6
+ - Tab list: role="tablist", aria-label="[description]"
7
+ - Tab: role="tab", aria-selected="true|false", aria-controls="[panel-id]"
8
+ - Tab panel: role="tabpanel", id matching aria-controls, aria-labelledby="[tab-id]"
9
+ - Keyboard: ArrowLeft/Right (horizontal) or ArrowUp/Down (vertical) to navigate
10
+ - Active tab: only the active tab should be in tab order (tabindex="0"), others tabindex="-1"
4
11
  ========================================================================== */
5
12
 
6
13
  .ds-tabs {
7
14
  display: flex;
8
15
  flex-direction: row;
9
16
  align-items: stretch;
10
- border-bottom: 1px solid var(--ds-color-border);
17
+ border-block-end: 1px solid var(--ds-color-border);
11
18
  gap: var(--ds-space-0);
12
19
  }
13
20
 
14
21
  /* --- Pill variant --- */
15
22
 
16
23
  .ds-tabs--pills {
17
- border-bottom: none;
24
+ border-block-end: none;
18
25
  gap: var(--ds-space-1);
19
26
  background-color: var(--ds-color-bg-elevated);
20
27
  border-radius: var(--ds-radius-lg);
@@ -22,7 +29,7 @@
22
29
  }
23
30
 
24
31
  .ds-tabs--pills .ds-tab {
25
- border-bottom: none;
32
+ border-block-end: none;
26
33
  border-radius: var(--ds-radius-md);
27
34
  padding: var(--ds-space-1-5) var(--ds-space-3);
28
35
  }
@@ -35,28 +42,28 @@
35
42
  background-color: var(--ds-color-surface);
36
43
  color: var(--ds-color-text);
37
44
  box-shadow: var(--ds-shadow-sm);
38
- border-bottom: none;
45
+ border-block-end: none;
39
46
  }
40
47
 
41
48
  /* --- Vertical variant --- */
42
49
 
43
50
  .ds-tabs--vertical {
44
51
  flex-direction: column;
45
- border-bottom: none;
46
- border-right: 1px solid var(--ds-color-border);
52
+ border-block-end: none;
53
+ border-inline-end: 1px solid var(--ds-color-border);
47
54
  gap: var(--ds-space-0-5);
48
55
  }
49
56
 
50
57
  .ds-tabs--vertical .ds-tab {
51
- border-bottom: none;
52
- border-right: 2px solid transparent;
58
+ border-block-end: none;
59
+ border-inline-end: 2px solid transparent;
53
60
  padding: var(--ds-space-2) var(--ds-space-4);
54
- text-align: left;
61
+ text-align: start;
55
62
  }
56
63
 
57
64
  .ds-tabs--vertical .ds-tab--active {
58
- border-bottom: none;
59
- border-right-color: var(--ds-color-interactive);
65
+ border-block-end: none;
66
+ border-inline-end-color: var(--ds-color-interactive);
60
67
  color: var(--ds-color-text);
61
68
  }
62
69
 
@@ -91,14 +98,14 @@
91
98
  line-height: var(--ds-leading-snug);
92
99
  color: var(--ds-color-text-secondary);
93
100
  cursor: pointer;
94
- border-bottom: 2px solid transparent;
101
+ border-block-end: 2px solid transparent;
95
102
  background: none;
96
- border-top: none;
97
- border-left: none;
98
- border-right: none;
103
+ border-block-start: none;
104
+ border-inline-start: none;
105
+ border-inline-end: none;
99
106
  white-space: nowrap;
100
107
  transition: all var(--ds-duration-fast) var(--ds-ease-default);
101
- margin-bottom: -1px;
108
+ margin-block-end: -1px;
102
109
  }
103
110
 
104
111
  .ds-tab:hover {
@@ -109,11 +116,12 @@
109
116
  outline: none;
110
117
  box-shadow: 0 0 0 var(--ds-ring-width) var(--ds-ring-color);
111
118
  border-radius: var(--ds-radius-sm);
119
+ scroll-margin-block: var(--ds-space-16, 4rem);
112
120
  }
113
121
 
114
122
  .ds-tab--active {
115
123
  color: var(--ds-color-text);
116
- border-bottom-color: var(--ds-color-interactive);
124
+ border-block-end-color: var(--ds-color-interactive);
117
125
  }
118
126
 
119
127
  .ds-tab:disabled,
@@ -159,5 +167,5 @@
159
167
  /* --- Tab Panel --- */
160
168
 
161
169
  .ds-tab-panel {
162
- padding-top: var(--ds-space-5);
170
+ padding-block-start: var(--ds-space-5);
163
171
  }
@@ -3,6 +3,11 @@
3
3
  ==========================================================================
4
4
  Interactive, optionally removable tag for categorisation and filtering.
5
5
 
6
+ ARIA requirements (consumer responsibility):
7
+ - Remove button: add aria-label="Remove [tag name]"
8
+ - Selectable tags (as <button>): use aria-pressed="true|false"
9
+ - Tag list: wrap in role="list" with aria-label
10
+
6
11
  Usage:
7
12
  <span class="ds-tag">Default</span>
8
13
  <span class="ds-tag ds-tag--success">Approved</span>
@@ -43,6 +48,7 @@
43
48
  button.ds-tag:focus-visible {
44
49
  outline: none;
45
50
  box-shadow: 0 0 0 var(--ds-ring-width) var(--ds-ring-color);
51
+ scroll-margin-block: var(--ds-space-16, 4rem);
46
52
  }
47
53
 
48
54
  /* ---------------------------------------------------------------------------
@@ -90,7 +96,7 @@ button.ds-tag:focus-visible {
90
96
  --------------------------------------------------------------------------- */
91
97
 
92
98
  .ds-tag--removable {
93
- padding-right: var(--ds-space-1);
99
+ padding-inline-end: var(--ds-space-1);
94
100
  }
95
101
 
96
102
  /* ---------------------------------------------------------------------------
@@ -103,6 +109,8 @@ button.ds-tag:focus-visible {
103
109
  justify-content: center;
104
110
  width: 1rem;
105
111
  height: 1rem;
112
+ min-width: 1.5rem; /* WCAG 2.5.8: minimum 24px target */
113
+ min-height: 1.5rem;
106
114
  padding: 0;
107
115
  border: none;
108
116
  border-radius: var(--ds-radius-full);
@@ -148,7 +156,7 @@ button.ds-tag:focus-visible {
148
156
  }
149
157
 
150
158
  .ds-tag--sm.ds-tag--removable {
151
- padding-right: var(--ds-space-0-5, 0.125rem);
159
+ padding-inline-end: var(--ds-space-0-5, 0.125rem);
152
160
  }
153
161
 
154
162
  /* ---------------------------------------------------------------------------
@@ -161,5 +169,5 @@ button.ds-tag:focus-visible {
161
169
  }
162
170
 
163
171
  .ds-tag--lg.ds-tag--removable {
164
- padding-right: var(--ds-space-1-5, 0.375rem);
172
+ padding-inline-end: var(--ds-space-1-5, 0.375rem);
165
173
  }
@@ -26,16 +26,16 @@
26
26
 
27
27
  .ds-timeline {
28
28
  position: relative;
29
- padding-left: var(--ds-space-8);
29
+ padding-inline-start: var(--ds-space-8);
30
30
  }
31
31
 
32
32
  /* Vertical line */
33
33
  .ds-timeline::before {
34
34
  content: "";
35
35
  position: absolute;
36
- left: 0.9rem;
37
- top: 0;
38
- bottom: 0;
36
+ inset-inline-start: 0.9rem;
37
+ inset-block-start: 0;
38
+ inset-block-end: 0;
39
39
  width: 2px;
40
40
  background-color: var(--ds-color-border);
41
41
  }
@@ -43,17 +43,17 @@
43
43
  /* Item */
44
44
  .ds-timeline__item {
45
45
  position: relative;
46
- padding-bottom: var(--ds-space-6);
46
+ padding-block-end: var(--ds-space-6);
47
47
  }
48
48
 
49
49
  .ds-timeline__item:last-child {
50
- padding-bottom: 0;
50
+ padding-block-end: 0;
51
51
  }
52
52
 
53
53
  /* Dot */
54
54
  .ds-timeline__dot {
55
55
  position: absolute;
56
- left: calc(-1 * var(--ds-space-8) + 0.5rem);
56
+ inset-inline-start: calc(-1 * var(--ds-space-8) + 0.5rem);
57
57
  width: 1rem;
58
58
  height: 1rem;
59
59
  border-radius: var(--ds-radius-full);
@@ -96,35 +96,35 @@
96
96
  .ds-timeline__description {
97
97
  font-size: var(--ds-text-sm);
98
98
  color: var(--ds-color-text-secondary);
99
- margin-top: var(--ds-space-1);
99
+ margin-block-start: var(--ds-space-1);
100
100
  }
101
101
 
102
102
  /* Timestamp */
103
103
  .ds-timeline__time {
104
104
  font-size: var(--ds-text-xs);
105
105
  color: var(--ds-color-text-tertiary);
106
- margin-top: var(--ds-space-0-5);
106
+ margin-block-start: var(--ds-space-0-5);
107
107
  }
108
108
 
109
109
  /* Compact variant */
110
110
  .ds-timeline--compact {
111
- padding-left: var(--ds-space-6);
111
+ padding-inline-start: var(--ds-space-6);
112
112
  }
113
113
 
114
114
  .ds-timeline--compact::before {
115
- left: 0.6rem;
115
+ inset-inline-start: 0.6rem;
116
116
  }
117
117
 
118
118
  .ds-timeline--compact .ds-timeline__item {
119
- padding-bottom: var(--ds-space-4);
119
+ padding-block-end: var(--ds-space-4);
120
120
  }
121
121
 
122
122
  .ds-timeline--compact .ds-timeline__item:last-child {
123
- padding-bottom: 0;
123
+ padding-block-end: 0;
124
124
  }
125
125
 
126
126
  .ds-timeline--compact .ds-timeline__dot {
127
- left: calc(-1 * var(--ds-space-6) + 0.25rem);
127
+ inset-inline-start: calc(-1 * var(--ds-space-6) + 0.25rem);
128
128
  width: 0.75rem;
129
129
  height: 0.75rem;
130
130
  }
@@ -1,5 +1,11 @@
1
1
  /* ==========================================================================
2
2
  Component: Toast
3
+
4
+ ARIA requirements (consumer responsibility):
5
+ - Container: role="status", aria-live="polite" (or role="alert" for errors)
6
+ - Close button: aria-label="Dismiss notification"
7
+ - Auto-dismiss: provide enough time (minimum 5s), or let user control
8
+ - Toast region: wrap container in aria-label="Notifications"
3
9
  ========================================================================== */
4
10
 
5
11
  .ds-toast-container {
@@ -12,10 +18,10 @@
12
18
  pointer-events: none;
13
19
  }
14
20
 
15
- .ds-toast-container--top-right { top: 0; right: 0; }
16
- .ds-toast-container--bottom-right { bottom: 0; right: 0; }
21
+ .ds-toast-container--top-right { inset-block-start: 0; inset-inline-end: 0; }
22
+ .ds-toast-container--bottom-right { inset-block-end: 0; inset-inline-end: 0; }
17
23
  .ds-toast-container--bottom-center {
18
- bottom: 0; left: 50%;
24
+ inset-block-end: 0; inset-inline-start: 50%;
19
25
  transform: translateX(-50%);
20
26
  align-items: center;
21
27
  }
@@ -35,10 +41,10 @@
35
41
  animation: ds-toast-in var(--ds-duration-slow) var(--ds-ease-out-expo) forwards;
36
42
  }
37
43
 
38
- .ds-toast--info { border-left: var(--ds-accent-border-width) solid var(--ds-color-info); }
39
- .ds-toast--success { border-left: var(--ds-accent-border-width) solid var(--ds-color-success); }
40
- .ds-toast--warning { border-left: var(--ds-accent-border-width) solid var(--ds-color-warning); }
41
- .ds-toast--error { border-left: var(--ds-accent-border-width) solid var(--ds-color-error); }
44
+ .ds-toast--info { border-inline-start: var(--ds-accent-border-width) solid var(--ds-color-info); }
45
+ .ds-toast--success { border-inline-start: var(--ds-accent-border-width) solid var(--ds-color-success); }
46
+ .ds-toast--warning { border-inline-start: var(--ds-accent-border-width) solid var(--ds-color-warning); }
47
+ .ds-toast--error { border-inline-start: var(--ds-accent-border-width) solid var(--ds-color-error); }
42
48
 
43
49
  .ds-toast__message {
44
50
  flex: 1;
@@ -55,9 +61,15 @@
55
61
  .ds-toast__close:hover {
56
62
  color: var(--ds-color-text);
57
63
  }
64
+ .ds-toast__close {
65
+ min-width: 1.5rem; /* WCAG 2.5.8: minimum 24px target */
66
+ min-height: 1.5rem;
67
+ }
68
+
58
69
  .ds-toast__close:focus-visible {
59
70
  outline: none;
60
71
  box-shadow: 0 0 0 var(--ds-ring-width) var(--ds-ring-color);
72
+ scroll-margin-block: var(--ds-space-16, 4rem);
61
73
  }
62
74
 
63
75
  @keyframes ds-toast-in {
@@ -4,6 +4,12 @@
4
4
  A toggle (switch) control for binary on/off states.
5
5
  Supports aria-checked attribute and modifier-class driven states.
6
6
 
7
+ ARIA requirements (consumer responsibility):
8
+ - Element: <button role="switch" aria-checked="false|true">
9
+ - Label: pair with visible label via aria-labelledby or wrap in <label>
10
+ - Keyboard: Space toggles state (native <button> handles this)
11
+ - State: update aria-checked on toggle
12
+
7
13
  Usage:
8
14
  <button class="ds-toggle" role="switch" aria-checked="false"></button>
9
15
 
@@ -40,8 +46,8 @@
40
46
  .ds-toggle::after {
41
47
  content: "";
42
48
  position: absolute;
43
- left: 2px;
44
- top: 50%;
49
+ inset-inline-start: 2px;
50
+ inset-block-start: 50%;
45
51
  width: 1.25rem;
46
52
  height: 1.25rem;
47
53
  border-radius: var(--ds-radius-full);
@@ -85,6 +91,7 @@
85
91
  .ds-toggle:focus-visible {
86
92
  outline: none;
87
93
  box-shadow: 0 0 0 var(--ds-ring-width) var(--ds-ring-color);
94
+ scroll-margin-block: var(--ds-space-16, 4rem);
88
95
  }
89
96
 
90
97
  /* ---------------------------------------------------------------------------
@@ -105,6 +112,7 @@
105
112
  .ds-toggle--sm {
106
113
  width: 2rem;
107
114
  height: 1.125rem;
115
+ min-height: 1.5rem; /* WCAG 2.5.8: minimum 24px target */
108
116
  }
109
117
 
110
118
  .ds-toggle--sm::after {
@@ -0,0 +1,189 @@
1
+ /* ==========================================================================
2
+ Component: Toolbar
3
+ Fixed bar with rows of actions: toolbar buttons, filter chips, segmented
4
+ controls, and scrollable groups. Common in data-heavy UIs below a header.
5
+
6
+ Usage:
7
+ <div class="ds-toolbar">
8
+ <div class="ds-toolbar__row">
9
+ <div class="ds-toolbar__group">...</div>
10
+ <div class="ds-toolbar__spacer"></div>
11
+ <div class="ds-toolbar__group">
12
+ <button class="ds-toolbar__btn ds-toolbar__btn--active">
13
+ <span>Filter</span>
14
+ <span class="ds-toolbar__badge">3</span>
15
+ </button>
16
+ <button class="ds-toolbar__btn">Sort</button>
17
+ </div>
18
+ </div>
19
+ </div>
20
+
21
+ Modifiers:
22
+ .ds-toolbar__row--scroll — Horizontally scrollable row
23
+ .ds-toolbar__btn--active — Active/toggled button
24
+ .ds-toolbar__group--scroll — Scrollable group within a row
25
+
26
+ Segmented control:
27
+ <div class="ds-toolbar__segmented">
28
+ <button class="ds-toolbar__segmented-btn ds-toolbar__segmented-btn--active">Past</button>
29
+ <button class="ds-toolbar__segmented-btn">Future</button>
30
+ </div>
31
+ ========================================================================== */
32
+
33
+ /* Row container */
34
+ .ds-toolbar__row {
35
+ display: flex;
36
+ align-items: center;
37
+ height: var(--ds-toolbar-row-height, 2.5rem);
38
+ gap: var(--ds-space-3);
39
+ padding-inline: var(--ds-space-4);
40
+ }
41
+
42
+ .ds-toolbar__row--scroll {
43
+ overflow-x: auto;
44
+ scrollbar-width: none;
45
+ }
46
+
47
+ .ds-toolbar__row--scroll::-webkit-scrollbar { display: none; }
48
+
49
+ /* Group (flex row of items) */
50
+ .ds-toolbar__group {
51
+ display: flex;
52
+ align-items: center;
53
+ flex-shrink: 0;
54
+ }
55
+
56
+ .ds-toolbar__group--scroll {
57
+ flex-shrink: 1;
58
+ min-width: 0;
59
+ overflow-x: auto;
60
+ scrollbar-width: none;
61
+ }
62
+
63
+ .ds-toolbar__group--scroll::-webkit-scrollbar { display: none; }
64
+
65
+ /* Spacer */
66
+ .ds-toolbar__spacer {
67
+ flex: 1 1 0;
68
+ }
69
+
70
+ /* Toolbar button */
71
+ .ds-toolbar__btn {
72
+ display: inline-flex;
73
+ align-items: center;
74
+ gap: var(--ds-space-1-5);
75
+ padding: var(--ds-space-1) var(--ds-space-2-5);
76
+ font-size: var(--ds-text-xs);
77
+ font-weight: var(--ds-weight-medium);
78
+ font-family: inherit;
79
+ color: var(--ds-color-text-tertiary);
80
+ background: transparent;
81
+ border: 1px solid transparent;
82
+ border-radius: var(--ds-radius-md);
83
+ cursor: pointer;
84
+ white-space: nowrap;
85
+ transition:
86
+ color var(--ds-duration-fast) var(--ds-ease-default),
87
+ background-color var(--ds-duration-fast) var(--ds-ease-default),
88
+ border-color var(--ds-duration-fast) var(--ds-ease-default);
89
+ }
90
+
91
+ .ds-toolbar__btn:hover {
92
+ color: var(--ds-color-text-secondary);
93
+ background: var(--ds-color-surface-hover);
94
+ }
95
+
96
+ .ds-toolbar__btn:focus-visible {
97
+ outline: none;
98
+ box-shadow: 0 0 0 var(--ds-ring-width) var(--ds-ring-color);
99
+ }
100
+
101
+ .ds-toolbar__btn--active {
102
+ color: var(--ds-color-text);
103
+ background: var(--ds-color-surface);
104
+ border-color: var(--ds-color-border);
105
+ }
106
+
107
+ /* Badge (count indicator inside button) */
108
+ .ds-toolbar__badge {
109
+ display: inline-flex;
110
+ align-items: center;
111
+ justify-content: center;
112
+ min-width: 1rem;
113
+ height: 1rem;
114
+ padding: 0 0.25rem;
115
+ font-size: 0.625rem;
116
+ font-weight: 600;
117
+ line-height: 1;
118
+ color: var(--ds-color-on-inverted);
119
+ background: var(--ds-color-interactive);
120
+ border-radius: var(--ds-radius-full);
121
+ }
122
+
123
+ /* Eye toggle (visibility) */
124
+ .ds-toolbar__eye {
125
+ display: inline-flex;
126
+ align-items: center;
127
+ cursor: pointer;
128
+ opacity: 0.7;
129
+ transition: opacity var(--ds-duration-fast) var(--ds-ease-default);
130
+ }
131
+
132
+ .ds-toolbar__eye:hover {
133
+ opacity: 1;
134
+ }
135
+
136
+ /* Segmented control */
137
+ .ds-toolbar__segmented {
138
+ flex-shrink: 0;
139
+ display: flex;
140
+ background: var(--ds-color-surface);
141
+ border-radius: var(--ds-radius-md);
142
+ padding: 2px;
143
+ }
144
+
145
+ .ds-toolbar__segmented-btn {
146
+ padding: var(--ds-space-1) var(--ds-space-3);
147
+ font-size: var(--ds-text-xs);
148
+ font-weight: var(--ds-weight-medium);
149
+ color: var(--ds-color-text-tertiary);
150
+ border: none;
151
+ border-radius: var(--ds-radius-sm);
152
+ background: transparent;
153
+ cursor: pointer;
154
+ transition:
155
+ color var(--ds-duration-fast) var(--ds-ease-default),
156
+ background-color var(--ds-duration-fast) var(--ds-ease-default);
157
+ }
158
+
159
+ .ds-toolbar__segmented-btn:hover {
160
+ color: var(--ds-color-text-secondary);
161
+ }
162
+
163
+ .ds-toolbar__segmented-btn--active {
164
+ background: var(--ds-color-bg-elevated);
165
+ color: var(--ds-color-text);
166
+ }
167
+
168
+ /* Responsive: mobile */
169
+ @media (max-width: 1023px) /* below --ds-breakpoint-lg */ {
170
+ .ds-toolbar__row {
171
+ padding-inline: var(--ds-space-3);
172
+ gap: var(--ds-space-2);
173
+ }
174
+
175
+ .ds-toolbar__btn-label { display: none; }
176
+
177
+ .ds-toolbar__btn {
178
+ padding: var(--ds-space-2);
179
+ min-width: var(--ds-size-2);
180
+ min-height: var(--ds-size-2);
181
+ justify-content: center;
182
+ }
183
+
184
+ .ds-toolbar__badge {
185
+ font-size: 0.5rem;
186
+ min-width: 0.875rem;
187
+ height: 0.875rem;
188
+ }
189
+ }