canny-ui 6.7.0 → 7.0.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 (49) hide show
  1. package/dist/canny-ui.min.css +1 -1
  2. package/dist/table-resize.js +16 -1
  3. package/package.json +1 -1
  4. package/src/_utilities.scss +4 -4
  5. package/src/base/_motion.scss +32 -0
  6. package/src/base/_reset.scss +7 -0
  7. package/src/base/_scrollbar-mixin.scss +84 -0
  8. package/src/base/_touch.scss +60 -0
  9. package/src/canny-ui.scss +5 -0
  10. package/src/components/_accordion.scss +10 -1
  11. package/src/components/_alerts.scss +18 -8
  12. package/src/components/_autocomplete.scss +16 -10
  13. package/src/components/_avatar.scss +22 -1
  14. package/src/components/_breadcrumb.scss +36 -2
  15. package/src/components/_buttons.scss +35 -24
  16. package/src/components/_charts-extra.scss +432 -0
  17. package/src/components/_charts.scss +90 -0
  18. package/src/components/_chip.scss +8 -7
  19. package/src/components/_command-palette.scss +27 -5
  20. package/src/components/_confirm.scss +14 -0
  21. package/src/components/_datatable.scss +383 -53
  22. package/src/components/_datepicker.scss +44 -21
  23. package/src/components/_dialog.scss +12 -0
  24. package/src/components/_drawer.scss +12 -0
  25. package/src/components/_fields.scss +115 -27
  26. package/src/components/_forms.scss +28 -10
  27. package/src/components/_gantt.scss +554 -0
  28. package/src/components/_inputs.scss +12 -7
  29. package/src/components/_list.scss +37 -3
  30. package/src/components/_menu.scss +23 -9
  31. package/src/components/_navbar.scss +98 -7
  32. package/src/components/_pagination.scss +105 -2
  33. package/src/components/_panels.scss +19 -5
  34. package/src/components/_popover.scss +3 -5
  35. package/src/components/_progress.scss +31 -0
  36. package/src/components/_scrollbar.scss +16 -159
  37. package/src/components/_sidebar.scss +24 -20
  38. package/src/components/_skeleton.scss +40 -1
  39. package/src/components/_slider.scss +8 -2
  40. package/src/components/_stepper.scss +22 -4
  41. package/src/components/_table.scss +23 -3
  42. package/src/components/_tabs.scss +120 -4
  43. package/src/components/_timeline.scss +26 -0
  44. package/src/components/_toast.scss +24 -12
  45. package/src/components/_tooltip-radix.scss +25 -4
  46. package/src/components/_tree.scss +51 -3
  47. package/src/components/_uploader.scss +97 -1
  48. package/src/scripts/table-resize.js +16 -1
  49. package/src/tokens/_semantic.scss +85 -21
@@ -0,0 +1,554 @@
1
+ @use '../tokens/primitives' as *;
2
+
3
+ // GanttChart — scheduling timeline (HTML bars + SVG dependency arrows).
4
+ // Shares the .cny-chart tooltip / empty-state styles from _charts.scss.
5
+
6
+ .cny-gantt {
7
+ --cny-gantt-row: 36px;
8
+ --cny-gantt-name: 200px;
9
+ background: var(--bg-surface-lowest);
10
+ border: 1px solid var(--border-color);
11
+ border-radius: $radius-md;
12
+ overflow: visible;
13
+ font-size: 0.8125rem;
14
+ color: var(--text-primary);
15
+ }
16
+
17
+ .cny-gantt-scroll {
18
+ overflow: auto;
19
+ border-radius: inherit;
20
+ }
21
+
22
+ .cny-gantt-inner {
23
+ position: relative;
24
+ min-width: 100%;
25
+ }
26
+
27
+ // ── header ───────────────────────────────────────────────────────
28
+ .cny-gantt-head {
29
+ position: sticky;
30
+ top: 0;
31
+ z-index: 6;
32
+ display: flex;
33
+ background: var(--bg-surface-low);
34
+ border-bottom: 1px solid var(--border-color);
35
+ }
36
+
37
+ .cny-gantt-corner {
38
+ position: sticky;
39
+ overflow: hidden;
40
+ left: 0;
41
+ z-index: 7;
42
+ flex: none;
43
+ width: var(--cny-gantt-name);
44
+ display: flex;
45
+ align-items: flex-end;
46
+ padding: 0 $space-3 6px;
47
+ background: var(--bg-surface-low);
48
+ border-inline-end: 1px solid var(--border-color);
49
+ font-size: 0.6875rem;
50
+ font-weight: 600;
51
+ letter-spacing: 0.04em;
52
+ text-transform: uppercase;
53
+ color: var(--text-muted);
54
+ }
55
+
56
+ .cny-gantt-timeline-head {
57
+ position: relative;
58
+ flex: none;
59
+ }
60
+
61
+ .cny-gantt-tier {
62
+ position: relative;
63
+ height: 50%;
64
+ }
65
+
66
+ .cny-gantt-cell {
67
+ position: absolute;
68
+ min-width: 0;
69
+ top: 0;
70
+ bottom: 0;
71
+ display: flex;
72
+ align-items: center;
73
+ padding-inline-start: 6px;
74
+ white-space: nowrap;
75
+ border-inline-start: 1px solid var(--hairline-color);
76
+ font-size: 0.6875rem;
77
+ color: var(--text-muted);
78
+
79
+ // The label is sticky inside its own cell, so a wide month/year label stays readable at
80
+ // the left edge of the timeline while its cell scrolls past (it can't leave the cell).
81
+ > .cny-gantt-cell-text {
82
+ position: sticky;
83
+ inset-inline-start: calc(var(--cny-gantt-name) + 6px);
84
+ max-width: 100%;
85
+ overflow: hidden;
86
+ text-overflow: ellipsis;
87
+ }
88
+
89
+ &.is-spill > .cny-gantt-cell-text {
90
+ max-width: none;
91
+ overflow: visible;
92
+ }
93
+
94
+ .is-top > & {
95
+ font-weight: 600;
96
+ color: var(--text-secondary);
97
+ }
98
+ }
99
+
100
+ .cny-gantt-today-flag {
101
+ position: absolute;
102
+ bottom: 0;
103
+ transform: translateX(-50%);
104
+ padding: 0 6px;
105
+ border-radius: 8px 8px 0 0;
106
+ background: var(--color-danger);
107
+ color: var(--color-danger-on);
108
+ font-size: 0.625rem;
109
+ font-weight: 600;
110
+ line-height: 14px;
111
+ pointer-events: none;
112
+
113
+ // Collapsed to a small pointer under the header when the chip would cover tick labels.
114
+ &.is-mark {
115
+ bottom: -5px;
116
+ width: 0;
117
+ height: 0;
118
+ padding: 0;
119
+ border-style: solid;
120
+ border-width: 6px 5px 0;
121
+ border-color: var(--color-danger) transparent transparent;
122
+ border-radius: 0;
123
+ background: none;
124
+ font-size: 0;
125
+ line-height: 0;
126
+ color: transparent;
127
+ overflow: hidden;
128
+ }
129
+ }
130
+
131
+ // drag edge of the sticky name column
132
+ .cny-gantt-resize {
133
+ position: absolute;
134
+ top: 0;
135
+ right: -3px;
136
+ bottom: 0;
137
+ width: 7px;
138
+ z-index: 8;
139
+ cursor: col-resize;
140
+ touch-action: none;
141
+
142
+ &:hover,
143
+ &:focus-visible {
144
+ background: color-mix(in srgb, var(--border-focus) 55%, transparent);
145
+ }
146
+
147
+ &:focus-visible {
148
+ outline: 2px solid var(--border-focus);
149
+ outline-offset: -2px;
150
+ }
151
+ }
152
+
153
+ // ── rows ─────────────────────────────────────────────────────────
154
+ .cny-gantt-body {
155
+ position: relative;
156
+ }
157
+
158
+ .cny-gantt-row {
159
+ position: absolute;
160
+ left: 0;
161
+ right: 0;
162
+ display: flex;
163
+ background: var(--bg-surface-lowest);
164
+ // The row line is a shadow (not a border) so the sticky name cell covers the full row
165
+ // height and nothing — dependency elbows, grid ticks — shows through beside it.
166
+ box-shadow: inset 0 -1px 0 var(--hairline-color);
167
+
168
+ &:hover {
169
+ background: var(--bg-surface-low);
170
+ }
171
+
172
+ &.is-group {
173
+ font-weight: 600;
174
+ }
175
+ }
176
+
177
+ .cny-gantt-name > .cny-gantt-label,
178
+ .cny-gantt-toggle > .cny-gantt-label {
179
+ min-width: 0;
180
+ }
181
+
182
+ .cny-gantt-name {
183
+ position: sticky;
184
+ left: 0;
185
+ z-index: 4;
186
+ flex: none;
187
+ display: flex;
188
+ align-items: center;
189
+ width: var(--cny-gantt-name);
190
+ padding: 0 $space-3;
191
+ background: inherit;
192
+ border-inline-end: 1px solid var(--border-color);
193
+ // opaque underlay + the row line, so the name column fully masks the timeline layers
194
+ box-shadow: inset 0 -1px 0 var(--hairline-color);
195
+ overflow: hidden;
196
+
197
+ &.is-indent {
198
+ padding-inline-start: $space-6;
199
+ }
200
+ }
201
+
202
+ .cny-gantt-label {
203
+ overflow: hidden;
204
+ text-overflow: ellipsis;
205
+ white-space: nowrap;
206
+ }
207
+
208
+ .cny-gantt-toggle {
209
+ appearance: none;
210
+ display: flex;
211
+ align-items: center;
212
+ gap: 6px;
213
+ width: 100%;
214
+ margin: 0;
215
+ padding: 0;
216
+ border: 0;
217
+ background: none;
218
+ font: inherit;
219
+ color: inherit;
220
+ cursor: pointer;
221
+ text-align: start;
222
+ height: 100%;
223
+
224
+ &:focus-visible {
225
+ outline: 2px solid var(--border-focus);
226
+ outline-offset: 2px;
227
+ border-radius: var(--radius-xs);
228
+ }
229
+ }
230
+
231
+ .cny-gantt-chevron {
232
+ flex: none;
233
+ color: var(--text-muted);
234
+ transition: transform 150ms ease;
235
+
236
+ [aria-expanded='true'] > & {
237
+ transform: rotate(90deg);
238
+ }
239
+ }
240
+
241
+ .cny-gantt-count {
242
+ margin-inline-start: auto;
243
+ padding: 0 6px;
244
+ border-radius: 8px;
245
+ background: var(--bg-surface-edge);
246
+ font-size: 0.6875rem;
247
+ font-weight: 500;
248
+ color: var(--text-secondary);
249
+ }
250
+
251
+ .cny-gantt-track {
252
+ position: relative;
253
+ flex: none;
254
+ }
255
+
256
+ .cny-gantt-groupbar {
257
+ position: absolute;
258
+ top: 50%;
259
+ height: 6px;
260
+ margin-top: -3px;
261
+ border-radius: 3px;
262
+ opacity: 0.55;
263
+ }
264
+
265
+ // ── grid layer (weekends, column lines, today): one svg for the rendered rows ──
266
+ .cny-gantt-grid {
267
+ position: absolute;
268
+ left: var(--cny-gantt-name);
269
+ z-index: 1;
270
+ pointer-events: none;
271
+ overflow: hidden;
272
+ }
273
+
274
+ .cny-gantt-weekend {
275
+ fill: var(--bg-surface-low);
276
+ opacity: 0.7;
277
+ }
278
+
279
+ .cny-gantt-line {
280
+ fill: none;
281
+ stroke: var(--hairline-color);
282
+ stroke-width: 1;
283
+ vector-effect: non-scaling-stroke;
284
+ }
285
+
286
+ .cny-gantt-today {
287
+ stroke: var(--color-danger);
288
+ stroke-width: 2;
289
+ opacity: 0.8;
290
+ }
291
+
292
+ // ── zoom buttons ─────────────────────────────────────────────────
293
+ .cny-gantt-toolbar {
294
+ display: flex;
295
+ justify-content: flex-end;
296
+ padding: $space-1 $space-2;
297
+ border-bottom: 1px solid var(--border-color);
298
+ border-radius: inherit;
299
+ border-end-start-radius: 0;
300
+ border-end-end-radius: 0;
301
+ background: var(--bg-surface-lowest);
302
+ }
303
+
304
+ // In the toolbar above the chart, not floating over the bars.
305
+ .cny-gantt-zoom {
306
+ display: flex;
307
+ border: 1px solid var(--border-color);
308
+ border-radius: $radius-md;
309
+ background: var(--bg-surface-lowest);
310
+ overflow: hidden;
311
+ }
312
+
313
+ .cny-gantt-zoom-btn {
314
+ appearance: none;
315
+ width: 30px;
316
+ height: 28px;
317
+ margin: 0;
318
+ padding: 0;
319
+ border: 0;
320
+ background: none;
321
+ font: inherit;
322
+ font-size: 1rem;
323
+ line-height: 1;
324
+ color: var(--text-primary);
325
+ cursor: pointer;
326
+
327
+ & + & {
328
+ border-inline-start: 1px solid var(--border-color);
329
+ }
330
+ &:hover:not(:disabled) {
331
+ background: var(--bg-surface-low);
332
+ }
333
+ &:focus-visible {
334
+ outline: 2px solid var(--border-focus);
335
+ outline-offset: -2px;
336
+ }
337
+ &:disabled {
338
+ opacity: 0.4;
339
+ cursor: default;
340
+ }
341
+ }
342
+
343
+ // ── bars ─────────────────────────────────────────────────────────
344
+ .cny-gantt-bar {
345
+ position: absolute;
346
+ top: 7px;
347
+ bottom: 7px;
348
+ z-index: 3;
349
+ border-radius: 5px;
350
+ background: color-mix(in srgb, var(--cny-gantt-color, var(--color-primary)) 30%, var(--bg-surface-lowest));
351
+ outline: none;
352
+ cursor: pointer;
353
+ transform-origin: left center;
354
+ touch-action: none;
355
+
356
+ &:hover {
357
+ filter: brightness(0.96);
358
+ }
359
+ &:focus-visible {
360
+ outline: 2px solid var(--border-focus);
361
+ outline-offset: 2px;
362
+ }
363
+ &.is-editable {
364
+ cursor: grab;
365
+ }
366
+ &.is-dragging {
367
+ cursor: grabbing;
368
+ box-shadow: var(--shadow-md);
369
+ z-index: 5;
370
+ }
371
+
372
+ &.is-milestone {
373
+ background: none;
374
+ transform-origin: center;
375
+
376
+ &::before {
377
+ content: '';
378
+ position: absolute;
379
+ top: 50%;
380
+ left: 50%;
381
+ width: 12px;
382
+ height: 12px;
383
+ margin: -6px 0 0 -6px;
384
+ border-radius: 2px;
385
+ background: var(--cny-gantt-color, var(--color-primary));
386
+ transform: rotate(45deg);
387
+ }
388
+ }
389
+ }
390
+
391
+ .cny-gantt-progress {
392
+ position: absolute;
393
+ inset: 0 auto 0 0;
394
+ border-radius: inherit;
395
+ background: var(--cny-gantt-color, var(--color-primary));
396
+ transform-origin: left center;
397
+ pointer-events: none;
398
+ }
399
+
400
+ .cny-gantt-handle {
401
+ position: absolute;
402
+ top: 0;
403
+ bottom: 0;
404
+ z-index: 1;
405
+ width: 8px;
406
+ cursor: ew-resize;
407
+
408
+ &.is-start {
409
+ left: -2px;
410
+ }
411
+ &.is-end {
412
+ right: -2px;
413
+ }
414
+ }
415
+
416
+ // ── coarse pointers: >=44px targets ──────────────────────────────
417
+ @media (pointer: coarse) {
418
+ .cny-gantt-zoom-btn {
419
+ width: 44px;
420
+ height: 44px;
421
+ }
422
+
423
+ .cny-gantt-resize::before {
424
+ content: '';
425
+ position: absolute;
426
+ inset: 0 0 0 -34px;
427
+ }
428
+
429
+ .cny-gantt-handle {
430
+ width: 16px;
431
+
432
+ &.is-start { left: -6px; }
433
+ &.is-end { right: -6px; }
434
+ }
435
+ }
436
+
437
+ // ── dependency arrows ────────────────────────────────────────────
438
+ .cny-gantt-deps {
439
+ position: absolute;
440
+ top: 0;
441
+ left: var(--cny-gantt-name);
442
+ z-index: 2;
443
+ pointer-events: none;
444
+ overflow: visible;
445
+ }
446
+
447
+ .cny-gantt-dep {
448
+ path {
449
+ fill: none;
450
+ stroke: var(--text-muted);
451
+ stroke-width: 1.5;
452
+ stroke-linejoin: round;
453
+ }
454
+
455
+ .cny-gantt-dep-head {
456
+ fill: var(--text-muted);
457
+ stroke: none;
458
+ }
459
+ }
460
+
461
+ // ── loading skeleton ─────────────────────────────────────────────
462
+ .cny-gantt-skeleton {
463
+ padding-top: 44px;
464
+ }
465
+
466
+ .cny-gantt-skeleton-row {
467
+ display: flex;
468
+ align-items: center;
469
+ gap: $space-4;
470
+ padding: 0 $space-3;
471
+ }
472
+
473
+ // ── motion ───────────────────────────────────────────────────────
474
+ @keyframes cny-gantt-grow {
475
+ from { transform: scaleX(0); opacity: 0; }
476
+ to { transform: scaleX(1); opacity: 1; }
477
+ }
478
+
479
+ @keyframes cny-gantt-pop {
480
+ from { transform: scale(0); opacity: 0; }
481
+ to { transform: scale(1); opacity: 1; }
482
+ }
483
+
484
+ @keyframes cny-gantt-draw {
485
+ from { stroke-dashoffset: 1; }
486
+ to { stroke-dashoffset: 0; }
487
+ }
488
+
489
+ @keyframes cny-gantt-fade {
490
+ from { opacity: 0; }
491
+ to { opacity: 1; }
492
+ }
493
+
494
+ .cny-gantt.is-animated {
495
+ .cny-gantt-bar {
496
+ transition: left 300ms ease, width 300ms ease, box-shadow 150ms ease;
497
+
498
+ &.is-dragging {
499
+ transition: box-shadow 150ms ease;
500
+ }
501
+ }
502
+
503
+ .cny-gantt-progress {
504
+ transition: width 300ms ease;
505
+ }
506
+
507
+ .cny-gantt-groupbar {
508
+ transition: left 300ms ease, width 300ms ease;
509
+ }
510
+ }
511
+
512
+ // entrance only on first mount (rows scrolled into view later don't replay it)
513
+ .cny-gantt.is-animated.is-entering {
514
+ .cny-gantt-bar {
515
+ animation: cny-gantt-grow 420ms cubic-bezier(0.2, 0.8, 0.2, 1) both;
516
+ animation-delay: calc(var(--cny-gantt-i, 0) * 40ms);
517
+
518
+ &.is-milestone {
519
+ animation-name: cny-gantt-pop;
520
+ }
521
+ }
522
+
523
+ .cny-gantt-progress {
524
+ animation: cny-gantt-grow 520ms cubic-bezier(0.2, 0.8, 0.2, 1) both;
525
+ animation-delay: calc(var(--cny-gantt-i, 0) * 40ms + 320ms);
526
+ }
527
+
528
+ .cny-gantt-dep path {
529
+ stroke-dasharray: 1;
530
+ animation: cny-gantt-draw 500ms ease both;
531
+ animation-delay: var(--cny-gantt-dep-delay, 0ms);
532
+ }
533
+
534
+ .cny-gantt-dep .cny-gantt-dep-head {
535
+ stroke-dasharray: none;
536
+ animation: cny-gantt-fade 200ms ease both;
537
+ animation-delay: calc(var(--cny-gantt-dep-delay, 0ms) + 450ms);
538
+ }
539
+ }
540
+
541
+ @media (prefers-reduced-motion: reduce) {
542
+ .cny-gantt .cny-gantt-bar,
543
+ .cny-gantt .cny-gantt-progress,
544
+ .cny-gantt .cny-gantt-groupbar,
545
+ .cny-gantt .cny-gantt-dep path,
546
+ .cny-gantt .cny-gantt-chevron {
547
+ animation: none !important;
548
+ transition: none !important;
549
+ }
550
+
551
+ .cny-gantt .cny-gantt-dep path {
552
+ stroke-dasharray: none;
553
+ }
554
+ }
@@ -1,3 +1,4 @@
1
+ @use '../base/scrollbar-mixin' as sb;
1
2
  @use '../tokens/primitives' as *;
2
3
 
3
4
  // Enterprise input — full real border, focus ring, predictable affordances.
@@ -9,7 +10,8 @@
9
10
  padding: 0 $space-3;
10
11
  background: var(--bg-surface-lowest);
11
12
  color: var(--text-primary);
12
- border: 1px solid var(--border-color);
13
+ border: 1px solid var(--border-input);
14
+ box-shadow: var(--shadow-field);
13
15
  border-radius: var(--radius-sm);
14
16
  outline: none;
15
17
  font-family: var(--font-body);
@@ -24,16 +26,17 @@
24
26
  }
25
27
 
26
28
  &:hover:not(:disabled):not(:focus) {
27
- border-color: var(--border-color-strong);
29
+ border-color: var(--border-input-hover);
28
30
  }
29
31
 
30
32
  &:focus {
31
- border-color: var(--border-focus);
33
+ border-color: var(--border-input-focus);
32
34
  box-shadow: none;
33
35
  }
34
36
 
35
37
  &:disabled {
36
38
  background: var(--bg-surface-low);
39
+ box-shadow: none;
37
40
  color: var(--text-disabled);
38
41
  cursor: not-allowed;
39
42
  }
@@ -50,6 +53,7 @@
50
53
  &.filled {
51
54
  background: var(--bg-surface-low);
52
55
  border-color: transparent;
56
+ box-shadow: none;
53
57
 
54
58
  &:hover:not(:disabled):not(:focus) {
55
59
  background: var(--bg-surface-edge);
@@ -58,7 +62,7 @@
58
62
 
59
63
  &:focus {
60
64
  background: var(--bg-surface-lowest);
61
- border-color: var(--border-focus);
65
+ border-color: var(--border-input-focus);
62
66
  }
63
67
  }
64
68
 
@@ -85,6 +89,7 @@ textarea.input {
85
89
  padding: $space-2 $space-3;
86
90
  line-height: 1.55;
87
91
  resize: vertical;
92
+ @include sb.expand-scrollbar;
88
93
  }
89
94
 
90
95
  // Label — small, uppercase-neutral, sits above the input
@@ -104,7 +109,7 @@ textarea.input {
104
109
  color: var(--text-muted);
105
110
  margin-top: $space-2;
106
111
 
107
- &.danger { color: var(--color-danger); }
108
- &.warning { color: var(--color-warning); }
109
- &.success { color: var(--color-success); }
112
+ &.danger { color: var(--color-danger-text); }
113
+ &.warning { color: var(--color-warning-text); }
114
+ &.success { color: var(--color-success-text); }
110
115
  }
@@ -29,6 +29,29 @@
29
29
  display: flex;
30
30
  }
31
31
 
32
+ // Windowed list: the list is the scrollport and every row has a fixed height;
33
+ // spacer rows stand in for the rows that are not in the DOM.
34
+ .cny-list.is-virtual {
35
+ overflow-y: auto;
36
+ overflow-x: hidden;
37
+
38
+ > li {
39
+ flex: none;
40
+ box-sizing: border-box;
41
+ height: var(--cny-list-row-h, 64px);
42
+ overflow: hidden;
43
+ }
44
+
45
+ > li > .cny-list-item {
46
+ height: 100%;
47
+ }
48
+
49
+ > li.cny-list-spacer {
50
+ height: auto;
51
+ padding: 0;
52
+ }
53
+ }
54
+
32
55
  .cny-list-item {
33
56
  display: flex;
34
57
  align-items: center;
@@ -100,11 +123,11 @@
100
123
 
101
124
  &.is-active {
102
125
  background: color-mix(in srgb, var(--color-primary) 10%, var(--bg-surface-low));
103
- color: var(--color-primary);
126
+ color: var(--text-accent);
104
127
 
105
128
  .cny-list-item-leading,
106
- .cny-list-item-trailing { color: var(--color-primary); }
107
- .cny-list-item-primary { color: var(--color-primary); font-weight: 600; }
129
+ .cny-list-item-trailing { color: var(--text-accent); }
130
+ .cny-list-item-primary { color: var(--text-accent); font-weight: 600; }
108
131
  }
109
132
 
110
133
  &.is-disabled {
@@ -127,3 +150,14 @@
127
150
  text-transform: uppercase;
128
151
  color: var(--text-muted);
129
152
  }
153
+
154
+ // `empty` / `loading` states
155
+ .cny-list-empty {
156
+ padding: 24px 14px;
157
+ text-align: center;
158
+ font-size: 0.875rem;
159
+ color: var(--text-muted);
160
+ }
161
+ .cny-list-skeleton .cny-list-item {
162
+ cursor: default;
163
+ }