@adamarant/designsystem 0.11.2

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 (84) hide show
  1. package/README.md +101 -0
  2. package/dist/designsystem.css +13494 -0
  3. package/dist/designsystem.js +67 -0
  4. package/dist/designsystem.min.css +2 -0
  5. package/package.json +111 -0
  6. package/src/base/index.css +2 -0
  7. package/src/base/reset.css +119 -0
  8. package/src/base/typography.css +172 -0
  9. package/src/components/accordion.css +166 -0
  10. package/src/components/admin-layout.css +371 -0
  11. package/src/components/alert.css +159 -0
  12. package/src/components/avatar.css +109 -0
  13. package/src/components/badge.css +80 -0
  14. package/src/components/bottom-nav.css +125 -0
  15. package/src/components/bottom-sheet.css +146 -0
  16. package/src/components/breadcrumb.css +102 -0
  17. package/src/components/button.css +250 -0
  18. package/src/components/card.css +117 -0
  19. package/src/components/chip.css +79 -0
  20. package/src/components/collapsible.css +112 -0
  21. package/src/components/color-picker.css +82 -0
  22. package/src/components/combobox.css +420 -0
  23. package/src/components/command.css +210 -0
  24. package/src/components/context-menu.css +162 -0
  25. package/src/components/copy-button.css +106 -0
  26. package/src/components/custom-select.css +446 -0
  27. package/src/components/datepicker.css +301 -0
  28. package/src/components/description-list.css +100 -0
  29. package/src/components/divider.css +66 -0
  30. package/src/components/drawer.css +234 -0
  31. package/src/components/drop-zone.css +166 -0
  32. package/src/components/dropdown.css +169 -0
  33. package/src/components/empty-state.css +75 -0
  34. package/src/components/field.css +112 -0
  35. package/src/components/gallery.css +257 -0
  36. package/src/components/hero.css +111 -0
  37. package/src/components/icon-btn.css +103 -0
  38. package/src/components/index.css +74 -0
  39. package/src/components/input.css +311 -0
  40. package/src/components/kbd.css +54 -0
  41. package/src/components/media-library.css +230 -0
  42. package/src/components/modal.css +136 -0
  43. package/src/components/nav.css +198 -0
  44. package/src/components/number-input.css +163 -0
  45. package/src/components/pagination.css +175 -0
  46. package/src/components/pin-input.css +136 -0
  47. package/src/components/popover.css +111 -0
  48. package/src/components/progress.css +217 -0
  49. package/src/components/prose.css +337 -0
  50. package/src/components/result.css +80 -0
  51. package/src/components/scroll-area.css +73 -0
  52. package/src/components/search.css +311 -0
  53. package/src/components/segmented-control.css +94 -0
  54. package/src/components/skeleton.css +100 -0
  55. package/src/components/slider.css +133 -0
  56. package/src/components/sortable.css +70 -0
  57. package/src/components/spinner.css +60 -0
  58. package/src/components/star-rating.css +121 -0
  59. package/src/components/stat-card.css +44 -0
  60. package/src/components/table.css +359 -0
  61. package/src/components/tabs.css +215 -0
  62. package/src/components/tag.css +188 -0
  63. package/src/components/timeline.css +130 -0
  64. package/src/components/toast.css +90 -0
  65. package/src/components/toggle.css +173 -0
  66. package/src/components/toolbar.css +206 -0
  67. package/src/components/tooltip.css +167 -0
  68. package/src/components/truncated-text.css +75 -0
  69. package/src/index.css +21 -0
  70. package/src/js/theme.js +67 -0
  71. package/src/tokens/colors.css +256 -0
  72. package/src/tokens/index.css +11 -0
  73. package/src/tokens/shadows.css +55 -0
  74. package/src/tokens/spacing.css +82 -0
  75. package/src/tokens/tokens.json +413 -0
  76. package/src/tokens/typography.css +90 -0
  77. package/src/utilities/a11y.css +102 -0
  78. package/src/utilities/index.css +7 -0
  79. package/src/utilities/interactive.css +121 -0
  80. package/src/utilities/layout.css +273 -0
  81. package/src/utilities/sizing.css +85 -0
  82. package/src/utilities/spacing.css +204 -0
  83. package/src/utilities/states.css +182 -0
  84. package/src/utilities/text.css +381 -0
@@ -0,0 +1,311 @@
1
+ /* ==========================================================================
2
+ Component: Form Inputs
3
+ Surface bg, clean borders, focus ring.
4
+
5
+ ARIA requirements (consumer responsibility):
6
+ - Input: associate with <label for="id"> or aria-label
7
+ - Error state: add aria-invalid="true" + aria-describedby pointing to error msg
8
+ - Required: add aria-required="true" or HTML required attribute
9
+ - Input group: icon is decorative (pointer-events: none), no ARIA needed
10
+ - Checkbox/radio: use native <input type="checkbox|radio"> inside <label>
11
+ ========================================================================== */
12
+
13
+ .ds-label {
14
+ display: block;
15
+ font-size: var(--ds-text-sm);
16
+ font-weight: var(--ds-weight-medium);
17
+ color: var(--ds-color-text-secondary);
18
+ margin-block-end: var(--ds-space-1-5);
19
+ }
20
+
21
+ .ds-input,
22
+ .ds-textarea {
23
+ width: 100%;
24
+ }
25
+
26
+ .ds-input,
27
+ .ds-textarea,
28
+ .ds-select {
29
+ padding: 0 var(--ds-space-4);
30
+ font-family: var(--ds-font-sans);
31
+ font-size: var(--ds-text-base); /* 16px — prevents iOS auto-zoom on focus */
32
+ line-height: var(--ds-leading-normal);
33
+ color: var(--ds-color-text);
34
+ background-color: var(--ds-color-surface);
35
+ border: 1px solid var(--ds-color-border);
36
+ border-radius: var(--ds-radius-lg);
37
+ outline: none;
38
+ transition:
39
+ border-color var(--ds-duration-fast) var(--ds-ease-default),
40
+ box-shadow var(--ds-duration-fast) var(--ds-ease-default),
41
+ background-color var(--ds-duration-fast) var(--ds-ease-default);
42
+ }
43
+
44
+ .ds-input,
45
+ .ds-select {
46
+ height: var(--ds-size-3);
47
+ }
48
+
49
+ .ds-input {
50
+ /* Hover */
51
+ &:hover {
52
+ border-color: var(--ds-color-border-hover);
53
+ }
54
+
55
+ /* Focus — box-shadow ring instead of outline.
56
+ Inputs always trigger :focus-visible (browser heuristic for text entry),
57
+ so outline creates unavoidable double-border with offset.
58
+ box-shadow follows border-radius perfectly and has no gap. */
59
+ &:focus-visible {
60
+ border-color: var(--ds-ring-color);
61
+ box-shadow: 0 0 0 var(--ds-ring-width) var(--ds-ring-color);
62
+ scroll-margin-block: var(--ds-space-16, 4rem);
63
+ }
64
+
65
+ &::placeholder {
66
+ color: var(--ds-color-text-tertiary);
67
+ }
68
+
69
+ /* States — error: border + ring match the semantic color */
70
+ &--error {
71
+ border-color: var(--ds-color-error);
72
+
73
+ &:hover {
74
+ border-color: var(--ds-color-error);
75
+ }
76
+
77
+ &:focus-visible {
78
+ border-color: var(--ds-color-error);
79
+ box-shadow: 0 0 0 var(--ds-ring-width) var(--ds-color-error);
80
+ }
81
+ }
82
+
83
+ /* States — success: border + ring match the semantic color */
84
+ &--success {
85
+ border-color: var(--ds-color-success);
86
+
87
+ &:hover {
88
+ border-color: var(--ds-color-success);
89
+ }
90
+
91
+ &:focus-visible {
92
+ border-color: var(--ds-color-success);
93
+ box-shadow: 0 0 0 var(--ds-ring-width) var(--ds-color-success);
94
+ }
95
+ }
96
+
97
+ /* Sizes */
98
+ &--xs {
99
+ height: var(--ds-size-1);
100
+ padding: 0 var(--ds-space-1-5);
101
+ font-size: var(--ds-text-xs);
102
+ border-radius: var(--ds-radius-sm);
103
+ }
104
+
105
+ &--sm {
106
+ height: var(--ds-size-2);
107
+ padding: 0 var(--ds-space-2);
108
+ font-size: var(--ds-text-sm);
109
+ border-radius: var(--ds-radius-md);
110
+ }
111
+
112
+ &--lg {
113
+ height: var(--ds-size-4);
114
+ padding: 0 var(--ds-space-4);
115
+ font-size: var(--ds-text-base);
116
+ }
117
+
118
+ /* --- Layout Modifiers ---
119
+ Override default width/display/chrome assumptions. */
120
+
121
+ /* Flush — naked input inside a styled container.
122
+ No border, no background, no padding, no focus ring.
123
+ The container handles visual chrome. */
124
+ &--flush {
125
+ background: transparent;
126
+ border: none;
127
+ padding: 0;
128
+ border-radius: 0;
129
+ box-shadow: none;
130
+ height: auto;
131
+
132
+ &:hover {
133
+ border-color: transparent;
134
+ }
135
+
136
+ &:focus-visible {
137
+ border-color: transparent;
138
+ box-shadow: none;
139
+ }
140
+ }
141
+
142
+ /* Inline — auto-width for use in flex rows */
143
+ &--inline {
144
+ width: auto;
145
+ display: inline-flex;
146
+ }
147
+ }
148
+
149
+ .ds-textarea {
150
+ &:hover {
151
+ border-color: var(--ds-color-border-hover);
152
+ }
153
+
154
+ &:focus-visible {
155
+ border-color: var(--ds-ring-color);
156
+ box-shadow: 0 0 0 var(--ds-ring-width) var(--ds-ring-color);
157
+ scroll-margin-block: var(--ds-space-16, 4rem);
158
+ }
159
+
160
+ &::placeholder {
161
+ color: var(--ds-color-text-tertiary);
162
+ }
163
+
164
+ /* States — error */
165
+ &--error {
166
+ border-color: var(--ds-color-error);
167
+
168
+ &:hover {
169
+ border-color: var(--ds-color-error);
170
+ }
171
+
172
+ &:focus-visible {
173
+ border-color: var(--ds-color-error);
174
+ box-shadow: 0 0 0 var(--ds-ring-width) var(--ds-color-error);
175
+ }
176
+ }
177
+
178
+ /* Textarea */
179
+ min-height: 6rem;
180
+ padding: var(--ds-space-2-5) var(--ds-space-4);
181
+ height: auto;
182
+ resize: vertical;
183
+ }
184
+
185
+ .ds-select {
186
+ &:hover {
187
+ border-color: var(--ds-color-border-hover);
188
+ }
189
+
190
+ &:focus-visible {
191
+ border-color: var(--ds-ring-color);
192
+ box-shadow: 0 0 0 var(--ds-ring-width) var(--ds-ring-color);
193
+ scroll-margin-block: var(--ds-space-16, 4rem);
194
+ }
195
+
196
+ /* Select */
197
+ appearance: none;
198
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%23a1a1aa' d='M2 4l4 4 4-4'/%3E%3C/svg%3E");
199
+ background-repeat: no-repeat;
200
+ background-position: right var(--ds-space-3) center;
201
+ padding-inline-end: var(--ds-space-8);
202
+
203
+ /* Sizes */
204
+ &--xs {
205
+ height: var(--ds-size-1);
206
+ padding: 0 var(--ds-space-1-5);
207
+ font-size: var(--ds-text-xs);
208
+ border-radius: var(--ds-radius-sm);
209
+ }
210
+
211
+ &--sm {
212
+ height: var(--ds-size-2);
213
+ padding: 0 var(--ds-space-2);
214
+ font-size: var(--ds-text-sm);
215
+ border-radius: var(--ds-radius-md);
216
+ }
217
+
218
+ &--lg {
219
+ height: var(--ds-size-4);
220
+ padding: 0 var(--ds-space-4);
221
+ font-size: var(--ds-text-base);
222
+ padding-inline-end: var(--ds-space-8);
223
+ }
224
+
225
+ /* Full width (opt-in for select, already default for input/textarea) */
226
+ &--full {
227
+ width: 100%;
228
+ }
229
+ }
230
+
231
+ /* --- Input Group ---
232
+ Wrapper for input with leading icon.
233
+ Icon sits inside the input via absolute positioning. */
234
+ .ds-input-group {
235
+ position: relative;
236
+
237
+ &__icon {
238
+ position: absolute;
239
+ inset-inline-start: var(--ds-space-3);
240
+ inset-block-start: 50%;
241
+ transform: translateY(-50%);
242
+ display: flex;
243
+ align-items: center;
244
+ justify-content: center;
245
+ color: var(--ds-color-text-tertiary);
246
+ pointer-events: none;
247
+ }
248
+
249
+ & .ds-input {
250
+ padding-inline-start: calc(var(--ds-space-3) + 1rem + var(--ds-space-2));
251
+ }
252
+
253
+ /* --- Input Group: icon-right ---
254
+ Move icon to the right side, flip input padding. */
255
+ &--icon-right {
256
+ & .ds-input-group__icon {
257
+ inset-inline-start: auto;
258
+ inset-inline-end: var(--ds-space-3);
259
+ }
260
+
261
+ & .ds-input {
262
+ padding-inline-start: var(--ds-space-4);
263
+ padding-inline-end: calc(var(--ds-space-3) + 1rem + var(--ds-space-2));
264
+ }
265
+ }
266
+ }
267
+
268
+ /* Help text */
269
+ .ds-help {
270
+ font-size: var(--ds-text-xs);
271
+ color: var(--ds-color-text-tertiary);
272
+ margin-block-start: var(--ds-space-1-5);
273
+
274
+ &--error { color: var(--ds-color-error); }
275
+ }
276
+
277
+ /* Form Group (legacy — prefer ds-form) */
278
+ .ds-form-group { margin-block-end: var(--ds-space-4); }
279
+
280
+ /* --- Form Stack ---
281
+ Vertical form layout: comfortable spacing between fields (24px),
282
+ extra breathing room before the action area (32px).
283
+ Use ds-form__actions on the button/submit wrapper. */
284
+ .ds-form {
285
+ & > * + * {
286
+ margin-block-start: var(--ds-space-6);
287
+ }
288
+
289
+ &__actions {
290
+ margin-block-start: var(--ds-space-8);
291
+ }
292
+ }
293
+
294
+ /* Checkbox / Radio */
295
+ .ds-checkbox,
296
+ .ds-radio {
297
+ display: inline-flex;
298
+ align-items: center;
299
+ gap: var(--ds-space-2);
300
+ cursor: pointer;
301
+ font-size: var(--ds-text-sm);
302
+ color: var(--ds-color-text-secondary);
303
+
304
+ & input {
305
+ accent-color: var(--ds-color-interactive);
306
+ width: 1rem;
307
+ height: 1rem;
308
+ min-width: 1.5rem; /* WCAG 2.5.8: minimum 24px target */
309
+ min-height: 1.5rem;
310
+ }
311
+ }
@@ -0,0 +1,54 @@
1
+ /* ==========================================================================
2
+ Kbd
3
+ ==========================================================================
4
+ Keyboard shortcut display component with a raised 3D key appearance.
5
+ Use individually or group multiple keys with ds-kbd-group for combos
6
+ like "Cmd + K".
7
+
8
+ Usage:
9
+ <kbd class="ds-kbd">Esc</kbd>
10
+
11
+ <span class="ds-kbd-group">
12
+ <kbd class="ds-kbd">Cmd</kbd>
13
+ <span class="ds-kbd-group__separator">+</span>
14
+ <kbd class="ds-kbd">K</kbd>
15
+ </span>
16
+
17
+ Modifiers:
18
+ .ds-kbd--lg — Larger key display
19
+ ========================================================================== */
20
+
21
+ .ds-kbd {
22
+ display: inline-flex;
23
+ align-items: center;
24
+ gap: var(--ds-space-1);
25
+ padding: var(--ds-space-0-5) var(--ds-space-1-5);
26
+ font-family: var(--ds-font-mono);
27
+ font-size: var(--ds-text-xs);
28
+ background-color: var(--ds-color-surface-muted);
29
+ border: 1px solid var(--ds-color-border);
30
+ border-block-end-width: 2px;
31
+ border-radius: var(--ds-radius-sm);
32
+ color: var(--ds-color-text-secondary);
33
+ line-height: 1;
34
+ vertical-align: baseline;
35
+
36
+ /* Large variant */
37
+ &--lg {
38
+ font-size: var(--ds-text-sm);
39
+ padding: var(--ds-space-1) var(--ds-space-2);
40
+ }
41
+ }
42
+
43
+ /* Key group (for combos like Cmd + K) */
44
+ .ds-kbd-group {
45
+ display: inline-flex;
46
+ align-items: center;
47
+ gap: var(--ds-space-1);
48
+
49
+ /* Separator between keys */
50
+ &__separator {
51
+ font-size: var(--ds-text-xs);
52
+ color: var(--ds-color-text-tertiary);
53
+ }
54
+ }
@@ -0,0 +1,230 @@
1
+ /* ==========================================================================
2
+ Component: Media Library
3
+ Composable classes for media management UI: grid items, selection toolbar,
4
+ detail panel, and folder sidebar. Used by CMS MediaLibrary component.
5
+
6
+ Classes:
7
+ ds-media-item Grid thumbnail card (border, transition)
8
+ ds-media-item--selected Selected state (interactive ring)
9
+ ds-media-item__thumb Thumbnail area (surface-muted background)
10
+ ds-media-item__check Selection check indicator (absolute, top-right)
11
+ ds-media-item__info File name + size footer
12
+ ds-media-toolbar Sticky selection toolbar bar
13
+ ds-media-toolbar__count Selected items counter text
14
+ ds-media-toolbar__spacer Flex spacer between left/right actions
15
+ ds-media-detail-slot Reserved sidebar slot (fixed width, sticky) — render always to keep grid stable
16
+ ds-media-detail Detail/edit sidebar card (surface card with padding) — render inside slot when selected
17
+ ds-media-detail__preview Preview container (surface-muted, aspect-video)
18
+ ds-media-detail__action Sidebar action button (Copy / Open / Delete)
19
+ ds-media-detail__action--danger Destructive variant (Delete)
20
+ ds-media-folder Folder sidebar container (responsive, hidden < md)
21
+ ds-media-folder__item Folder list button
22
+ ds-media-folder__item--active Active folder state
23
+ ds-media-folder__actions Rename/delete buttons (visible on interaction)
24
+
25
+ ARIA:
26
+ - Grid items: <button type="button"> with aria-selected for state
27
+ - Toolbar: role="toolbar" with aria-label
28
+ - Bulk delete: aria-live="polite" for confirmation state change
29
+ - Folder sidebar: <nav> with aria-label
30
+ ========================================================================== */
31
+
32
+
33
+ /* ─── Media Item ─────────────────────────────────────────────────────────── */
34
+
35
+ .ds-media-item {
36
+ position: relative;
37
+ cursor: pointer;
38
+ overflow: hidden;
39
+ border-radius: var(--ds-radius-lg);
40
+ border: 1px solid var(--ds-color-border);
41
+ background-color: var(--ds-color-surface);
42
+ transition:
43
+ border-color var(--ds-duration-fast) var(--ds-ease-default),
44
+ box-shadow var(--ds-duration-fast) var(--ds-ease-default);
45
+ }
46
+
47
+ .ds-media-item:hover {
48
+ border-color: var(--ds-color-border-hover);
49
+ }
50
+
51
+ .ds-media-item--selected {
52
+ border-color: var(--ds-color-interactive);
53
+ box-shadow: 0 0 0 1px var(--ds-color-interactive);
54
+ }
55
+
56
+ .ds-media-item__thumb {
57
+ background-color: var(--ds-color-surface-muted);
58
+ }
59
+
60
+ .ds-media-item__check {
61
+ position: absolute;
62
+ inset-block-start: var(--ds-space-1-5);
63
+ inset-inline-end: var(--ds-space-1-5);
64
+ display: flex;
65
+ align-items: center;
66
+ justify-content: center;
67
+ width: 1.375rem;
68
+ height: 1.375rem;
69
+ border-radius: var(--ds-radius-full);
70
+ background-color: var(--ds-color-interactive);
71
+ color: var(--ds-color-static-white);
72
+ pointer-events: none;
73
+ }
74
+
75
+ .ds-media-item__info {
76
+ padding: var(--ds-space-2);
77
+ }
78
+
79
+
80
+ /* ─── Media Toolbar ──────────────────────────────────────────────────────── */
81
+
82
+ .ds-media-toolbar {
83
+ position: sticky;
84
+ inset-block-start: 0;
85
+ z-index: var(--ds-z-sticky);
86
+ display: flex;
87
+ align-items: center;
88
+ gap: var(--ds-space-3);
89
+ padding: var(--ds-space-3) var(--ds-space-4);
90
+ margin-block-end: var(--ds-space-3);
91
+ background-color: var(--ds-color-surface);
92
+ border: 1px solid var(--ds-color-border);
93
+ border-radius: var(--ds-radius-md);
94
+ box-shadow: var(--ds-shadow-sm);
95
+ }
96
+
97
+ .ds-media-toolbar__count {
98
+ font-size: var(--ds-text-sm);
99
+ font-weight: var(--ds-weight-medium);
100
+ color: var(--ds-color-text);
101
+ }
102
+
103
+ .ds-media-toolbar__spacer {
104
+ flex: 1;
105
+ }
106
+
107
+
108
+ /* ─── Media Detail ───────────────────────────────────────────────────────── */
109
+
110
+ .ds-media-detail-slot {
111
+ width: 17.5rem;
112
+ flex-shrink: 0;
113
+ position: sticky;
114
+ inset-block-start: var(--ds-space-4);
115
+ align-self: flex-start;
116
+ }
117
+
118
+ .ds-media-detail {
119
+ width: 100%;
120
+ display: flex;
121
+ flex-direction: column;
122
+ gap: var(--ds-space-4);
123
+ padding: var(--ds-space-4);
124
+ border-radius: var(--ds-radius-xl);
125
+ border: 1px solid var(--ds-color-border);
126
+ background-color: var(--ds-color-surface);
127
+ }
128
+
129
+ .ds-media-detail__preview {
130
+ background-color: var(--ds-color-surface-muted);
131
+ }
132
+
133
+ .ds-media-detail__action {
134
+ display: flex;
135
+ align-items: center;
136
+ gap: var(--ds-space-2);
137
+ width: 100%;
138
+ padding: var(--ds-space-2) var(--ds-space-3);
139
+ border-radius: var(--ds-radius-md);
140
+ font-size: var(--ds-text-sm);
141
+ color: var(--ds-color-text-secondary);
142
+ background: transparent;
143
+ border: none;
144
+ cursor: pointer;
145
+ text-align: start;
146
+ transition:
147
+ background-color var(--ds-duration-fast) var(--ds-ease-default),
148
+ color var(--ds-duration-fast) var(--ds-ease-default);
149
+ }
150
+
151
+ .ds-media-detail__action:hover {
152
+ background-color: var(--ds-color-surface-hover);
153
+ color: var(--ds-color-text);
154
+ }
155
+
156
+ .ds-media-detail__action--danger:hover,
157
+ .ds-media-detail__action--danger:focus-visible {
158
+ color: var(--ds-color-error);
159
+ }
160
+
161
+
162
+ /* ─── Media Folder Sidebar ───────────────────────────────────────────────── */
163
+
164
+ .ds-media-folder {
165
+ display: none;
166
+ width: 12rem;
167
+ flex-shrink: 0;
168
+ flex-direction: column;
169
+ border-radius: var(--ds-radius-xl);
170
+ border: 1px solid var(--ds-color-border);
171
+ background-color: var(--ds-color-surface);
172
+ padding: var(--ds-space-3);
173
+ }
174
+
175
+ @media (min-width: 768px) {
176
+ .ds-media-folder {
177
+ display: flex;
178
+ }
179
+ }
180
+
181
+
182
+ /* ─── Folder item — base + transient interaction ─────────────────────────── */
183
+
184
+ .ds-media-folder__item {
185
+ display: flex;
186
+ align-items: center;
187
+ gap: var(--ds-space-2);
188
+ width: 100%;
189
+ padding: var(--ds-space-1-5) var(--ds-space-2);
190
+ border-radius: var(--ds-radius-md);
191
+ font-size: var(--ds-text-sm);
192
+ color: var(--ds-color-text-secondary);
193
+ background: transparent;
194
+ border: none;
195
+ cursor: pointer;
196
+ transition:
197
+ background-color var(--ds-duration-fast) var(--ds-ease-default),
198
+ color var(--ds-duration-fast) var(--ds-ease-default);
199
+ }
200
+
201
+ .ds-media-folder__item:hover {
202
+ background-color: var(--ds-color-surface-hover);
203
+ color: var(--ds-color-text);
204
+ }
205
+
206
+ .ds-media-folder__item:hover .ds-media-folder__actions {
207
+ display: flex;
208
+ }
209
+
210
+
211
+ /* ═══════════════════════════════════════════════════════════════════════════
212
+ Folder item — persistent selection state
213
+ Separated to avoid semantic token hook window overlap.
214
+ ═══════════════════════════════════════════════════════════════════════════ */
215
+
216
+ .ds-media-folder__item--active {
217
+ background-color: var(--ds-color-surface-active);
218
+ color: var(--ds-color-text);
219
+ font-weight: var(--ds-weight-medium);
220
+ }
221
+
222
+
223
+ /* ─── Folder actions (visible on parent interaction) ─────────────────────── */
224
+
225
+ .ds-media-folder__actions {
226
+ display: none;
227
+ align-items: center;
228
+ gap: var(--ds-space-0-5);
229
+ margin-inline-start: auto;
230
+ }