sid-ui 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (116) hide show
  1. package/README.md +54 -2
  2. package/package.json +51 -4
  3. package/src/brand/BrandFooter.tsx +45 -0
  4. package/src/brand/BrandHeading.tsx +24 -0
  5. package/src/brand/BrandLockup.tsx +47 -0
  6. package/src/brand/JoinedLogo.tsx +67 -0
  7. package/src/brand/JoinedMark.tsx +76 -0
  8. package/src/brand/geometry.ts +26 -0
  9. package/src/brand/index.ts +11 -0
  10. package/src/brand/name.ts +5 -0
  11. package/src/brand/paint.tsx +56 -0
  12. package/src/components/Action.tsx +44 -0
  13. package/src/components/AddressSelector.tsx +99 -0
  14. package/src/components/BarChart.tsx +132 -0
  15. package/src/components/Calendar.tsx +284 -0
  16. package/src/components/CalendarAgenda.tsx +87 -0
  17. package/src/components/CalendarMonth.tsx +223 -0
  18. package/src/components/CalendarSchedule.tsx +210 -0
  19. package/src/components/Card.tsx +80 -0
  20. package/src/components/Charts.tsx +64 -0
  21. package/src/components/Chat.tsx +35 -0
  22. package/src/components/CitySelector.tsx +81 -0
  23. package/src/components/Clock.tsx +196 -0
  24. package/src/components/CodeInput.tsx +183 -0
  25. package/src/components/Container.tsx +20 -0
  26. package/src/components/Content.tsx +50 -0
  27. package/src/components/Data.tsx +43 -0
  28. package/src/components/DataInput.tsx +107 -0
  29. package/src/components/DateField.tsx +162 -0
  30. package/src/components/DonutChart.tsx +123 -0
  31. package/src/components/Drawer.tsx +110 -0
  32. package/src/components/Feedback.tsx +37 -0
  33. package/src/components/FileUploader.tsx +377 -0
  34. package/src/components/FunnelChart.tsx +83 -0
  35. package/src/components/Glyph.tsx +330 -0
  36. package/src/components/GoogleSignIn.tsx +67 -0
  37. package/src/components/GridSystem.tsx +131 -0
  38. package/src/components/HeatmapCalendar.tsx +167 -0
  39. package/src/components/KanbanBoard.tsx +421 -0
  40. package/src/components/Kpi.tsx +61 -0
  41. package/src/components/LayoutPrimitives.tsx +86 -0
  42. package/src/components/Lists.tsx +19 -0
  43. package/src/components/LocationSelector.tsx +49 -0
  44. package/src/components/MessageList.tsx +80 -0
  45. package/src/components/Nav.tsx +69 -0
  46. package/src/components/Navigation.tsx +52 -0
  47. package/src/components/Notification.tsx +115 -0
  48. package/src/components/NotificationTrigger.tsx +248 -0
  49. package/src/components/Overlay.tsx +50 -0
  50. package/src/components/Page.tsx +143 -0
  51. package/src/components/PageTabs.tsx +28 -0
  52. package/src/components/PickerShell.tsx +138 -0
  53. package/src/components/PillNav.tsx +194 -0
  54. package/src/components/Primitives.tsx +30 -0
  55. package/src/components/Rating.tsx +78 -0
  56. package/src/components/Responsive.tsx +128 -0
  57. package/src/components/ResponsiveFrame.tsx +122 -0
  58. package/src/components/Segment.tsx +190 -0
  59. package/src/components/Sparkline.tsx +52 -0
  60. package/src/components/StateSelector.tsx +39 -0
  61. package/src/components/Sticky.tsx +95 -0
  62. package/src/components/Table.tsx +344 -0
  63. package/src/components/ThemeToggle.tsx +48 -0
  64. package/src/components/Tile.tsx +23 -0
  65. package/src/components/TimeColumns.tsx +155 -0
  66. package/src/components/TimeDial.tsx +260 -0
  67. package/src/components/TimeField.tsx +196 -0
  68. package/src/components/TimeInput.tsx +213 -0
  69. package/src/components/TimeSlots.tsx +83 -0
  70. package/src/components/Timeline.tsx +111 -0
  71. package/src/components/TokenDemo.tsx +378 -0
  72. package/src/components/Tree.tsx +283 -0
  73. package/src/components/TrendChart.tsx +211 -0
  74. package/src/components/breakpoints.ts +42 -0
  75. package/src/components/calendarTypes.ts +26 -0
  76. package/src/components/chartMath.ts +125 -0
  77. package/src/components/chartParts.tsx +116 -0
  78. package/src/components/codeInputRules.ts +58 -0
  79. package/src/components/date.ts +87 -0
  80. package/src/components/hooks.ts +53 -0
  81. package/src/components/index.ts +195 -0
  82. package/src/components/kanban.ts +78 -0
  83. package/src/components/motion.ts +78 -0
  84. package/src/components/places-search.tsx +73 -0
  85. package/src/components/places.ts +209 -0
  86. package/src/components/size.ts +3 -0
  87. package/src/components/time.ts +83 -0
  88. package/src/components/useFileDrop.ts +104 -0
  89. package/src/places/geoapify.ts +129 -0
  90. package/src/styles/astryx.css +5 -0
  91. package/src/styles/components/brand.css +98 -0
  92. package/src/styles/components/calendar.css +680 -0
  93. package/src/styles/components/charts.css +659 -0
  94. package/src/styles/components/code-input.css +233 -0
  95. package/src/styles/components/google.css +11 -0
  96. package/src/styles/components/message-list.css +153 -0
  97. package/src/styles/components/notification.css +350 -0
  98. package/src/styles/components/picker.css +114 -0
  99. package/src/styles/components/pill-nav.css +179 -0
  100. package/src/styles/components/responsive.css +419 -0
  101. package/src/styles/components/sticky.css +23 -0
  102. package/src/styles/components/table.css +267 -0
  103. package/src/styles/components/time.css +526 -0
  104. package/src/styles/components/timeline.css +426 -0
  105. package/src/styles/components/tree.css +269 -0
  106. package/src/styles/components.css +423 -0
  107. package/src/styles/joined.css +4 -0
  108. package/src/styles/theme.css +79 -0
  109. package/src/styles/tokens.css +338 -0
  110. package/src/theme/JoinedProvider.tsx +50 -0
  111. package/src/theme/index.ts +3 -0
  112. package/src/theme/joined.d.ts +11 -0
  113. package/src/theme/joined.js +569 -0
  114. package/src/theme/joined.theme.ts +74 -0
  115. package/src/theme/joined.variants.d.ts +16 -0
  116. package/src/theme/theme.css +786 -0
@@ -0,0 +1,426 @@
1
+ /* Timeline — each item is [track | body]. The track holds the marker and the
2
+ rail segment that runs down to the next marker, so custom marker sizes and
3
+ done/current/upcoming states line up without absolute positioning. */
4
+
5
+ .os-tl {
6
+ --os-tl-marker: 10px;
7
+ --os-tl-track: 24px;
8
+ --os-tl-line: 2px;
9
+ --os-tl-title-line: 20px;
10
+ --os-tl-body-pad: 0px;
11
+ --os-tl-breath: var(--spacing-1);
12
+ --os-tl-space: var(--spacing-6);
13
+ list-style: none;
14
+ margin: 0;
15
+ padding: 0;
16
+ width: 100%;
17
+ max-width: 560px;
18
+ display: flex;
19
+ flex-direction: column;
20
+ color: var(--color-text-primary);
21
+ }
22
+
23
+ .os-tl-item {
24
+ --os-tl-offset: calc(
25
+ var(--os-tl-body-pad) + var(--os-tl-title-line) / 2 - var(--os-tl-marker) / 2
26
+ );
27
+ display: grid;
28
+ grid-template-columns: var(--os-tl-track) minmax(0, 1fr);
29
+ column-gap: var(--spacing-3);
30
+ }
31
+ .os-tl-item:is(.os-tl-item-done, .os-tl-item-current, .os-tl-item-upcoming) {
32
+ --os-tl-marker: 18px;
33
+ }
34
+ .os-tl-item:has(.os-tl-marker-custom) {
35
+ --os-tl-marker: 24px;
36
+ }
37
+
38
+ .os-tl-track {
39
+ display: flex;
40
+ flex-direction: column;
41
+ align-items: center;
42
+ }
43
+ .os-tl-item:not(:last-child) .os-tl-track::after {
44
+ content: "";
45
+ flex: 1;
46
+ width: var(--os-tl-line);
47
+ min-height: var(--spacing-3);
48
+ margin-top: var(--os-tl-breath);
49
+ margin-bottom: calc(var(--os-tl-breath) - var(--os-tl-offset));
50
+ border-radius: var(--radius-full);
51
+ background: var(--color-border);
52
+ }
53
+ .os-tl-item-done:not(:last-child) .os-tl-track::after {
54
+ background: var(--color-accent);
55
+ }
56
+ .os-tl-item-current:not(:last-child) .os-tl-track::after {
57
+ background: linear-gradient(to bottom, var(--color-accent), var(--color-border));
58
+ }
59
+ .os-tl-item-upcoming:not(:last-child) .os-tl-track::after {
60
+ background: repeating-linear-gradient(
61
+ to bottom,
62
+ var(--color-border-emphasized) 0 3px,
63
+ transparent 3px 7px
64
+ );
65
+ }
66
+
67
+ /* Markers */
68
+ .os-tl-tone-accent {
69
+ --os-tl-tone: var(--color-accent);
70
+ --os-tl-soft: var(--color-accent-muted);
71
+ --os-tl-ink: var(--color-text-accent);
72
+ }
73
+ .os-tl-tone-success {
74
+ --os-tl-tone: var(--color-success);
75
+ --os-tl-soft: var(--color-success-muted);
76
+ --os-tl-ink: var(--color-success);
77
+ }
78
+ .os-tl-tone-warning {
79
+ --os-tl-tone: var(--color-warning);
80
+ --os-tl-soft: var(--color-warning-muted);
81
+ --os-tl-ink: var(--color-warning);
82
+ }
83
+ .os-tl-tone-danger {
84
+ --os-tl-tone: var(--color-error);
85
+ --os-tl-soft: var(--color-error-muted);
86
+ --os-tl-ink: var(--color-error);
87
+ }
88
+ .os-tl-tone-neutral {
89
+ --os-tl-tone: var(--color-icon-secondary);
90
+ --os-tl-soft: var(--color-neutral);
91
+ --os-tl-ink: var(--color-text-secondary);
92
+ }
93
+
94
+ .os-tl-marker {
95
+ position: relative;
96
+ box-sizing: border-box;
97
+ flex: none;
98
+ display: grid;
99
+ place-items: center;
100
+ width: var(--os-tl-marker);
101
+ height: var(--os-tl-marker);
102
+ margin-top: var(--os-tl-offset);
103
+ border-radius: var(--radius-full);
104
+ color: var(--color-on-accent);
105
+ font-size: var(--font-size-xs, 0.625rem);
106
+ font-weight: var(--font-weight-semibold, 600);
107
+ }
108
+ .os-tl-marker .os-glyph {
109
+ width: 70%;
110
+ height: 70%;
111
+ stroke-width: 2.5;
112
+ }
113
+ .os-tl-plain {
114
+ background: var(--os-tl-tone);
115
+ box-shadow: 0 0 0 3px var(--os-tl-soft);
116
+ }
117
+ .os-tl-done {
118
+ background: var(--os-tl-tone);
119
+ }
120
+ .os-tl-current {
121
+ background: var(--color-background-surface);
122
+ box-shadow: inset 0 0 0 2px var(--os-tl-tone);
123
+ animation: os-tl-pulse 2.4s var(--ease-standard) infinite;
124
+ }
125
+ .os-tl-current:not(.os-tl-marker-custom)::after {
126
+ content: "";
127
+ width: 6px;
128
+ height: 6px;
129
+ border-radius: var(--radius-full);
130
+ background: var(--os-tl-tone);
131
+ }
132
+ .os-tl-upcoming {
133
+ background: var(--color-background-surface);
134
+ box-shadow: inset 0 0 0 1.5px var(--color-border-emphasized);
135
+ }
136
+ .os-tl-marker-custom {
137
+ background: var(--os-tl-soft);
138
+ color: var(--os-tl-ink);
139
+ box-shadow: none;
140
+ font-size: var(--font-size-sm);
141
+ }
142
+ .os-tl-marker-custom.os-tl-current {
143
+ box-shadow: inset 0 0 0 2px var(--os-tl-tone);
144
+ }
145
+ @keyframes os-tl-pulse {
146
+ 0% {
147
+ box-shadow:
148
+ inset 0 0 0 2px var(--os-tl-tone),
149
+ 0 0 0 0 var(--os-tl-soft);
150
+ }
151
+ 70% {
152
+ box-shadow:
153
+ inset 0 0 0 2px var(--os-tl-tone),
154
+ 0 0 0 7px transparent;
155
+ }
156
+ 100% {
157
+ box-shadow:
158
+ inset 0 0 0 2px var(--os-tl-tone),
159
+ 0 0 0 0 transparent;
160
+ }
161
+ }
162
+
163
+ /* Body */
164
+ .os-tl-body {
165
+ min-width: 0;
166
+ padding-top: var(--os-tl-body-pad);
167
+ padding-bottom: var(--os-tl-space);
168
+ }
169
+ .os-tl-item:last-child .os-tl-body {
170
+ padding-bottom: 0;
171
+ }
172
+ .os-tl-head {
173
+ display: flex;
174
+ align-items: baseline;
175
+ justify-content: space-between;
176
+ gap: var(--spacing-3);
177
+ }
178
+ .os-tl-title {
179
+ margin: 0;
180
+ font-size: var(--font-size-base);
181
+ line-height: var(--os-tl-title-line);
182
+ font-weight: var(--font-weight-medium, 500);
183
+ color: var(--color-text-primary);
184
+ }
185
+ .os-tl-item-upcoming .os-tl-title {
186
+ color: var(--color-text-secondary);
187
+ }
188
+ .os-tl-time {
189
+ flex: none;
190
+ font-size: var(--font-size-sm);
191
+ color: var(--color-text-secondary);
192
+ font-variant-numeric: tabular-nums;
193
+ white-space: nowrap;
194
+ }
195
+ .os-tl-desc {
196
+ margin: var(--spacing-0-5, 2px) 0 0;
197
+ font-size: var(--font-size-sm);
198
+ line-height: 1.5;
199
+ color: var(--color-text-secondary);
200
+ }
201
+ .os-tl-meta {
202
+ margin-top: var(--spacing-2);
203
+ }
204
+
205
+ /* Group headings — "Today", "Yesterday" */
206
+ .os-tl-heading {
207
+ display: flex;
208
+ align-items: center;
209
+ gap: var(--spacing-3);
210
+ padding-bottom: var(--spacing-3);
211
+ font-size: var(--font-size-sm);
212
+ font-weight: var(--font-weight-semibold, 600);
213
+ color: var(--color-text-secondary);
214
+ }
215
+ .os-tl-heading:not(:first-child) {
216
+ padding-top: var(--spacing-2);
217
+ }
218
+ .os-tl-heading::after {
219
+ content: "";
220
+ flex: 1;
221
+ height: 1px;
222
+ background: var(--color-border);
223
+ }
224
+
225
+ /* compact — a log with the time in its own column */
226
+ .os-tl-compact {
227
+ --os-tl-space: var(--spacing-3);
228
+ --os-tl-line: 1px;
229
+ --os-tl-track: 12px;
230
+ --os-tl-breath: 3px;
231
+ }
232
+ .os-tl-compact .os-tl-item,
233
+ .os-tl-compact .os-tl-item:is(.os-tl-item-done, .os-tl-item-current, .os-tl-item-upcoming) {
234
+ --os-tl-marker: 8px;
235
+ grid-template-columns: 4.5rem var(--os-tl-track) minmax(0, 1fr);
236
+ }
237
+ .os-tl-compact .os-tl-time-lead {
238
+ grid-column: 1;
239
+ text-align: right;
240
+ line-height: var(--os-tl-title-line);
241
+ }
242
+ .os-tl-compact .os-tl-track {
243
+ grid-column: 2;
244
+ }
245
+ .os-tl-compact .os-tl-body {
246
+ grid-column: 3;
247
+ display: flex;
248
+ flex-wrap: wrap;
249
+ align-items: baseline;
250
+ column-gap: var(--spacing-2);
251
+ }
252
+ .os-tl-compact .os-tl-title {
253
+ font-weight: var(--font-weight-normal, 400);
254
+ }
255
+ .os-tl-compact .os-tl-desc {
256
+ margin: 0;
257
+ line-height: var(--os-tl-title-line);
258
+ }
259
+ .os-tl-compact .os-tl-marker .os-glyph,
260
+ .os-tl-compact .os-tl-current::after {
261
+ display: none;
262
+ }
263
+ .os-tl-compact .os-tl-plain {
264
+ box-shadow: none;
265
+ }
266
+
267
+ /* cards — each event on a surface */
268
+ .os-tl-cards {
269
+ --os-tl-body-pad: var(--spacing-3);
270
+ --os-tl-space: var(--spacing-3);
271
+ }
272
+ .os-tl-cards .os-tl-body,
273
+ .os-tl-alternate .os-tl-body {
274
+ padding: var(--spacing-3) var(--spacing-4);
275
+ margin-bottom: var(--os-tl-space);
276
+ background: var(--color-background-surface);
277
+ border-radius: var(--radius-element);
278
+ box-shadow:
279
+ 0 0 0 1px var(--color-border),
280
+ var(--shadow-low, var(--elevation-1));
281
+ transition:
282
+ box-shadow var(--duration-fast) var(--ease-standard),
283
+ transform var(--duration-fast) var(--ease-standard);
284
+ }
285
+ .os-tl-cards .os-tl-item:last-child .os-tl-body,
286
+ .os-tl-alternate .os-tl-item:last-child .os-tl-body {
287
+ margin-bottom: 0;
288
+ padding-bottom: var(--spacing-3);
289
+ }
290
+ .os-tl-cards .os-tl-item-current .os-tl-body {
291
+ box-shadow:
292
+ 0 0 0 1.5px var(--color-accent),
293
+ var(--shadow-low, var(--elevation-1));
294
+ }
295
+ .os-tl-cards .os-tl-item-upcoming .os-tl-body {
296
+ background: transparent;
297
+ box-shadow: inset 0 0 0 1px var(--color-border);
298
+ }
299
+
300
+ /* alternate — events swap sides of a centred rail */
301
+ .os-tl-alternate {
302
+ --os-tl-body-pad: var(--spacing-3);
303
+ --os-tl-space: var(--spacing-4);
304
+ container-type: inline-size;
305
+ max-width: 720px;
306
+ }
307
+ .os-tl-alternate .os-tl-item {
308
+ grid-template-columns: minmax(0, 1fr) var(--os-tl-track) minmax(0, 1fr);
309
+ }
310
+ .os-tl-alternate .os-tl-track {
311
+ grid-column: 2;
312
+ grid-row: 1;
313
+ }
314
+ .os-tl-alternate .os-tl-item:nth-child(odd of .os-tl-item) .os-tl-body {
315
+ grid-column: 1;
316
+ grid-row: 1;
317
+ text-align: right;
318
+ }
319
+ .os-tl-alternate .os-tl-item:nth-child(odd of .os-tl-item) .os-tl-head {
320
+ flex-direction: row-reverse;
321
+ }
322
+ .os-tl-alternate .os-tl-item:nth-child(even of .os-tl-item) .os-tl-body {
323
+ grid-column: 3;
324
+ grid-row: 1;
325
+ }
326
+ .os-tl-alternate .os-tl-heading {
327
+ justify-content: center;
328
+ }
329
+ .os-tl-alternate .os-tl-heading::before {
330
+ content: "";
331
+ flex: 1;
332
+ height: 1px;
333
+ background: var(--color-border);
334
+ }
335
+ @container (max-width: 480px) {
336
+ .os-tl-alternate .os-tl-item {
337
+ grid-template-columns: var(--os-tl-track) minmax(0, 1fr);
338
+ }
339
+ .os-tl-alternate .os-tl-track {
340
+ grid-column: 1;
341
+ }
342
+ .os-tl-alternate
343
+ .os-tl-item:is(:nth-child(odd of .os-tl-item), :nth-child(even of .os-tl-item))
344
+ .os-tl-body {
345
+ grid-column: 2;
346
+ text-align: left;
347
+ }
348
+ .os-tl-alternate .os-tl-item:nth-child(odd of .os-tl-item) .os-tl-head {
349
+ flex-direction: row;
350
+ }
351
+ }
352
+
353
+ /* horizontal — milestones left to right */
354
+ .os-tl-horizontal {
355
+ flex-direction: row;
356
+ max-width: none;
357
+ overflow-x: auto;
358
+ scroll-snap-type: x proximity;
359
+ padding-bottom: var(--spacing-1);
360
+ }
361
+ .os-tl-horizontal .os-tl-item {
362
+ --os-tl-offset: 0px;
363
+ flex: 1 0 150px;
364
+ grid-template-columns: minmax(0, 1fr);
365
+ grid-template-rows: auto auto;
366
+ row-gap: var(--spacing-3);
367
+ scroll-snap-align: start;
368
+ }
369
+ .os-tl-horizontal .os-tl-track {
370
+ flex-direction: row;
371
+ align-items: center;
372
+ height: 24px;
373
+ }
374
+ .os-tl-horizontal .os-tl-item:not(:last-child) .os-tl-track::after {
375
+ width: auto;
376
+ height: var(--os-tl-line);
377
+ min-height: 0;
378
+ margin: 0 var(--os-tl-breath);
379
+ }
380
+ .os-tl-horizontal .os-tl-item-upcoming:not(:last-child) .os-tl-track::after {
381
+ background: repeating-linear-gradient(
382
+ to right,
383
+ var(--color-border-emphasized) 0 3px,
384
+ transparent 3px 7px
385
+ );
386
+ }
387
+ .os-tl-horizontal .os-tl-item-current:not(:last-child) .os-tl-track::after {
388
+ background: linear-gradient(to right, var(--color-accent), var(--color-border));
389
+ }
390
+ .os-tl-horizontal .os-tl-body {
391
+ padding: 0 var(--spacing-4) 0 0;
392
+ }
393
+ .os-tl-horizontal .os-tl-head {
394
+ flex-direction: column-reverse;
395
+ align-items: flex-start;
396
+ gap: 0;
397
+ }
398
+
399
+ /* activity — feed with people and icons */
400
+ .os-tl-activity {
401
+ --os-tl-track: 32px;
402
+ --os-tl-space: var(--spacing-5);
403
+ }
404
+ .os-tl-activity .os-tl-item:has(.os-tl-marker-custom) {
405
+ --os-tl-marker: 32px;
406
+ --os-tl-offset: 0px;
407
+ }
408
+ .os-tl-activity .os-tl-item:has(.os-tl-marker-custom) .os-tl-body {
409
+ padding-top: calc((32px - var(--os-tl-title-line)) / 2);
410
+ }
411
+ .os-tl-activity .os-tl-marker-custom {
412
+ font-size: var(--font-size-sm);
413
+ }
414
+ .os-tl-activity .os-tl-meta {
415
+ padding: var(--spacing-2) var(--spacing-3);
416
+ border-radius: var(--radius-element);
417
+ background: var(--color-background-muted);
418
+ font-size: var(--font-size-sm);
419
+ color: var(--color-text-secondary);
420
+ }
421
+
422
+ @media (prefers-reduced-motion: reduce) {
423
+ .os-tl-current {
424
+ animation: none;
425
+ }
426
+ }
@@ -0,0 +1,269 @@
1
+ /* Tree — rows share one grid: indent columns, chevron, optional check and icon, text, meta. */
2
+
3
+ .os-tree {
4
+ --os-tree-row: 32px;
5
+ --os-tree-step: 20px;
6
+ --os-tree-guide: var(--color-border-emphasized);
7
+ list-style: none;
8
+ margin: 0;
9
+ padding: 0;
10
+ width: 100%;
11
+ max-width: 360px;
12
+ min-width: 240px;
13
+ font-size: var(--font-size-base);
14
+ color: var(--color-text-primary);
15
+ }
16
+ .os-tree-compact {
17
+ --os-tree-row: 26px;
18
+ --os-tree-step: 18px;
19
+ }
20
+ .os-tree-spacious {
21
+ --os-tree-row: 44px;
22
+ --os-tree-step: 24px;
23
+ }
24
+
25
+ .os-tree-group {
26
+ list-style: none;
27
+ margin: 0;
28
+ padding: 0;
29
+ animation: os-tree-open var(--duration-fast) var(--ease-standard);
30
+ }
31
+ @keyframes os-tree-open {
32
+ from {
33
+ opacity: 0;
34
+ transform: translateY(-2px);
35
+ }
36
+ }
37
+
38
+ .os-tree-item {
39
+ outline: none;
40
+ }
41
+ .os-tree-row {
42
+ position: relative;
43
+ display: flex;
44
+ align-items: center;
45
+ min-height: var(--os-tree-row);
46
+ padding: 0 var(--spacing-2) 0 var(--spacing-1);
47
+ border-radius: var(--radius-inner);
48
+ cursor: pointer;
49
+ user-select: none;
50
+ transition: background-color var(--duration-fast) var(--ease-standard);
51
+ }
52
+ .os-tree-row:hover {
53
+ background: var(--color-overlay-hover);
54
+ }
55
+ .os-tree-item:focus-visible > .os-tree-row {
56
+ box-shadow: inset 0 0 0 2px var(--color-accent);
57
+ }
58
+ .os-tree-row-selected {
59
+ background: var(--color-neutral);
60
+ }
61
+ .os-tree-row-disabled {
62
+ opacity: 0.45;
63
+ cursor: default;
64
+ }
65
+ .os-tree-row-disabled:hover {
66
+ background: transparent;
67
+ }
68
+
69
+ /* One column per ancestor. Guides sit where the parent's chevron was. */
70
+ .os-tree-indent {
71
+ position: relative;
72
+ flex: none;
73
+ align-self: stretch;
74
+ width: var(--os-tree-step);
75
+ }
76
+ .os-tree-indent::before {
77
+ content: "";
78
+ position: absolute;
79
+ top: 0;
80
+ bottom: 0;
81
+ left: calc(var(--os-tree-step) / 2);
82
+ width: 1px;
83
+ background: var(--os-tree-guide);
84
+ opacity: 0;
85
+ transition: opacity var(--duration-fast) var(--ease-standard);
86
+ }
87
+ .os-tree-guides .os-tree-indent::before,
88
+ .os-tree-checkbox .os-tree-indent::before,
89
+ .os-tree-explorer:hover .os-tree-indent::before,
90
+ .os-tree-explorer:focus-within .os-tree-indent::before {
91
+ opacity: 1;
92
+ }
93
+ .os-tree-explorer {
94
+ --os-tree-guide: var(--color-border);
95
+ }
96
+
97
+ .os-tree-chevron {
98
+ flex: none;
99
+ display: grid;
100
+ place-items: center;
101
+ width: var(--os-tree-step);
102
+ height: var(--os-tree-step);
103
+ border-radius: calc(var(--radius-inner) - 2px);
104
+ color: var(--color-icon-secondary);
105
+ transition:
106
+ background-color var(--duration-fast) var(--ease-standard),
107
+ color var(--duration-fast) var(--ease-standard);
108
+ }
109
+ .os-tree-chevron .os-glyph {
110
+ width: 14px;
111
+ height: 14px;
112
+ transition: transform var(--duration-fast) var(--ease-standard);
113
+ }
114
+ .os-tree-item[aria-expanded="true"] > .os-tree-row .os-tree-chevron .os-glyph {
115
+ transform: rotate(90deg);
116
+ }
117
+ .os-tree-chevron:not(.os-tree-chevron-empty):hover {
118
+ background: var(--color-overlay-pressed);
119
+ color: var(--color-text-primary);
120
+ }
121
+
122
+ .os-tree-lead {
123
+ flex: none;
124
+ display: inline-flex;
125
+ align-items: center;
126
+ margin-left: var(--spacing-1);
127
+ color: var(--color-icon-secondary);
128
+ }
129
+ .os-tree-icon .os-glyph {
130
+ width: 16px;
131
+ height: 16px;
132
+ }
133
+ .os-tree-item[aria-expanded] > .os-tree-row .os-tree-icon {
134
+ color: var(--color-icon-accent);
135
+ }
136
+
137
+ .os-tree-text {
138
+ flex: 1;
139
+ min-width: 0;
140
+ display: flex;
141
+ flex-direction: column;
142
+ margin-left: var(--spacing-2);
143
+ padding: var(--spacing-1) 0;
144
+ }
145
+ .os-tree-label {
146
+ line-height: 20px;
147
+ white-space: nowrap;
148
+ overflow: hidden;
149
+ text-overflow: ellipsis;
150
+ }
151
+ .os-tree-root > .os-tree-row .os-tree-label {
152
+ font-weight: var(--font-weight-medium, 500);
153
+ }
154
+ .os-tree-desc {
155
+ font-size: var(--font-size-sm);
156
+ line-height: 16px;
157
+ color: var(--color-text-secondary);
158
+ white-space: nowrap;
159
+ overflow: hidden;
160
+ text-overflow: ellipsis;
161
+ }
162
+ .os-tree-compact .os-tree-text {
163
+ flex-direction: row;
164
+ align-items: baseline;
165
+ gap: var(--spacing-2);
166
+ padding: 0;
167
+ }
168
+ .os-tree-meta {
169
+ flex: none;
170
+ margin-left: var(--spacing-2);
171
+ font-size: var(--font-size-sm);
172
+ color: var(--color-text-secondary);
173
+ font-variant-numeric: tabular-nums;
174
+ }
175
+ .os-tree-mark {
176
+ background: var(--color-warning-muted);
177
+ color: inherit;
178
+ border-radius: 3px;
179
+ padding: 0 1px;
180
+ }
181
+
182
+ /* Leading avatar used by demos and apps */
183
+ .os-tree-leading {
184
+ display: inline-grid;
185
+ place-items: center;
186
+ width: 22px;
187
+ height: 22px;
188
+ border-radius: var(--radius-full);
189
+ background: var(--color-accent-muted);
190
+ color: var(--color-text-accent);
191
+ font-size: var(--font-size-xs, 0.625rem);
192
+ font-weight: var(--font-weight-semibold, 600);
193
+ }
194
+
195
+ /* selection — one chosen row with an accent bar */
196
+ .os-tree-selection .os-tree-row-selected,
197
+ .os-tree-selection .os-tree-row-selected:hover {
198
+ background: var(--color-accent-muted);
199
+ color: var(--color-text-accent);
200
+ }
201
+ .os-tree-selection .os-tree-row-selected::before {
202
+ content: "";
203
+ position: absolute;
204
+ left: 0;
205
+ top: 25%;
206
+ bottom: 25%;
207
+ width: 3px;
208
+ border-radius: var(--radius-full);
209
+ background: var(--color-accent);
210
+ }
211
+ .os-tree-selection .os-tree-row-selected :is(.os-tree-desc, .os-tree-meta, .os-tree-chevron) {
212
+ color: var(--color-text-accent);
213
+ }
214
+
215
+ /* checkbox — tri-state */
216
+ .os-tree-check {
217
+ flex: none;
218
+ display: grid;
219
+ place-items: center;
220
+ width: 16px;
221
+ height: 16px;
222
+ margin-left: var(--spacing-1);
223
+ border-radius: 5px;
224
+ background: var(--color-background-surface);
225
+ box-shadow: inset 0 0 0 1.5px var(--color-border-emphasized);
226
+ color: var(--color-on-accent);
227
+ transition:
228
+ background-color var(--duration-fast) var(--ease-standard),
229
+ box-shadow var(--duration-fast) var(--ease-standard);
230
+ }
231
+ .os-tree-check .os-glyph {
232
+ width: 12px;
233
+ height: 12px;
234
+ stroke-width: 3;
235
+ }
236
+ .os-tree-check[data-state="checked"],
237
+ .os-tree-check[data-state="mixed"] {
238
+ background: var(--color-accent);
239
+ box-shadow: none;
240
+ }
241
+ .os-tree-row:hover .os-tree-check[data-state="unchecked"] {
242
+ box-shadow: inset 0 0 0 1.5px var(--color-accent);
243
+ }
244
+
245
+ /* cards — each top-level branch on its own surface */
246
+ .os-tree-cards {
247
+ display: flex;
248
+ flex-direction: column;
249
+ gap: var(--spacing-2);
250
+ }
251
+ .os-tree-cards > .os-tree-root {
252
+ padding: var(--spacing-1);
253
+ background: var(--color-background-surface);
254
+ border-radius: var(--radius-element);
255
+ box-shadow:
256
+ 0 0 0 1px var(--color-border),
257
+ var(--shadow-low, var(--elevation-1));
258
+ }
259
+ .os-tree-cards > .os-tree-root > .os-tree-group {
260
+ margin-top: var(--spacing-1);
261
+ padding-top: var(--spacing-1);
262
+ border-top: 1px solid var(--color-border);
263
+ }
264
+
265
+ @media (prefers-reduced-motion: reduce) {
266
+ .os-tree-group {
267
+ animation: none;
268
+ }
269
+ }