@salemcobalt/ui 0.2.0-rc.3 → 0.2.0-rc.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/styles.css CHANGED
@@ -1,4 +1,4 @@
1
- /* @salemcobalt/ui 0.2.0-rc.3 — requires @salemcobalt/tokens/css. */
1
+ /* @salemcobalt/ui 0.2.0-rc.5 — requires @salemcobalt/tokens/css. */
2
2
  @layer sc {
3
3
  /* ---- base.css ---- */
4
4
  /* Shared: focus ring, reduced motion. Component files follow. */
@@ -10,6 +10,7 @@
10
10
  .sc-input:focus-visible,
11
11
  .sc-select:focus-visible,
12
12
  .sc-select__item:focus-visible,
13
+ .sc-select__clear:focus-visible,
13
14
  .sc-checkbox:focus-visible,
14
15
  .sc-switch:focus-visible,
15
16
  .sc-tabs__tab:focus-visible,
@@ -731,14 +732,19 @@
731
732
  transition-duration: calc(var(--sc-duration-base) * 0.75);
732
733
  transition-timing-function: var(--sc-ease-exit);
733
734
  }
735
+ /* The popup never exceeds the viewport minus a gutter each side, whatever `size` says. 100dvw rather than
736
+ 100% so the clamp holds inside a transformed or narrow portal container too. */
734
737
  .sc-dialog__popup {
738
+ --_gutter: var(--sc-spacing-md);
739
+ --_max: calc(100dvw - 2 * var(--_gutter));
735
740
  position: fixed;
736
741
  inset: 0;
737
742
  margin: auto;
738
743
  z-index: var(--sc-z-dialog);
739
744
  box-sizing: border-box;
740
- inline-size: min(100% - 2 * var(--sc-spacing-md), var(--sc-size-dialog-md));
741
- max-block-size: min(100% - 2 * var(--sc-spacing-md), 85dvh);
745
+ inline-size: min(var(--_max), var(--sc-size-dialog-md));
746
+ max-inline-size: var(--_max);
747
+ max-block-size: min(100dvh - 2 * var(--_gutter), 85dvh);
742
748
  block-size: fit-content;
743
749
  overflow: auto;
744
750
  padding: var(--sc-spacing-lg);
@@ -764,10 +770,10 @@
764
770
  transition-timing-function: var(--sc-ease-exit);
765
771
  }
766
772
  .sc-dialog__popup[data-size='sm'] {
767
- inline-size: min(100% - 2 * var(--sc-spacing-md), var(--sc-size-dialog-sm));
773
+ inline-size: min(var(--_max), var(--sc-size-dialog-sm));
768
774
  }
769
775
  .sc-dialog__popup[data-size='lg'] {
770
- inline-size: min(100% - 2 * var(--sc-spacing-md), var(--sc-size-dialog-lg));
776
+ inline-size: min(var(--_max), var(--sc-size-dialog-lg));
771
777
  }
772
778
  .sc-dialog__title {
773
779
  margin: 0;
@@ -788,6 +794,20 @@
788
794
  font-size: var(--sc-font-size-sm);
789
795
  line-height: var(--sc-font-line-height-normal);
790
796
  }
797
+ /* Content wraps instead of widening the popup: long URLs break, fields and media stay inside the box. */
798
+ .sc-dialog__title,
799
+ .sc-dialog__description,
800
+ .sc-dialog__body {
801
+ min-inline-size: 0;
802
+ overflow-wrap: anywhere;
803
+ }
804
+ .sc-dialog__body > *,
805
+ .sc-dialog__body :where(img, video, table, pre, .sc-select) {
806
+ max-inline-size: 100%;
807
+ }
808
+ .sc-dialog__body :where(pre) {
809
+ overflow: auto;
810
+ }
791
811
  .sc-dialog__actions {
792
812
  margin-block-start: var(--sc-spacing-lg);
793
813
  }
@@ -810,6 +830,65 @@
810
830
  background: var(--sc-color-surface-hover);
811
831
  color: var(--sc-color-text-default);
812
832
  }
833
+ /* Sheet: title and actions stay put, the body scrolls. Same centred box as `dialog` on wide viewports. */
834
+ .sc-dialog__popup[data-variant='sheet'] {
835
+ display: flex;
836
+ flex-direction: column;
837
+ overflow: hidden;
838
+ }
839
+ .sc-dialog__popup[data-variant='sheet'] > .sc-dialog__title,
840
+ .sc-dialog__popup[data-variant='sheet'] > .sc-dialog__description,
841
+ .sc-dialog__popup[data-variant='sheet'] > .sc-dialog__actions {
842
+ flex: none;
843
+ }
844
+ .sc-dialog__popup[data-variant='sheet'] > .sc-dialog__body {
845
+ flex: 1 1 auto;
846
+ min-block-size: 0;
847
+ overflow: auto;
848
+ overscroll-behavior: contain;
849
+ }
850
+ /* Below 640px the sheet docks to the bottom edge, full width, and slides up. The breakpoint is fixed
851
+ here because custom properties cannot drive a media query. */
852
+ @media (width < 640px) {
853
+ .sc-dialog__popup[data-variant='sheet'] {
854
+ inset: auto 0 0 0;
855
+ margin: 0;
856
+ inline-size: 100%;
857
+ max-inline-size: none;
858
+ max-block-size: calc(100dvh - env(safe-area-inset-top, 0px) - var(--sc-spacing-xl));
859
+ padding-block-end: calc(var(--sc-spacing-lg) + env(safe-area-inset-bottom, 0px));
860
+ padding-inline: calc(var(--sc-spacing-lg) + env(safe-area-inset-left, 0px))
861
+ calc(var(--sc-spacing-lg) + env(safe-area-inset-right, 0px));
862
+ border-block-end: 0;
863
+ border-radius: var(--sc-radius-xl) var(--sc-radius-xl) 0 0;
864
+ transition:
865
+ opacity var(--sc-duration-base) var(--sc-ease-enter),
866
+ translate var(--sc-duration-base) var(--sc-ease-enter);
867
+ }
868
+ .sc-dialog__popup[data-variant='sheet']::before {
869
+ content: '';
870
+ flex: none;
871
+ align-self: center;
872
+ inline-size: 36px;
873
+ block-size: 4px;
874
+ margin-block: calc(-1 * var(--sc-spacing-sm)) var(--sc-spacing-md);
875
+ border-radius: var(--sc-radius-full);
876
+ background: var(--sc-color-border-strong);
877
+ }
878
+ .sc-dialog__popup[data-variant='sheet'][data-starting-style],
879
+ .sc-dialog__popup[data-variant='sheet'][data-ending-style] {
880
+ opacity: 1;
881
+ translate: 0 100%;
882
+ scale: none;
883
+ }
884
+ /* Actions stack full width, confirming action on top, in thumb reach. */
885
+ .sc-dialog__popup[data-variant='sheet'] > .sc-dialog__actions {
886
+ flex-wrap: wrap-reverse;
887
+ }
888
+ .sc-dialog__popup[data-variant='sheet'] > .sc-dialog__actions > * {
889
+ flex: 1 1 100%;
890
+ }
891
+ }
813
892
  @media (prefers-reduced-motion: reduce) {
814
893
  .sc-dialog__backdrop,
815
894
  .sc-dialog__popup {
@@ -1100,6 +1179,7 @@
1100
1179
  min-inline-size: 0;
1101
1180
  }
1102
1181
  .sc-input {
1182
+ appearance: none;
1103
1183
  box-sizing: border-box;
1104
1184
  inline-size: 100%;
1105
1185
  min-inline-size: 0;
@@ -1137,6 +1217,30 @@
1137
1217
  color: var(--sc-color-text-subtle);
1138
1218
  cursor: not-allowed;
1139
1219
  }
1220
+ /* Native date, time and number fields: same box, tabular digits, the picker indicator at the end edge. */
1221
+ .sc-input:is(
1222
+ [type='date'],
1223
+ [type='time'],
1224
+ [type='datetime-local'],
1225
+ [type='month'],
1226
+ [type='week'],
1227
+ [type='number']
1228
+ ) {
1229
+ font-variant-numeric: tabular-nums;
1230
+ }
1231
+ .sc-input::-webkit-date-and-time-value {
1232
+ min-block-size: 1lh;
1233
+ text-align: start;
1234
+ }
1235
+ .sc-input::-webkit-calendar-picker-indicator {
1236
+ margin-inline-start: var(--sc-spacing-xs);
1237
+ padding: 0;
1238
+ opacity: 0.7;
1239
+ cursor: pointer;
1240
+ }
1241
+ .sc-input::-webkit-calendar-picker-indicator:hover {
1242
+ opacity: 1;
1243
+ }
1140
1244
  .sc-input-wrap[data-icon-start] > .sc-input {
1141
1245
  padding-inline-start: calc(var(--_px) + var(--sc-size-icon-md) + var(--sc-spacing-xs));
1142
1246
  }
@@ -1174,7 +1278,29 @@
1174
1278
  .sc-textarea[data-resize='none'] {
1175
1279
  resize: none;
1176
1280
  }
1281
+ .sc-textarea[data-variant='code'] {
1282
+ font-family: var(--sc-font-family-mono);
1283
+ font-size: calc(var(--_fs) * 0.95);
1284
+ line-height: var(--sc-font-line-height-normal);
1285
+ tab-size: 2;
1286
+ hyphens: none;
1287
+ overflow-wrap: normal;
1288
+ }
1289
+ .sc-textarea[wrap='off'] {
1290
+ white-space: pre;
1291
+ overflow-x: auto;
1292
+ }
1177
1293
  /* Select */
1294
+ .sc-select__wrap {
1295
+ position: relative;
1296
+ display: inline-flex;
1297
+ max-inline-size: 100%;
1298
+ align-self: flex-start;
1299
+ }
1300
+ .sc-select__wrap[data-full-width] {
1301
+ display: flex;
1302
+ align-self: stretch;
1303
+ }
1178
1304
  .sc-select {
1179
1305
  box-sizing: border-box;
1180
1306
  display: inline-flex;
@@ -1206,6 +1332,30 @@
1206
1332
  inline-size: 100%;
1207
1333
  align-self: stretch;
1208
1334
  }
1335
+ /* Room for the × between the value and the chevron. The clear button is a sibling, never nested in the trigger. */
1336
+ .sc-select[data-clearable] > .sc-select__icon {
1337
+ margin-inline-start: calc(var(--sc-size-icon-lg) + var(--sc-spacing-2xs));
1338
+ }
1339
+ .sc-select__clear {
1340
+ position: absolute;
1341
+ inset-block-start: 50%;
1342
+ inset-inline-end: calc(var(--sc-spacing-xs) + var(--sc-size-icon-md) + var(--sc-spacing-2xs));
1343
+ translate: 0 -50%;
1344
+ display: inline-grid;
1345
+ place-items: center;
1346
+ inline-size: var(--sc-size-icon-lg);
1347
+ block-size: var(--sc-size-icon-lg);
1348
+ padding: 0;
1349
+ border: 0;
1350
+ border-radius: var(--sc-radius-sm);
1351
+ background: transparent;
1352
+ color: var(--sc-color-text-muted);
1353
+ cursor: pointer;
1354
+ }
1355
+ .sc-select__clear:hover {
1356
+ background: var(--sc-color-surface-hover);
1357
+ color: var(--sc-color-text-default);
1358
+ }
1209
1359
  .sc-select:hover:not([data-disabled]) {
1210
1360
  border-color: var(--sc-color-text-muted);
1211
1361
  }
@@ -2114,4 +2264,398 @@
2114
2264
  font-size: var(--sc-font-size-xs);
2115
2265
  }
2116
2266
 
2267
+ /* ---- chip.css ---- */
2268
+ /* ---- Chip ------------------------------------------------------------------ */
2269
+ .sc-chip {
2270
+ --_h: var(--sc-size-control-sm);
2271
+ --_px: var(--sc-spacing-sm);
2272
+ --_fs: var(--sc-font-size-sm);
2273
+ --_icon: var(--sc-size-icon-sm);
2274
+ --_bg: transparent;
2275
+ --_fg: var(--sc-color-text-default);
2276
+ --_bd: var(--sc-color-border-strong);
2277
+ --_bg-hover: var(--sc-color-surface-hover);
2278
+ --_bg-on: var(--sc-color-surface-active);
2279
+ --_fg-on: var(--sc-color-text-default);
2280
+ --_bd-on: var(--sc-color-text-muted);
2281
+ position: relative;
2282
+ display: inline-flex;
2283
+ align-items: center;
2284
+ box-sizing: border-box;
2285
+ max-inline-size: 100%;
2286
+ block-size: var(--_h);
2287
+ border-radius: var(--sc-radius-full);
2288
+ border: var(--sc-border-width-hairline) solid var(--_bd);
2289
+ background: var(--_bg);
2290
+ color: var(--_fg);
2291
+ font-family: var(--sc-font-family-sans);
2292
+ font-size: var(--_fs);
2293
+ font-weight: var(--sc-font-weight-medium);
2294
+ line-height: 1;
2295
+ white-space: nowrap;
2296
+ transition:
2297
+ background-color var(--sc-duration-fast) var(--sc-ease-standard),
2298
+ border-color var(--sc-duration-fast) var(--sc-ease-standard),
2299
+ color var(--sc-duration-fast) var(--sc-ease-standard);
2300
+ }
2301
+ .sc-chip[data-size='sm'] {
2302
+ --_h: var(--sc-size-badge-md);
2303
+ --_px: var(--sc-spacing-xs);
2304
+ --_fs: var(--sc-font-size-xs);
2305
+ --_icon: var(--sc-size-icon-xs);
2306
+ }
2307
+ .sc-chip[data-selected] {
2308
+ --_bg: var(--_bg-on);
2309
+ --_fg: var(--_fg-on);
2310
+ --_bd: var(--_bd-on);
2311
+ }
2312
+ .sc-chip[data-disabled] {
2313
+ opacity: 0.5;
2314
+ }
2315
+ /* The text, or the toggle button that holds it. */
2316
+ .sc-chip__action,
2317
+ .sc-chip > .sc-chip__icon,
2318
+ .sc-chip > .sc-chip__label {
2319
+ display: inline-flex;
2320
+ align-items: center;
2321
+ min-inline-size: 0;
2322
+ }
2323
+ .sc-chip > .sc-chip__icon {
2324
+ margin-inline-start: var(--_px);
2325
+ }
2326
+ .sc-chip > .sc-chip__label {
2327
+ padding-inline: var(--_px);
2328
+ }
2329
+ .sc-chip > .sc-chip__icon + .sc-chip__label {
2330
+ padding-inline-start: var(--sc-spacing-2xs);
2331
+ }
2332
+ .sc-chip__action {
2333
+ gap: var(--sc-spacing-2xs);
2334
+ box-sizing: border-box;
2335
+ block-size: 100%;
2336
+ margin: 0;
2337
+ padding-inline: var(--_px);
2338
+ border: 0;
2339
+ border-radius: inherit;
2340
+ background: transparent;
2341
+ color: inherit;
2342
+ font: inherit;
2343
+ line-height: 1;
2344
+ cursor: pointer;
2345
+ }
2346
+ .sc-chip__action:hover:not(:disabled) {
2347
+ background: var(--_bg-hover);
2348
+ }
2349
+ .sc-chip[data-selected] > .sc-chip__action:hover:not(:disabled) {
2350
+ background: transparent;
2351
+ filter: brightness(0.97);
2352
+ }
2353
+ .sc-chip__action:disabled {
2354
+ cursor: not-allowed;
2355
+ }
2356
+ .sc-chip__icon {
2357
+ flex: none;
2358
+ inline-size: var(--_icon);
2359
+ block-size: var(--_icon);
2360
+ }
2361
+ .sc-chip__icon > svg {
2362
+ inline-size: 100%;
2363
+ block-size: 100%;
2364
+ }
2365
+ .sc-chip__label {
2366
+ overflow: hidden;
2367
+ text-overflow: ellipsis;
2368
+ }
2369
+ .sc-chip[data-removable] > .sc-chip__action,
2370
+ .sc-chip[data-removable] > .sc-chip__label {
2371
+ padding-inline-end: var(--sc-spacing-2xs);
2372
+ }
2373
+ .sc-chip__remove {
2374
+ flex: none;
2375
+ display: inline-grid;
2376
+ place-items: center;
2377
+ box-sizing: border-box;
2378
+ inline-size: calc(var(--_h) - 2 * var(--sc-spacing-2xs) - 2px);
2379
+ block-size: calc(var(--_h) - 2 * var(--sc-spacing-2xs) - 2px);
2380
+ margin-inline-end: var(--sc-spacing-2xs);
2381
+ padding: 0;
2382
+ border: 0;
2383
+ border-radius: var(--sc-radius-full);
2384
+ background: transparent;
2385
+ color: inherit;
2386
+ opacity: 0.7;
2387
+ cursor: pointer;
2388
+ }
2389
+ .sc-chip__remove:hover:not(:disabled) {
2390
+ opacity: 1;
2391
+ background: var(--_bg-hover);
2392
+ }
2393
+ .sc-chip__remove:disabled {
2394
+ cursor: not-allowed;
2395
+ }
2396
+ .sc-chip__action:focus-visible,
2397
+ .sc-chip__remove:focus-visible {
2398
+ outline: var(--sc-border-width-focus) solid var(--sc-color-border-focus);
2399
+ outline-offset: 0;
2400
+ }
2401
+ /* 44px hit area on touch without changing layout. */
2402
+ @media (pointer: coarse) {
2403
+ .sc-chip__action::after,
2404
+ .sc-chip__remove::after {
2405
+ content: '';
2406
+ position: absolute;
2407
+ inset: 50% auto auto 50%;
2408
+ translate: -50% -50%;
2409
+ inline-size: max(100%, var(--sc-size-touch-target));
2410
+ block-size: max(100%, var(--sc-size-touch-target));
2411
+ }
2412
+ .sc-chip__action,
2413
+ .sc-chip__remove {
2414
+ position: relative;
2415
+ }
2416
+ }
2417
+ /* Tones: soft fill when selected, tinted outline otherwise. */
2418
+ .sc-chip[data-tone='accent'] {
2419
+ --_fg: var(--sc-color-accent-text);
2420
+ --_bd: var(--sc-color-accent-text);
2421
+ --_bg-hover: var(--sc-color-accent-subtle);
2422
+ --_bg-on: var(--sc-color-accent-subtle);
2423
+ --_fg-on: var(--sc-color-accent-text);
2424
+ --_bd-on: var(--sc-color-accent-default);
2425
+ }
2426
+ .sc-chip[data-tone='success'] {
2427
+ --_fg: var(--sc-color-success-text);
2428
+ --_bd: var(--sc-color-success-text);
2429
+ --_bg-hover: var(--sc-color-success-subtle);
2430
+ --_bg-on: var(--sc-color-success-subtle);
2431
+ --_fg-on: var(--sc-color-success-text);
2432
+ --_bd-on: var(--sc-color-success-solid);
2433
+ }
2434
+ .sc-chip[data-tone='warning'] {
2435
+ --_fg: var(--sc-color-warning-text);
2436
+ --_bd: var(--sc-color-warning-text);
2437
+ --_bg-hover: var(--sc-color-warning-subtle);
2438
+ --_bg-on: var(--sc-color-warning-subtle);
2439
+ --_fg-on: var(--sc-color-warning-text);
2440
+ --_bd-on: var(--sc-color-warning-solid);
2441
+ }
2442
+ .sc-chip[data-tone='danger'] {
2443
+ --_fg: var(--sc-color-danger-text);
2444
+ --_bd: var(--sc-color-danger-text);
2445
+ --_bg-hover: var(--sc-color-danger-subtle);
2446
+ --_bg-on: var(--sc-color-danger-subtle);
2447
+ --_fg-on: var(--sc-color-danger-text);
2448
+ --_bd-on: var(--sc-color-danger-solid);
2449
+ }
2450
+ .sc-chip[data-tone='info'] {
2451
+ --_fg: var(--sc-color-info-text);
2452
+ --_bd: var(--sc-color-info-text);
2453
+ --_bg-hover: var(--sc-color-info-subtle);
2454
+ --_bg-on: var(--sc-color-info-subtle);
2455
+ --_fg-on: var(--sc-color-info-text);
2456
+ --_bd-on: var(--sc-color-info-solid);
2457
+ }
2458
+ @media (prefers-reduced-motion: reduce) {
2459
+ .sc-chip {
2460
+ transition: none;
2461
+ }
2462
+ }
2463
+
2464
+ /* ---- disclosure.css ---- */
2465
+ /* ---- Disclosure ------------------------------------------------------------ */
2466
+ .sc-disclosure {
2467
+ display: flex;
2468
+ flex-direction: column;
2469
+ gap: var(--sc-spacing-xs);
2470
+ min-inline-size: 0;
2471
+ font-family: var(--sc-font-family-sans);
2472
+ font-size: var(--sc-font-size-sm);
2473
+ line-height: var(--sc-font-line-height-normal);
2474
+ color: var(--sc-color-text-default);
2475
+ }
2476
+ .sc-disclosure__summary {
2477
+ display: inline-flex;
2478
+ align-items: center;
2479
+ gap: var(--sc-spacing-2xs);
2480
+ inline-size: fit-content;
2481
+ margin-inline: calc(-1 * var(--sc-spacing-2xs));
2482
+ padding: var(--sc-spacing-2xs);
2483
+ border-radius: var(--sc-radius-sm);
2484
+ color: var(--sc-color-accent-text);
2485
+ font-weight: var(--sc-font-weight-medium);
2486
+ line-height: var(--sc-font-line-height-ui);
2487
+ list-style: none;
2488
+ cursor: pointer;
2489
+ user-select: none;
2490
+ }
2491
+ .sc-disclosure__summary::-webkit-details-marker,
2492
+ .sc-disclosure__summary::marker {
2493
+ display: none;
2494
+ content: '';
2495
+ }
2496
+ .sc-disclosure__summary:hover {
2497
+ background: var(--sc-color-surface-hover);
2498
+ }
2499
+ .sc-disclosure__summary:focus-visible {
2500
+ outline: var(--sc-border-width-focus) solid var(--sc-color-border-focus);
2501
+ outline-offset: 0;
2502
+ }
2503
+ .sc-disclosure__chevron {
2504
+ flex: none;
2505
+ inline-size: var(--sc-size-icon-md);
2506
+ block-size: var(--sc-size-icon-md);
2507
+ transition: rotate var(--sc-duration-fast) var(--sc-ease-standard);
2508
+ }
2509
+ .sc-disclosure[open] > .sc-disclosure__summary > .sc-disclosure__chevron {
2510
+ rotate: 180deg;
2511
+ }
2512
+ .sc-disclosure[data-summary-position='end'] > .sc-disclosure__summary {
2513
+ order: 1;
2514
+ }
2515
+ .sc-disclosure__content {
2516
+ min-inline-size: 0;
2517
+ }
2518
+ /* Preview: while closed, the content stays rendered, clipped to N lines and faded. Browsers without
2519
+ `::details-content` keep the native behaviour (content hidden until open). */
2520
+ .sc-disclosure[data-preview]:not([open])::details-content {
2521
+ content-visibility: visible;
2522
+ display: block;
2523
+ max-block-size: calc(var(--_lines, 3) * 1lh);
2524
+ overflow: clip;
2525
+ mask-image: linear-gradient(to bottom, #000 40%, transparent 100%);
2526
+ }
2527
+ @media (prefers-reduced-motion: reduce) {
2528
+ .sc-disclosure__chevron {
2529
+ transition: none;
2530
+ }
2531
+ }
2532
+
2533
+ /* ---- empty-state.css ---- */
2534
+ /* ---- EmptyState ------------------------------------------------------------ */
2535
+ .sc-empty-state {
2536
+ --_icon: var(--sc-size-icon-xl);
2537
+ --_ring: 48px;
2538
+ --_py: var(--sc-spacing-2xl);
2539
+ --_title: var(--sc-font-size-lg);
2540
+ display: flex;
2541
+ flex-direction: column;
2542
+ align-items: center;
2543
+ gap: var(--sc-spacing-xs);
2544
+ box-sizing: border-box;
2545
+ inline-size: 100%;
2546
+ margin: 0;
2547
+ padding: var(--_py) var(--sc-spacing-lg);
2548
+ list-style: none;
2549
+ text-align: center;
2550
+ font-family: var(--sc-font-family-sans);
2551
+ color: var(--sc-color-text-default);
2552
+ }
2553
+ .sc-empty-state[data-size='sm'] {
2554
+ --_icon: var(--sc-size-icon-lg);
2555
+ --_ring: 40px;
2556
+ --_py: var(--sc-spacing-lg);
2557
+ --_title: var(--sc-font-size-md);
2558
+ gap: var(--sc-spacing-2xs);
2559
+ }
2560
+ .sc-empty-state__icon {
2561
+ display: inline-grid;
2562
+ place-items: center;
2563
+ inline-size: var(--_ring);
2564
+ block-size: var(--_ring);
2565
+ margin-block-end: var(--sc-spacing-xs);
2566
+ border-radius: var(--sc-radius-full);
2567
+ background: var(--sc-color-surface-sunken);
2568
+ color: var(--sc-color-text-muted);
2569
+ }
2570
+ .sc-empty-state__icon > svg {
2571
+ inline-size: var(--_icon);
2572
+ block-size: var(--_icon);
2573
+ }
2574
+ .sc-empty-state__title {
2575
+ margin: 0;
2576
+ max-inline-size: 36ch;
2577
+ font-size: var(--_title);
2578
+ font-weight: var(--sc-font-weight-semibold);
2579
+ line-height: var(--sc-font-line-height-snug);
2580
+ letter-spacing: var(--sc-font-tracking-snug);
2581
+ text-wrap: balance;
2582
+ }
2583
+ .sc-empty-state__description {
2584
+ margin: 0;
2585
+ max-inline-size: 48ch;
2586
+ font-size: var(--sc-font-size-sm);
2587
+ line-height: var(--sc-font-line-height-normal);
2588
+ color: var(--sc-color-text-muted);
2589
+ text-wrap: pretty;
2590
+ }
2591
+ .sc-empty-state__actions {
2592
+ display: flex;
2593
+ flex-wrap: wrap;
2594
+ justify-content: center;
2595
+ gap: var(--sc-spacing-xs);
2596
+ margin-block-start: var(--sc-spacing-sm);
2597
+ }
2598
+
2599
+ /* ---- skeleton.css ---- */
2600
+ /* ---- Skeleton -------------------------------------------------------------- */
2601
+ .sc-skeleton {
2602
+ --_base: var(--sc-color-surface-active);
2603
+ --_sheen: var(--sc-color-surface-hover);
2604
+ display: block;
2605
+ box-sizing: border-box;
2606
+ inline-size: 100%;
2607
+ block-size: 1em;
2608
+ border-radius: var(--sc-radius-sm);
2609
+ background: var(--_base);
2610
+ background-image: linear-gradient(90deg, var(--_base) 0%, var(--_sheen) 50%, var(--_base) 100%);
2611
+ background-size: 200% 100%;
2612
+ animation: sc-shimmer 1.6s ease-in-out infinite;
2613
+ }
2614
+ .sc-skeleton[data-variant='text'] {
2615
+ display: inline-block;
2616
+ vertical-align: middle;
2617
+ block-size: 1em;
2618
+ border-radius: var(--sc-radius-sm);
2619
+ }
2620
+ .sc-skeleton[data-variant='rect'] {
2621
+ block-size: 80px;
2622
+ border-radius: var(--sc-radius-md);
2623
+ }
2624
+ .sc-skeleton[data-variant='circle'] {
2625
+ inline-size: 40px;
2626
+ aspect-ratio: 1;
2627
+ block-size: auto;
2628
+ border-radius: var(--sc-radius-full);
2629
+ }
2630
+ .sc-skeleton[data-still] {
2631
+ animation: none;
2632
+ background-image: none;
2633
+ }
2634
+ .sc-skeleton-lines {
2635
+ display: flex;
2636
+ flex-direction: column;
2637
+ gap: calc(1lh - 1em);
2638
+ inline-size: 100%;
2639
+ }
2640
+ .sc-skeleton-lines > .sc-skeleton {
2641
+ display: block;
2642
+ }
2643
+ .sc-skeleton-lines > .sc-skeleton[data-last] {
2644
+ inline-size: 60%;
2645
+ }
2646
+ @keyframes sc-shimmer {
2647
+ from {
2648
+ background-position: 200% 0;
2649
+ }
2650
+ to {
2651
+ background-position: -200% 0;
2652
+ }
2653
+ }
2654
+ @media (prefers-reduced-motion: reduce) {
2655
+ .sc-skeleton {
2656
+ animation: none;
2657
+ background-image: none;
2658
+ }
2659
+ }
2660
+
2117
2661
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@salemcobalt/ui",
3
- "version": "0.2.0-rc.3",
4
- "description": "React components for the Salem Cobalt design system: Button, IconButton, Icon set, Badge, Card, Stack, Inline, Kbd, Dialog, Tooltip, Menu, Toolbar, Banner, Spinner, Progress, Tabs, Input, Textarea, Select, Checkbox, Switch, Heading, Text, Table, Stat.",
3
+ "version": "0.2.0-rc.5",
4
+ "description": "React components for the Salem Cobalt design system: Button, IconButton, Icon set, Badge, Card, Stack, Inline, Kbd, Dialog, Tooltip, Menu, Toolbar, Banner, Spinner, Progress, Tabs, Input, Textarea, Select, Checkbox, Switch, Heading, Text, Table, Stat, Chip, Disclosure, EmptyState, Skeleton.",
5
5
  "license": "MIT",
6
6
  "repository": {
7
7
  "type": "git",
@@ -33,7 +33,7 @@
33
33
  "peerDependencies": {
34
34
  "react": "^19.0.0",
35
35
  "react-dom": "^19.0.0",
36
- "@salemcobalt/tokens": "^0.2.0-rc.3"
36
+ "@salemcobalt/tokens": "^0.2.0-rc.5"
37
37
  },
38
38
  "dependencies": {
39
39
  "@base-ui/react": "^1.9.0",
@@ -56,7 +56,7 @@
56
56
  "tsup": "^9.0.0",
57
57
  "typescript": "^5.9.3",
58
58
  "vitest": "^5.0.5",
59
- "@salemcobalt/tokens": "^0.2.0-rc.3"
59
+ "@salemcobalt/tokens": "^0.2.0-rc.5"
60
60
  },
61
61
  "publishConfig": {
62
62
  "access": "public"