@crewlethq/ui 0.37.1 → 0.38.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 (60) hide show
  1. package/README.md +34 -0
  2. package/dist/Accordion/index.js +1 -1
  3. package/dist/AgentHandoffPanel/index.js +4 -4
  4. package/dist/AppShell/index.js +1 -1
  5. package/dist/{AppShell-JBCZSSX3.css → AppShell-NDU4XMGF.css} +39 -6
  6. package/dist/ArtifactCard/index.js +2 -2
  7. package/dist/ArtifactMakeRow/ArtifactMakeRow.d.ts +3 -1
  8. package/dist/ArtifactMakeRow/index.js +1 -1
  9. package/dist/{ArtifactMakeRow-W3RD5YWZ.css → ArtifactMakeRow-6UX2LTF7.css} +43 -5
  10. package/dist/AuthLayout/index.js +2 -2
  11. package/dist/Card/index.js +1 -1
  12. package/dist/{Card-QOVASQNU.css → Card-G2ZGT5Z6.css} +43 -0
  13. package/dist/CommandPalette/index.js +2 -2
  14. package/dist/CommentThread/index.js +3 -3
  15. package/dist/Composer/index.js +2 -2
  16. package/dist/DataView/index.js +2 -2
  17. package/dist/DatasetSource/index.js +2 -2
  18. package/dist/DescriptionList/DescriptionList.d.ts +12 -1
  19. package/dist/DescriptionList/index.js +1 -1
  20. package/dist/{DescriptionList-IXMRCSMK.css → DescriptionList-DEZISDLQ.css} +8 -1
  21. package/dist/Disclosure/index.js +1 -1
  22. package/dist/{Disclosure-VKBJJIZ7.css → Disclosure-P4FH3C35.css} +28 -2
  23. package/dist/ListInput/index.js +2 -2
  24. package/dist/PricingCard/index.js +2 -2
  25. package/dist/SheetColumnEditor/index.js +3 -3
  26. package/dist/SheetGrid/index.js +2 -2
  27. package/dist/StatGroup/StatGroup.d.ts +11 -7
  28. package/dist/StatGroup/index.js +1 -1
  29. package/dist/StatGroup-DOFHX5QJ.css +168 -0
  30. package/dist/TableCells/index.js +2 -2
  31. package/dist/Tag/index.js +1 -1
  32. package/dist/{Tag-SRGTK5KI.css → Tag-2DQOVE6W.css} +15 -5
  33. package/dist/TagsInput/index.js +2 -2
  34. package/dist/{chunk-K4VP6ZKE.js → chunk-4BJK7FE5.js} +1 -1
  35. package/dist/{chunk-3SBM4DGI.js → chunk-BH52LIY6.js} +1 -1
  36. package/dist/{chunk-WX2NIG4G.js → chunk-BJI3RFXG.js} +1 -1
  37. package/dist/{chunk-JXRI5YD2.js → chunk-BT5H2THK.js} +2 -1
  38. package/dist/{chunk-HDHZWIFL.js → chunk-DYB66CNM.js} +16 -2
  39. package/dist/{chunk-HMLAWVG6.js → chunk-IPWU6ERC.js} +1 -1
  40. package/dist/{chunk-DZSBFITC.js → chunk-JZPK4IXR.js} +1 -1
  41. package/dist/{chunk-GFV4LJHH.js → chunk-KYIAFNU7.js} +1 -1
  42. package/dist/{chunk-F2XSYBKH.js → chunk-MFS6F2P7.js} +4 -1
  43. package/dist/{chunk-MICH6QSJ.js → chunk-OGXHZHRX.js} +1 -1
  44. package/dist/{chunk-OHA6WSAG.js → chunk-OTCXRJ7D.js} +1 -1
  45. package/dist/{chunk-MMPKN7WV.js → chunk-PT6WKXKW.js} +1 -1
  46. package/dist/{chunk-NS4NSHVX.js → chunk-R2IBCEU6.js} +12 -2
  47. package/dist/{chunk-DQSXWQMJ.js → chunk-U3ILLCR2.js} +1 -1
  48. package/dist/{chunk-YSG3DW7W.js → chunk-XBURIXHO.js} +2 -2
  49. package/dist/{chunk-5QXRI35B.js → chunk-ZK3VYY7L.js} +1 -1
  50. package/dist/{chunk-RIAZM6L3.js → chunk-ZNOXQACX.js} +1 -1
  51. package/dist/generated/index.js +42 -42
  52. package/dist/index.js +42 -42
  53. package/dist/styles.css +285 -46
  54. package/package.json +3 -3
  55. package/dist/StatGroup-PADTJCUQ.css +0 -86
  56. package/dist/{chunk-DOLATMGF.js → chunk-3ZUINC7C.js} +1 -1
  57. package/dist/{chunk-F3WZ5AKM.js → chunk-4L2BWSHR.js} +1 -1
  58. package/dist/{chunk-ISA2O2BK.js → chunk-ETVEGR2Y.js} +1 -1
  59. package/dist/{chunk-A72JPXIV.js → chunk-PAQXOP2M.js} +1 -1
  60. package/dist/{chunk-MG3HTY6F.js → chunk-YQG4PZGC.js} +1 -1
package/dist/styles.css CHANGED
@@ -702,7 +702,7 @@
702
702
  }
703
703
 
704
704
 
705
- /* AppShell-JBCZSSX3.css */
705
+ /* AppShell-NDU4XMGF.css */
706
706
  /*
707
707
  * The application frame: a rail on the FRAME, and the screen on a SHEET that
708
708
  * floats beside it.
@@ -886,7 +886,9 @@
886
886
  * compact density cannot take the target under it.
887
887
  *
888
888
  * And the boundary is TRANSPARENT rather than absent, spending one pixel of
889
- * that step rather than adding one on top of it. A button carries one at every
889
+ * that step rather than adding one on top of it. It spends a pixel of the row
890
+ * pad too: added to it, the boundary stood the row's mark and words a pixel
891
+ * right of every nav glyph and word above them. A button carries one at every
890
892
  * variant so that a bordered variant and a borderless one stand the same
891
893
  * height, and the row this package draws carries the same one for the same
892
894
  * reason: without it the two rows in one foot are 34px and 36px, and the
@@ -901,7 +903,7 @@
901
903
  width: 100%;
902
904
  min-width: 0;
903
905
  min-height: var(--size-row-sm);
904
- padding: calc(var(--spacing-2) - 1px) var(--size-nav-row-pad);
906
+ padding: calc(var(--spacing-2) - 1px) calc(var(--size-nav-row-pad) - 1px);
905
907
  border: 1px solid transparent;
906
908
  border-radius: var(--radius-md);
907
909
  background: transparent;
@@ -1132,13 +1134,22 @@
1132
1134
  overflow: hidden;
1133
1135
  }
1134
1136
 
1137
+ /*
1138
+ * THE BAR'S INSET IS THE CONTENT'S, so a page's first line starts under the
1139
+ * bar's title and its cards end under the bar's last control. It stood 16px
1140
+ * from each edge over a content column inset 20px, and at its end the
1141
+ * content also gives up the scroller's gutter, which the bar, not scrolling,
1142
+ * did not: with scrollbars drawn in the layout every page's actions ended
1143
+ * 15px past the cards under them. The gutter is measured by the shell
1144
+ * (`--crewlet-app-shell-gutter`, 0 where scrollbars overlay the content).
1145
+ */
1135
1146
  .crewlet-app-shell__topbar {
1136
1147
  display: flex;
1137
1148
  align-items: center;
1138
1149
  gap: var(--spacing-3);
1139
1150
  flex: none;
1140
1151
  height: var(--crewlet-app-shell-topbar);
1141
- padding: 0 var(--spacing-4);
1152
+ padding: 0 calc(var(--spacing-5) + var(--crewlet-app-shell-gutter, 0px)) 0 var(--spacing-5);
1142
1153
  border-bottom: 1px solid var(--color-border-default);
1143
1154
  background: var(--color-surface-background);
1144
1155
  }
@@ -1321,7 +1332,12 @@
1321
1332
  }
1322
1333
 
1323
1334
  /* THE TOP BAR'S GUTTER, 16px: the content's 12px stood every page's first
1324
- line 4px left of the title and the controls over it. */
1335
+ line 4px left of the title and the controls over it. The bar and the
1336
+ content take it together. */
1337
+ .crewlet-app-shell__topbar {
1338
+ padding: 0 calc(var(--spacing-4) + var(--crewlet-app-shell-gutter, 0px)) 0 var(--spacing-4);
1339
+ }
1340
+
1325
1341
  .crewlet-app-shell__content {
1326
1342
  padding: var(--spacing-4) var(--spacing-4) var(--spacing-9);
1327
1343
  }
@@ -1367,10 +1383,27 @@
1367
1383
  transition: background var(--motion-duration-fast) var(--motion-easing-default);
1368
1384
  }
1369
1385
 
1370
- /* In the rail's foot, the account row reaches up across its own padding to
1371
- half the foot's gap, to meet the row above (HitArea.css). */
1386
+ /*
1387
+ * In the rail's foot, the account row reaches up across its own padding to
1388
+ * half the foot's gap, to meet the row above (HitArea.css).
1389
+ *
1390
+ * AND IT STANDS ON THE NAV'S COLUMNS: the avatar centred on the column every
1391
+ * nav glyph is centred on, and the name starting on the line every nav word
1392
+ * starts on. On a 4px inset with an 8px gap a 26px avatar stood 2px left of
1393
+ * the glyphs above it and the name 2px right of their words. The avatar's box
1394
+ * takes a nav glyph's width (`sm`, 14px) and the badge is centred over it, so
1395
+ * whatever size of badge a caller hands the row, it is centred where a glyph
1396
+ * is, and the row takes the nav row's pad and its glyph-to-word gap.
1397
+ */
1372
1398
  .crewlet-app-shell__rail-foot .crewlet-account-row__who {
1373
1399
  --crewlet-hit-area-block-start: calc(var(--crewlet-rail-foot-gap) / 2 + var(--crewlet-account-row-pad));
1400
+ gap: calc(var(--spacing-2) + var(--spacing-1) / 2);
1401
+ padding-inline-start: var(--size-nav-row-pad);
1402
+ }
1403
+
1404
+ .crewlet-app-shell__rail-foot .crewlet-account-row__avatar {
1405
+ justify-content: center;
1406
+ width: 14px;
1374
1407
  }
1375
1408
 
1376
1409
  /* The row as the reader's menu button: a button drawn as the link is. */
@@ -3311,7 +3344,7 @@ a.crewlet-kind-tile:hover .crewlet-kind-tile__frame,
3311
3344
  .crewlet-kind--sheet { --crewlet-kind-hue: var(--color-artifact-kind-sheet); --crewlet-kind-fill: var(--color-artifact-kind-sheet-fill); --crewlet-kind-line: var(--color-artifact-kind-sheet-line); --crewlet-kind-ink: var(--color-artifact-kind-sheet-ink); }
3312
3345
 
3313
3346
 
3314
- /* ArtifactMakeRow-W3RD5YWZ.css */
3347
+ /* ArtifactMakeRow-6UX2LTF7.css */
3315
3348
  /*
3316
3349
  * The "Start a new artifact" tray.
3317
3350
  *
@@ -3322,9 +3355,16 @@ a.crewlet-kind-tile:hover .crewlet-kind-tile__frame,
3322
3355
  *
3323
3356
  * THE TRAY SIZES ITSELF BY ITS OWN WIDTH, never the window's: it sits in a
3324
3357
  * page column a sidebar narrows, so three steps are container queries on the
3325
- * tray. Under 560px three across in two lines; from 560px the six in one
3326
- * line, each its mark over its name, so a long name is never cut; from 920px
3327
- * the mark beside the name and what the kind is for under it.
3358
+ * tray. Under 560px three across, each its mark over its name; from 560px
3359
+ * every kind in one line, still mark over name, so a long name is never cut;
3360
+ * from 920px the mark beside the name and what the kind is for under it.
3361
+ *
3362
+ * AND BY ITS OWN COUNT. A reader is offered the kinds their company runs, so
3363
+ * a tray holds five as often as six, and a grid fixed at six columns left an
3364
+ * empty sixth of dotted field at the end of the line, and three across left a
3365
+ * hole after the fifth. The line takes one column per kind
3366
+ * (`--crewlet-make-row-count`, set from the items), and the narrow tray fills
3367
+ * its rows by the count (`data-count`): see the narrow step below.
3328
3368
  */
3329
3369
 
3330
3370
  .crewlet-make-row {
@@ -3342,7 +3382,7 @@ a.crewlet-kind-tile:hover .crewlet-kind-tile__frame,
3342
3382
  .crewlet-make-row__list {
3343
3383
  --crewlet-make-row-gap: var(--spacing-1);
3344
3384
  display: grid;
3345
- grid-template-columns: repeat(3, minmax(0, 1fr));
3385
+ grid-template-columns: repeat(6, minmax(0, 1fr));
3346
3386
  gap: var(--crewlet-make-row-gap);
3347
3387
  margin: 0;
3348
3388
  padding: var(--spacing-1);
@@ -3423,9 +3463,40 @@ a.crewlet-kind-tile:hover .crewlet-kind-tile__frame,
3423
3463
  line-height: 1.35;
3424
3464
  }
3425
3465
 
3466
+ /*
3467
+ * THE NARROW TRAY, on six tracks, each kind two of them: three a row. A last
3468
+ * row that is short is centred under the full one rather than left with a
3469
+ * hole after it, so five kinds stand three and two, the two in the middle.
3470
+ * Two and four kinds stand two a row, which fills every row, and one kind
3471
+ * takes the tray.
3472
+ */
3473
+ @container (width < 560px) {
3474
+ .crewlet-make-row__cell {
3475
+ grid-column: span 2;
3476
+ }
3477
+
3478
+ /* One kind short of a full last row: the first of the two moves in a track. */
3479
+ .crewlet-make-row__cell:nth-child(3n + 1):nth-last-child(2) {
3480
+ grid-column: 2 / span 2;
3481
+ }
3482
+
3483
+ /* A last row of one stands in the middle. */
3484
+ .crewlet-make-row__cell:nth-child(3n + 1):last-child {
3485
+ grid-column: 3 / span 2;
3486
+ }
3487
+
3488
+ .crewlet-make-row__list:is([data-count='2'], [data-count='4']) > .crewlet-make-row__cell {
3489
+ grid-column: span 3;
3490
+ }
3491
+
3492
+ .crewlet-make-row__list[data-count='1'] > .crewlet-make-row__cell {
3493
+ grid-column: span 6;
3494
+ }
3495
+ }
3496
+
3426
3497
  @container (width >= 560px) {
3427
3498
  .crewlet-make-row__list {
3428
- grid-template-columns: repeat(6, minmax(0, 1fr));
3499
+ grid-template-columns: repeat(var(--crewlet-make-row-count, 6), minmax(0, 1fr));
3429
3500
  }
3430
3501
 
3431
3502
  .crewlet-make-row__item {
@@ -6195,7 +6266,7 @@ a.crewlet-breadcrumb__crumb:focus-visible {
6195
6266
  }
6196
6267
 
6197
6268
 
6198
- /* Card-QOVASQNU.css */
6269
+ /* Card-G2ZGT5Z6.css */
6199
6270
  /*
6200
6271
  * Card, THE surface. Everything on a screen is a card, a row inside one, or a
6201
6272
  * control.
@@ -6650,6 +6721,49 @@ a.crewlet-breadcrumb__crumb:focus-visible {
6650
6721
  min-width: 0;
6651
6722
  }
6652
6723
 
6724
+ /*
6725
+ * ON A NARROW CARD THE SUBTITLE TAKES A LINE OF ITS OWN, under the title and
6726
+ * the card's controls, and wraps there rather than ending.
6727
+ *
6728
+ * One line is right while the subtitle has room to say something beside the
6729
+ * title. In a card under 480px wide it had none: on a phone an Agent seats
6730
+ * card drew "Resets today at midnight, the week…" in 202px of a 361px
6731
+ * sentence, and the half it cut was the half that said when. On its own line
6732
+ * the subtitle has the head's whole width, and the title and the controls
6733
+ * keep the first.
6734
+ *
6735
+ * THE CARD IS THE CONTAINER, and only a card whose head has a subtitle, since
6736
+ * that is the one card this changes. Inline-size containment takes a card's
6737
+ * width from where it stands, never from its contents, which is how a panel
6738
+ * is laid out anyway; a card that sized itself to its contents (a tile in a
6739
+ * row that does not stretch it) and carried no subtitle is untouched.
6740
+ *
6741
+ * THE NAME BLOCK TAKES THE FIRST LINE'S ROOM rather than its own width. With
6742
+ * the row free to wrap, a title wider than what the controls leave would
6743
+ * otherwise push the controls onto a second line; from a zero basis it grows
6744
+ * into the room they leave and clips there, exactly as the one-line head does.
6745
+ */
6746
+ .crewlet-card:has(> .crewlet-card__header > .crewlet-card__subtitle) {
6747
+ container: crewlet-card / inline-size;
6748
+ }
6749
+
6750
+ @container crewlet-card (width < 480px) {
6751
+ .crewlet-card__header:has(> .crewlet-card__subtitle) {
6752
+ flex-wrap: wrap;
6753
+ row-gap: var(--spacing-1);
6754
+ }
6755
+
6756
+ .crewlet-card__header:has(> .crewlet-card__subtitle) > .crewlet-card__header-main {
6757
+ flex: 1 1 0;
6758
+ }
6759
+
6760
+ .crewlet-card__header > .crewlet-card__subtitle {
6761
+ order: 1;
6762
+ flex: 1 1 100%;
6763
+ white-space: normal;
6764
+ }
6765
+ }
6766
+
6653
6767
  .crewlet-card__description {
6654
6768
  margin: 0;
6655
6769
  font-size: var(--font-size-compact);
@@ -12393,18 +12507,25 @@ svg.crewlet-datetime__chevron {
12393
12507
  }
12394
12508
 
12395
12509
 
12396
- /* DescriptionList-IXMRCSMK.css */
12510
+ /* DescriptionList-DEZISDLQ.css */
12397
12511
  /*
12398
12512
  * Metadata pairs on one grid.
12399
12513
  *
12400
12514
  * The term track is `minmax(120px, max-content)`: wide enough that short terms
12401
12515
  * line up with each other, and free to grow for a long one rather than
12402
12516
  * wrapping it into two lines beside a one-word value.
12517
+ *
12518
+ * ONE LIST'S TRACK IS ITS OWN, which is wrong for a page of them. Four cards
12519
+ * of limits stacked on one page each sized the column to their own longest
12520
+ * term, so their values started at four different places and the cards did
12521
+ * not read as one table. `--crewlet-description-list-term` names the track
12522
+ * instead, and it is inherited: set once on the page (or passed to each list
12523
+ * as `termWidth`), every list under it shares one column.
12403
12524
  */
12404
12525
 
12405
12526
  .crewlet-description-list {
12406
12527
  display: grid;
12407
- grid-template-columns: minmax(120px, max-content) 1fr;
12528
+ grid-template-columns: var(--crewlet-description-list-term, minmax(120px, max-content)) 1fr;
12408
12529
  gap: var(--spacing-2) var(--spacing-4);
12409
12530
  margin: 0;
12410
12531
  font-size: var(--font-size-compact);
@@ -12670,7 +12791,7 @@ svg.crewlet-datetime__chevron {
12670
12791
  }
12671
12792
 
12672
12793
 
12673
- /* Disclosure-VKBJJIZ7.css */
12794
+ /* Disclosure-P4FH3C35.css */
12674
12795
  /*
12675
12796
  * The disclosure anatomy, declared once for every expander in the package.
12676
12797
  *
@@ -12788,9 +12909,35 @@ svg.crewlet-datetime__chevron {
12788
12909
  font-variant-ligatures: none;
12789
12910
  }
12790
12911
 
12791
- /* A fact inside the button: quieter than the title it belongs to. */
12912
+ /*
12913
+ * A fact inside the button: quieter than the title it belongs to, and the
12914
+ * first thing to give up room when the row runs short.
12915
+ *
12916
+ * IT USED TO TAKE NONE. `flex: none` held a fact at its full width while the
12917
+ * title, which may shrink, was the only thing that could, so a long fact (a
12918
+ * log's replay mode, generation, range and size, beside a status badge in the
12919
+ * actions) took the whole trigger: the title shrank to nothing, so a row no
12920
+ * longer said which log it was, and the fact ran out of the button and under
12921
+ * the badge beside it.
12922
+ *
12923
+ * A HUNDRED TO THE TITLE'S ONE, as a card's subtitle gives way to its title:
12924
+ * two items that may shrink give up space in proportion to their widths, so
12925
+ * at that ratio the fact absorbs effectively all of it, and ends in an
12926
+ * ellipsis, before the title gives up a pixel. The fact is still the button's
12927
+ * name in full; only its drawing is cut.
12928
+ *
12929
+ * NEVER TO NOTHING. The floor is one glyph wide, because a fact is often a
12930
+ * mark (a failed call's glyph beside a tool's name), and a mark that shrank
12931
+ * to nothing would say nothing at all. A long fact keeps an ellipsis there,
12932
+ * which says a fact was cut. Once the fact is at its floor the title shrinks
12933
+ * and ends in its own ellipsis.
12934
+ */
12792
12935
  .crewlet-disclosure__meta {
12793
- flex: none;
12936
+ flex: 0 100 auto;
12937
+ min-width: 1.5em;
12938
+ overflow: hidden;
12939
+ text-overflow: ellipsis;
12940
+ white-space: nowrap;
12794
12941
  color: var(--color-text-tertiary);
12795
12942
  font-size: var(--font-size-xs);
12796
12943
  }
@@ -25690,7 +25837,7 @@ svg.crewlet-select__chevron {
25690
25837
  .crewlet-statcard--info .crewlet-statcard__value { color: var(--color-feedback-info-ink); }
25691
25838
 
25692
25839
 
25693
- /* StatGroup-PADTJCUQ.css */
25840
+ /* StatGroup-DOFHX5QJ.css */
25694
25841
  /*
25695
25842
  * A row of stat tiles.
25696
25843
  *
@@ -25698,11 +25845,29 @@ svg.crewlet-select__chevron {
25698
25845
  * tiles appeared and vanished moved every number on the page for a reason that
25699
25846
  * had nothing to do with the numbers, which is exactly what a reader watching
25700
25847
  * a live board is trying not to have happen.
25848
+ *
25849
+ * IT FOLDS BY ITS OWN WIDTH, never the window's. The row used to drop to two
25850
+ * columns under a 1024px viewport, but a row's width is whatever its column
25851
+ * leaves it: beside the rail and a settings column at exactly 1024 a
25852
+ * four-column row was 489px wide, its tiles about 120px each, and its figures
25853
+ * were cut ("Not s…", "1.6 …"), while on a phone a three-column row folded to
25854
+ * two and left its third tile alone on a row of its own. So the row is a size
25855
+ * container, and the tiles take their place from the row's own width.
25856
+ *
25857
+ * TWELVE TRACKS, AND EACH TILE SPANS ITS SHARE. A container query styles what
25858
+ * is inside the container, never the container itself, so the row cannot
25859
+ * change its own column count by its own width. Its tiles can change how many
25860
+ * of its twelve tracks they span, which is the same layout: twelve divides by
25861
+ * every count a row takes (one, two, three and four a row).
25862
+ *
25863
+ * The row's width comes from where it stands, as a block's does: inline-size
25864
+ * containment means its contents never widen it.
25701
25865
  */
25702
25866
 
25703
25867
  .crewlet-stat-group {
25868
+ container: crewlet-stat-group / inline-size;
25704
25869
  display: grid;
25705
- grid-template-columns: repeat(var(--crewlet-stat-group-cols, 4), minmax(0, 1fr));
25870
+ grid-template-columns: repeat(12, minmax(0, 1fr));
25706
25871
  /* The flush-panel recipe: the card's surface, its hairline and its 12px
25707
25872
  corner, flat as every card is, and `overflow: hidden`, which is what lets
25708
25873
  the tiles inside sit against the corners without their own hairlines
@@ -25713,8 +25878,19 @@ svg.crewlet-select__chevron {
25713
25878
  overflow: hidden;
25714
25879
  }
25715
25880
 
25716
- /* Inside another card: the card's surface and edge are the row's. */
25717
- .crewlet-stat-group--flush {
25881
+ /*
25882
+ * Inside another card: the card's surface and edge are the row's.
25883
+ *
25884
+ * A ROW STANDING IN A CARD IS FLUSH WHETHER OR NOT ITS CALLER SAID SO. Six
25885
+ * settings pages wrapped a row in a card without `flush`, and each drew the
25886
+ * row's own edge and 12px corner one pixel inside the card's: a box inside a
25887
+ * box, and inside a padded body a third frame. A row that is a card's content,
25888
+ * or its body's, is that card's row; `flush` is for a host that is not a
25889
+ * Card (a widget's frame, a panel of an application's own).
25890
+ */
25891
+ .crewlet-stat-group--flush,
25892
+ .crewlet-card > .crewlet-stat-group,
25893
+ .crewlet-card__body > .crewlet-stat-group {
25718
25894
  background: transparent;
25719
25895
  border: 0;
25720
25896
  border-radius: var(--radius-none);
@@ -25740,40 +25916,93 @@ svg.crewlet-select__chevron {
25740
25916
  }
25741
25917
 
25742
25918
  /*
25743
- * A hairline between columns, drawn on the tile that follows one.
25919
+ * Each tile spans its share of the twelve tracks: the row's `columns`, set on
25920
+ * it as `--crewlet-stat-group-cols`, a row.
25921
+ */
25922
+ .crewlet-stat-group > * {
25923
+ grid-column: span calc(12 / var(--crewlet-stat-group-cols, 4));
25924
+ }
25925
+
25926
+ /*
25927
+ * The hairlines between tiles: one before every tile that does not start a
25928
+ * row, and one above every tile that is not on the first.
25744
25929
  *
25745
25930
  * NAMED TWICE, ON PURPOSE. The rule above clears the tile's own border and
25746
25931
  * weighs two classes, so a one-class selector here loses to it and the row
25747
25932
  * of numbers runs together with nothing between the columns. The first
25748
- * selector matches whatever a caller puts in the row; the second weighs the
25749
- * same as the rule it has to beat, and sits after it.
25933
+ * selector of each pair matches whatever a caller puts in the row; the second
25934
+ * weighs at least as much as the rule it has to beat, and sits after it.
25750
25935
  */
25751
25936
  .crewlet-stat-group > * + *,
25752
25937
  .crewlet-stat-group > .crewlet-statcard + .crewlet-statcard {
25753
25938
  border-left: 1px solid var(--color-border-default);
25754
25939
  }
25755
25940
 
25941
+ .crewlet-stat-group[data-columns='2'] > :nth-child(2n + 1),
25942
+ .crewlet-stat-group[data-columns='2'] > .crewlet-statcard:nth-child(2n + 1),
25943
+ .crewlet-stat-group[data-columns='3'] > :nth-child(3n + 1),
25944
+ .crewlet-stat-group[data-columns='3'] > .crewlet-statcard:nth-child(3n + 1),
25945
+ .crewlet-stat-group[data-columns='4'] > :nth-child(4n + 1),
25946
+ .crewlet-stat-group[data-columns='4'] > .crewlet-statcard:nth-child(4n + 1) {
25947
+ border-left: 0;
25948
+ }
25949
+
25950
+ .crewlet-stat-group[data-columns='2'] > :nth-child(n + 3),
25951
+ .crewlet-stat-group[data-columns='2'] > .crewlet-statcard:nth-child(n + 3),
25952
+ .crewlet-stat-group[data-columns='3'] > :nth-child(n + 4),
25953
+ .crewlet-stat-group[data-columns='3'] > .crewlet-statcard:nth-child(n + 4),
25954
+ .crewlet-stat-group[data-columns='4'] > :nth-child(n + 5),
25955
+ .crewlet-stat-group[data-columns='4'] > .crewlet-statcard:nth-child(n + 5) {
25956
+ border-top: 1px solid var(--color-border-default);
25957
+ }
25958
+
25756
25959
  /*
25757
- * Two columns under the shell breakpoint, which is where the engine drops its
25758
- * own stat row, and strictly under it, as the shell switches. The step is
25759
- * 1024px, a 236px rail, the 8px inset and a 780px floor for the sheet, and it
25760
- * is the width at which the shell stops holding the page beside the rail. The
25761
- * rules are written for the general case rather than per column count: the
25762
- * first tile of each pair loses its left hairline, and everything on the
25763
- * second row and below gains a top one.
25960
+ * FOUR A ROW FOLD TO TWO under 640px of row (the phone breakpoint's number):
25961
+ * four tiles of 160px is the narrowest at which a six-character figure and a
25962
+ * two-word label still stand on one line each. Two by two keeps every row
25963
+ * full.
25764
25964
  */
25765
- @media (width < 1024px) {
25766
- .crewlet-stat-group {
25767
- grid-template-columns: repeat(2, minmax(0, 1fr));
25965
+ @container crewlet-stat-group (width < 640px) {
25966
+ .crewlet-stat-group[data-columns='4'] > *,
25967
+ .crewlet-stat-group[data-columns='4'] > .crewlet-statcard {
25968
+ grid-column: span 6;
25768
25969
  }
25769
25970
 
25770
- .crewlet-stat-group > *:nth-child(odd),
25771
- .crewlet-stat-group > .crewlet-statcard:nth-child(odd) {
25971
+ .crewlet-stat-group[data-columns='4'] > :nth-child(odd),
25972
+ .crewlet-stat-group[data-columns='4'] > .crewlet-statcard:nth-child(odd) {
25772
25973
  border-left: 0;
25773
25974
  }
25774
25975
 
25775
- .crewlet-stat-group > *:nth-child(n + 3),
25776
- .crewlet-stat-group > .crewlet-statcard:nth-child(n + 3) {
25976
+ .crewlet-stat-group[data-columns='4'] > :nth-child(even),
25977
+ .crewlet-stat-group[data-columns='4'] > .crewlet-statcard:nth-child(even) {
25978
+ border-left: 1px solid var(--color-border-default);
25979
+ }
25980
+
25981
+ .crewlet-stat-group[data-columns='4'] > :nth-child(n + 3),
25982
+ .crewlet-stat-group[data-columns='4'] > .crewlet-statcard:nth-child(n + 3) {
25983
+ border-top: 1px solid var(--color-border-default);
25984
+ }
25985
+ }
25986
+
25987
+ /*
25988
+ * THREE A ROW STACK under 480px of row (the small breakpoint's number), at the
25989
+ * same 160px a tile. Folded to two, three tiles stood two and one, the last
25990
+ * alone at double width and a different height, which read as a tile that had
25991
+ * failed to load; one a row leaves no row short.
25992
+ */
25993
+ @container crewlet-stat-group (width < 480px) {
25994
+ .crewlet-stat-group[data-columns='3'] > *,
25995
+ .crewlet-stat-group[data-columns='3'] > .crewlet-statcard {
25996
+ grid-column: span 12;
25997
+ }
25998
+
25999
+ .crewlet-stat-group[data-columns='3'] > *,
26000
+ .crewlet-stat-group[data-columns='3'] > .crewlet-statcard + .crewlet-statcard {
26001
+ border-left: 0;
26002
+ }
26003
+
26004
+ .crewlet-stat-group[data-columns='3'] > :nth-child(n + 2),
26005
+ .crewlet-stat-group[data-columns='3'] > .crewlet-statcard:nth-child(n + 2) {
25777
26006
  border-top: 1px solid var(--color-border-default);
25778
26007
  }
25779
26008
  }
@@ -27405,7 +27634,7 @@ b.crewlet-switcher__match {
27405
27634
  }
27406
27635
 
27407
27636
 
27408
- /* Tag-SRGTK5KI.css */
27637
+ /* Tag-2DQOVE6W.css */
27409
27638
  /*
27410
27639
  * The tag: a small pill naming a state, a category or a value.
27411
27640
  *
@@ -27685,12 +27914,22 @@ b.crewlet-switcher__match {
27685
27914
  --crewlet-tag-line: var(--color-border-strong-hover);
27686
27915
  }
27687
27916
 
27688
- /* The neutral outline is the engine's `.badge.outline`: the hairline step as
27689
- the boundary, and the tertiary ink, which is a quieter register than the
27690
- tinted outlines keep. It is the appearance for a value that is not a state
27691
- at all, so it says less than its neighbours on purpose. */
27917
+ /*
27918
+ * The neutral outline: the neutral pill's own boundary with no fill, and the
27919
+ * tertiary ink, which is a quieter register than the tinted outlines keep. It
27920
+ * is the appearance for a value that is not a state at all, so it says less
27921
+ * than its neighbours on purpose, by its ink and its empty ground.
27922
+ *
27923
+ * NOT BY A FAINTER EDGE. It used to take the plain hairline, the line that
27924
+ * finds a card, and on the card it so often stands on that line measured
27925
+ * 1.07:1 in dark: Limits' "Off" beside a filled "Default", an audit row's
27926
+ * machine and open, a tool's "builtin", all read as loose words rather than
27927
+ * as pills. The strong step is the edge the neutral soft pill already draws
27928
+ * (1.49:1 dark, 1.52:1 light on the card), so the two neutral pills differ by
27929
+ * their fill alone and both read as pills.
27930
+ */
27692
27931
  .crewlet-tag--neutral.crewlet-tag--outline {
27693
- border-color: var(--color-border-default);
27932
+ border-color: var(--color-border-strong);
27694
27933
  --crewlet-tag-ink: var(--color-text-tertiary);
27695
27934
  }
27696
27935
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@crewlethq/ui",
3
- "version": "0.37.1",
3
+ "version": "0.38.0",
4
4
  "description": "Crewlet shared React components built on @crewlethq/tokens and @crewlethq/icons.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -42,8 +42,8 @@
42
42
  "clean": "rm -rf dist src/generated"
43
43
  },
44
44
  "dependencies": {
45
- "@crewlethq/icons": "0.37.1",
46
- "@crewlethq/tokens": "0.37.1",
45
+ "@crewlethq/icons": "0.38.0",
46
+ "@crewlethq/tokens": "0.38.0",
47
47
  "prosemirror-commands": "1.7.2",
48
48
  "prosemirror-gapcursor": "1.4.1",
49
49
  "prosemirror-history": "1.5.1",
@@ -1,86 +0,0 @@
1
- /*
2
- * A row of stat tiles.
3
- *
4
- * ITS COLUMN COUNT NEVER MOVES with its contents. A grid that reflowed as
5
- * tiles appeared and vanished moved every number on the page for a reason that
6
- * had nothing to do with the numbers, which is exactly what a reader watching
7
- * a live board is trying not to have happen.
8
- */
9
-
10
- .crewlet-stat-group {
11
- display: grid;
12
- grid-template-columns: repeat(var(--crewlet-stat-group-cols, 4), minmax(0, 1fr));
13
- /* The flush-panel recipe: the card's surface, its hairline and its 12px
14
- corner, flat as every card is, and `overflow: hidden`, which is what lets
15
- the tiles inside sit against the corners without their own hairlines
16
- escaping past them. */
17
- background: var(--color-surface-subtle);
18
- border: 1px solid var(--color-border-default);
19
- border-radius: var(--radius-lg);
20
- overflow: hidden;
21
- }
22
-
23
- /* Inside another card: the card's surface and edge are the row's. */
24
- .crewlet-stat-group--flush {
25
- background: transparent;
26
- border: 0;
27
- border-radius: var(--radius-none);
28
- }
29
-
30
- /*
31
- * A tile inside the row brings no surface of its own, whether or not its
32
- * caller remembered `flush`. The group draws one card and the hairlines
33
- * inside it, so a tile that kept its own border and radius is a card inside
34
- * a card: a box inside a box, which is what the reader sees.
35
- *
36
- * TWO CLASSES, NOT :where(). Written as `> :where(.crewlet-statcard)` this
37
- * weighed exactly what the tile's own `.crewlet-statcard` rule weighs, so
38
- * which one painted was settled by whichever stylesheet the bundler put
39
- * last. It put the tile's last, and every tile in every group drew its own
40
- * border, its own 12px corner and its own surface inside the group's.
41
- * Naming both classes settles it by weight, which no import order can undo.
42
- */
43
- .crewlet-stat-group > .crewlet-statcard {
44
- background: transparent;
45
- border: 0;
46
- border-radius: var(--radius-none);
47
- }
48
-
49
- /*
50
- * A hairline between columns, drawn on the tile that follows one.
51
- *
52
- * NAMED TWICE, ON PURPOSE. The rule above clears the tile's own border and
53
- * weighs two classes, so a one-class selector here loses to it and the row
54
- * of numbers runs together with nothing between the columns. The first
55
- * selector matches whatever a caller puts in the row; the second weighs the
56
- * same as the rule it has to beat, and sits after it.
57
- */
58
- .crewlet-stat-group > * + *,
59
- .crewlet-stat-group > .crewlet-statcard + .crewlet-statcard {
60
- border-left: 1px solid var(--color-border-default);
61
- }
62
-
63
- /*
64
- * Two columns under the shell breakpoint, which is where the engine drops its
65
- * own stat row, and strictly under it, as the shell switches. The step is
66
- * 1024px, a 236px rail, the 8px inset and a 780px floor for the sheet, and it
67
- * is the width at which the shell stops holding the page beside the rail. The
68
- * rules are written for the general case rather than per column count: the
69
- * first tile of each pair loses its left hairline, and everything on the
70
- * second row and below gains a top one.
71
- */
72
- @media (width < 1024px) {
73
- .crewlet-stat-group {
74
- grid-template-columns: repeat(2, minmax(0, 1fr));
75
- }
76
-
77
- .crewlet-stat-group > *:nth-child(odd),
78
- .crewlet-stat-group > .crewlet-statcard:nth-child(odd) {
79
- border-left: 0;
80
- }
81
-
82
- .crewlet-stat-group > *:nth-child(n + 3),
83
- .crewlet-stat-group > .crewlet-statcard:nth-child(n + 3) {
84
- border-top: 1px solid var(--color-border-default);
85
- }
86
- }
@@ -1,5 +1,5 @@
1
- import { FormField, Textarea, Input } from './chunk-TYONQSOK.js';
2
1
  import { Kbd } from './chunk-SMBKXWML.js';
2
+ import { FormField, Textarea, Input } from './chunk-TYONQSOK.js';
3
3
  import { announce } from './chunk-RSAQOKH3.js';
4
4
  import { isComposing } from './chunk-H5XTJ7GJ.js';
5
5
  import { IconButton } from './chunk-4FQT6ZAY.js';
@@ -3,8 +3,8 @@ import { SHEET_LABELS, SHEET_COLUMN_TYPES, optionHue, retypeColumn } from './chu
3
3
  import { HueSwatch } from './chunk-F4LPQA4E.js';
4
4
  import { NODE_HUES, NODE_HUE_NAMES } from './chunk-AYKXMIOR.js';
5
5
  import { Checkbox } from './chunk-AXS6MBNH.js';
6
- import { FormField, Input } from './chunk-TYONQSOK.js';
7
6
  import { Kbd } from './chunk-SMBKXWML.js';
7
+ import { FormField, Input } from './chunk-TYONQSOK.js';
8
8
  import { Menu } from './chunk-D6FEHY5G.js';
9
9
  import { Button } from './chunk-OG6CL3EB.js';
10
10
  import { IconButton } from './chunk-4FQT6ZAY.js';
@@ -1,5 +1,5 @@
1
- import { Textarea } from './chunk-TYONQSOK.js';
2
1
  import { Kbd } from './chunk-SMBKXWML.js';
2
+ import { Textarea } from './chunk-TYONQSOK.js';
3
3
  import { cx } from './chunk-ODEQTPFM.js';
4
4
  import './Composer-TXULCPPV.css';
5
5
  import { forwardRef } from 'react';
@@ -1,7 +1,7 @@
1
1
  import { Modal } from './chunk-SVGARBDY.js';
2
2
  import { useListbox, useHighlightRest } from './chunk-7KHM2FZH.js';
3
- import { Input } from './chunk-TYONQSOK.js';
4
3
  import { Kbd } from './chunk-SMBKXWML.js';
4
+ import { Input } from './chunk-TYONQSOK.js';
5
5
  import { Count } from './chunk-BHHIIK3M.js';
6
6
  import { isComposing } from './chunk-H5XTJ7GJ.js';
7
7
  import { HIT_AREA_CLASS } from './chunk-2YTOOH3A.js';
@@ -5,8 +5,8 @@ import { useListbox, useOptionKeys } from './chunk-7KHM2FZH.js';
5
5
  import { Popover } from './chunk-KHJIEPZV.js';
6
6
  import { Toolbar } from './chunk-NR4CPM4T.js';
7
7
  import { RelativeTime } from './chunk-3CZ7XAVY.js';
8
- import { Input } from './chunk-TYONQSOK.js';
9
8
  import { Kbd } from './chunk-SMBKXWML.js';
9
+ import { Input } from './chunk-TYONQSOK.js';
10
10
  import { Count } from './chunk-BHHIIK3M.js';
11
11
  import { Menu } from './chunk-D6FEHY5G.js';
12
12
  import { Button } from './chunk-OG6CL3EB.js';