@crewlethq/ui 0.4.3 → 0.5.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 (237) hide show
  1. package/README.md +888 -24
  2. package/dist/Accordion/index.js +2 -2
  3. package/dist/AddPill/index.js +1 -1
  4. package/dist/{AddPill-DFWXYLIQ.css → AddPill-IJQYCY6C.css} +9 -0
  5. package/dist/AppShell/AppShell.d.ts +26 -5
  6. package/dist/AppShell/index.js +3 -3
  7. package/dist/{AppShell-NVE6LHNI.css → AppShell-XARELGIH.css} +178 -25
  8. package/dist/Avatar/Avatar.d.ts +85 -40
  9. package/dist/Avatar/AvatarStack.d.ts +76 -0
  10. package/dist/Avatar/index.d.ts +5 -2
  11. package/dist/Avatar/index.js +1 -1
  12. package/dist/Avatar-XID7Z74C.css +200 -0
  13. package/dist/AvatarStack-GEJBNV7E.css +72 -0
  14. package/dist/BrandLockup/index.js +1 -1
  15. package/dist/{BrandLockup-6ISDEHPJ.css → BrandLockup-JKGXFCZF.css} +25 -19
  16. package/dist/Button/Button.d.ts +7 -2
  17. package/dist/Button/index.js +1 -1
  18. package/dist/{Button-D4J6B4MA.css → Button-X4B2TJAQ.css} +50 -19
  19. package/dist/Callout/index.js +1 -1
  20. package/dist/Canvas/index.js +4 -4
  21. package/dist/Card/Card.d.ts +9 -5
  22. package/dist/Card/index.js +1 -1
  23. package/dist/{Card-RLR254LD.css → Card-GLP7SUV6.css} +25 -18
  24. package/dist/Charts/BarList.d.ts +18 -1
  25. package/dist/Charts/ChartTooltip.d.ts +68 -0
  26. package/dist/Charts/StackedBar.d.ts +25 -7
  27. package/dist/Charts/StackedColumns.d.ts +112 -0
  28. package/dist/Charts/TimeSeries.d.ts +33 -2
  29. package/dist/Charts/dataColor.d.ts +22 -14
  30. package/dist/Charts/index.d.ts +6 -0
  31. package/dist/Charts/index.js +1 -1
  32. package/dist/Charts/useChartHover.d.ts +56 -0
  33. package/dist/Charts-B3YEF7R4.css +742 -0
  34. package/dist/Checkbox/index.js +1 -1
  35. package/dist/{Checkbox-VGW26YLQ.css → Checkbox-BOXQ747I.css} +2 -2
  36. package/dist/CodeBlock/index.js +4 -4
  37. package/dist/Combobox/index.js +5 -5
  38. package/dist/CommandPalette/CommandPalette.d.ts +97 -6
  39. package/dist/CommandPalette/index.d.ts +1 -1
  40. package/dist/CommandPalette/index.js +9 -7
  41. package/dist/CommandPalette-C5AMKGN2.css +259 -0
  42. package/dist/Copyable/index.js +3 -3
  43. package/dist/DataTable/index.js +7 -7
  44. package/dist/{DataTable-ITNACQ2X.css → DataTable-OLHPF7D4.css} +44 -43
  45. package/dist/DataView/index.js +14 -14
  46. package/dist/{DataView-256YF32J.css → DataView-N6JX464S.css} +5 -4
  47. package/dist/DateTimePicker/index.js +5 -5
  48. package/dist/DiffList/index.js +1 -1
  49. package/dist/Disclosure/index.js +2 -2
  50. package/dist/EntityChip/EntityChip.d.ts +9 -12
  51. package/dist/EntityChip/index.d.ts +1 -1
  52. package/dist/EntityChip/index.js +2 -2
  53. package/dist/ErrorBoundary/index.js +2 -2
  54. package/dist/{ErrorBoundary-ME36CQTA.css → ErrorBoundary-U2PA3LY2.css} +4 -4
  55. package/dist/IconButton/index.js +1 -1
  56. package/dist/{IconButton-VQGNMJDI.css → IconButton-TVEUWK6L.css} +2 -2
  57. package/dist/ImageUpload/ImageUpload.d.ts +10 -7
  58. package/dist/ImageUpload/index.js +2 -2
  59. package/dist/{ImageUpload-HKFIZR6D.css → ImageUpload-YCHJMUGX.css} +24 -10
  60. package/dist/Input/index.js +2 -2
  61. package/dist/Kbd/Kbd.d.ts +14 -4
  62. package/dist/Kbd/index.js +1 -1
  63. package/dist/Kbd-JPLDVJIP.css +71 -0
  64. package/dist/Layer/index.js +1 -1
  65. package/dist/Link/index.js +1 -1
  66. package/dist/List/index.js +1 -1
  67. package/dist/{List-XTHESXLR.css → List-MYJIV6MP.css} +12 -2
  68. package/dist/ListInput/index.js +5 -5
  69. package/dist/Listbox/index.js +2 -2
  70. package/dist/Listbox/useListbox.d.ts +16 -0
  71. package/dist/Listbox/useOptionKeys.d.ts +12 -1
  72. package/dist/{Listbox-X2DOTSQA.css → Listbox-6WJNJQVQ.css} +60 -7
  73. package/dist/Menu/index.js +4 -4
  74. package/dist/{Menu-6DE7I66I.css → Menu-BT5PMFJI.css} +15 -0
  75. package/dist/Meter/Meter.d.ts +103 -16
  76. package/dist/Meter/index.d.ts +2 -2
  77. package/dist/Meter/index.js +1 -1
  78. package/dist/{Meter-SKOOXQBC.css → Meter-5VCSFMZW.css} +46 -7
  79. package/dist/Modal/index.js +4 -4
  80. package/dist/{Modal-XYQJ4BL6.css → Modal-JAYBS2KS.css} +13 -4
  81. package/dist/OrgLabel/OrgLabel.d.ts +60 -24
  82. package/dist/OrgLabel/index.d.ts +1 -1
  83. package/dist/OrgLabel/index.js +2 -1
  84. package/dist/{OrgLabel-D7U6QJZD.css → OrgLabel-CR233G34.css} +9 -18
  85. package/dist/OrgNode/index.js +3 -2
  86. package/dist/OrgTable/OrgTable.d.ts +2 -2
  87. package/dist/OrgTable/index.js +8 -7
  88. package/dist/Popover/index.js +2 -2
  89. package/dist/PricingCard/index.js +3 -3
  90. package/dist/{PricingCard-JFI7RYXP.css → PricingCard-7EFXRSD2.css} +4 -5
  91. package/dist/SearchTrigger/SearchTrigger.d.ts +23 -4
  92. package/dist/SearchTrigger/index.d.ts +1 -1
  93. package/dist/SearchTrigger/index.js +1 -1
  94. package/dist/SearchTrigger-Z5D4AAY7.css +112 -0
  95. package/dist/SegmentedControl/index.js +2 -2
  96. package/dist/SegmentedMeter/SegmentedMeter.d.ts +107 -0
  97. package/dist/SegmentedMeter/index.d.ts +3 -0
  98. package/dist/SegmentedMeter/index.js +2 -0
  99. package/dist/SegmentedMeter-KQNML2TW.css +109 -0
  100. package/dist/Select/index.js +3 -3
  101. package/dist/{Select-2X77FSWR.css → Select-E24U5LBC.css} +34 -0
  102. package/dist/Shortcut/index.js +2 -2
  103. package/dist/SidebarNav/SidebarNav.d.ts +85 -25
  104. package/dist/SidebarNav/index.d.ts +1 -1
  105. package/dist/SidebarNav/index.js +1 -1
  106. package/dist/SidebarNav-X5NLZNWA.css +424 -0
  107. package/dist/StatCard/StatCard.d.ts +59 -12
  108. package/dist/StatCard/index.d.ts +1 -1
  109. package/dist/StatCard/index.js +1 -1
  110. package/dist/StatCard-KPAFD4E2.css +204 -0
  111. package/dist/StatGroup/index.js +1 -1
  112. package/dist/{StatGroup-TGB6AEKM.css → StatGroup-HVG6O62W.css} +8 -9
  113. package/dist/StatusDot/StatusDot.d.ts +24 -6
  114. package/dist/StatusDot/index.js +1 -1
  115. package/dist/StatusDot-7OMCQCZF.css +186 -0
  116. package/dist/Stepper/Stepper.d.ts +78 -0
  117. package/dist/Stepper/index.d.ts +3 -0
  118. package/dist/Stepper/index.js +4 -0
  119. package/dist/Stepper-HW4JM3YH.css +176 -0
  120. package/dist/Table/index.js +1 -1
  121. package/dist/{Table-MDOLVUAW.css → Table-TGCS4C3F.css} +14 -4
  122. package/dist/Tabs/index.js +1 -1
  123. package/dist/{Tabs-VLICJFVB.css → Tabs-XCNPHA7B.css} +79 -27
  124. package/dist/Tag/Tag.d.ts +29 -22
  125. package/dist/Tag/index.js +2 -2
  126. package/dist/{Tag-VNZEYLB6.css → Tag-GBE7LQJP.css} +82 -83
  127. package/dist/TagsInput/index.js +6 -6
  128. package/dist/ThemeSwitcher/ThemeSwitcher.d.ts +53 -21
  129. package/dist/ThemeSwitcher/index.d.ts +3 -3
  130. package/dist/ThemeSwitcher/index.js +4 -3
  131. package/dist/ThemeSwitcher/preferences.d.ts +19 -5
  132. package/dist/ThemeToggle/ThemeToggle.d.ts +40 -0
  133. package/dist/ThemeToggle/index.d.ts +2 -0
  134. package/dist/ThemeToggle/index.js +5 -0
  135. package/dist/TimeWindowPicker/index.js +8 -8
  136. package/dist/Toaster/index.js +2 -2
  137. package/dist/Toolbar/index.js +2 -2
  138. package/dist/{Toolbar-IP6LXN45.css → Toolbar-HUOSMNTH.css} +3 -1
  139. package/dist/Tooltip/index.js +2 -2
  140. package/dist/Tree/index.d.ts +2 -2
  141. package/dist/Tree/index.js +1 -1
  142. package/dist/Tree/layout.d.ts +103 -28
  143. package/dist/TreeCanvas/TreeCanvas.d.ts +60 -14
  144. package/dist/TreeCanvas/index.d.ts +1 -1
  145. package/dist/TreeCanvas/index.js +6 -6
  146. package/dist/TreeCanvas/motion.d.ts +3 -2
  147. package/dist/{TreeCanvas-WBNQPHC7.css → TreeCanvas-HVOV4SQN.css} +154 -30
  148. package/dist/TreeGrid/index.js +4 -4
  149. package/dist/{chunk-F6OE5FH3.js → chunk-2FPENTCF.js} +1 -1
  150. package/dist/chunk-4AK52VHB.js +88 -0
  151. package/dist/{chunk-7EM5T4ME.js → chunk-4IQD3HUQ.js} +2 -2
  152. package/dist/{chunk-YODNNSZL.js → chunk-4PZ6FJKW.js} +43 -13
  153. package/dist/{chunk-F27EPQ7D.js → chunk-4UQ7SMPK.js} +1 -1
  154. package/dist/chunk-5QWIJSQM.js +73 -0
  155. package/dist/{chunk-GTOUGQQK.js → chunk-6MU7HNB4.js} +13 -10
  156. package/dist/{chunk-S2XHHEW4.js → chunk-74KMX7YH.js} +4 -4
  157. package/dist/{chunk-WNI2WSJF.js → chunk-7KBNFFM3.js} +1 -1
  158. package/dist/{chunk-DD5BBGBE.js → chunk-AUS5FNQE.js} +9 -5
  159. package/dist/{chunk-CMEE37QJ.js → chunk-BMYPGGPV.js} +4 -4
  160. package/dist/{chunk-H4FBTAYS.js → chunk-BNCCEER3.js} +8 -8
  161. package/dist/chunk-C5WJUZVR.js +56 -0
  162. package/dist/{chunk-5WS6L6FA.js → chunk-CAIHUYXV.js} +9 -9
  163. package/dist/{chunk-XV6WRMBC.js → chunk-CQY5NTRS.js} +4 -1
  164. package/dist/{chunk-UOGSZKLT.js → chunk-D6EVJUGU.js} +2 -2
  165. package/dist/{chunk-6ZFVFA56.js → chunk-DHPUMOTX.js} +2 -2
  166. package/dist/{chunk-HZ5XZNPS.js → chunk-DS2C73RJ.js} +3 -3
  167. package/dist/{chunk-O6232G37.js → chunk-DSUY5F4E.js} +17 -5
  168. package/dist/{chunk-Q4ZPPART.js → chunk-EFYPAJT3.js} +3 -3
  169. package/dist/{chunk-WQX73TWF.js → chunk-ERVO6OUF.js} +18 -17
  170. package/dist/{chunk-BZYDZBAN.js → chunk-ETYEBKR4.js} +3 -3
  171. package/dist/{chunk-34VGEDVV.js → chunk-FD5UEN6X.js} +30 -30
  172. package/dist/{chunk-5SDBMKUO.js → chunk-FIFNP6PL.js} +3 -3
  173. package/dist/{chunk-7HPRF5XN.js → chunk-FUF52K7E.js} +98 -16
  174. package/dist/{chunk-5KPQ6D7N.js → chunk-FZVJDJFN.js} +2 -2
  175. package/dist/chunk-IA232OTU.js +156 -0
  176. package/dist/{chunk-2EOKFKHX.js → chunk-IG27QX7Q.js} +7 -7
  177. package/dist/chunk-IKB6HFGK.js +55 -0
  178. package/dist/{chunk-FBZAKNSX.js → chunk-IPVQKAHO.js} +10 -7
  179. package/dist/{chunk-3EYF6HKB.js → chunk-IVFJD7WY.js} +28 -9
  180. package/dist/{chunk-WOYYD2YR.js → chunk-JGRNTBF2.js} +11 -11
  181. package/dist/chunk-K3OWD7BJ.js +121 -0
  182. package/dist/{chunk-BJSKPEZI.js → chunk-KD4H66L6.js} +7 -20
  183. package/dist/{chunk-SFZOKW2G.js → chunk-KJ34ZBBI.js} +8 -3
  184. package/dist/{chunk-HQNHV7D6.js → chunk-LFHCXZO5.js} +6 -6
  185. package/dist/{chunk-LWKJQTOM.js → chunk-MICH6QSJ.js} +1 -1
  186. package/dist/chunk-N3DPO6HG.js +226 -0
  187. package/dist/{chunk-S4GZWSKR.js → chunk-OM5E3TTK.js} +1 -1
  188. package/dist/{chunk-3QRYCPXQ.js → chunk-OPKIKM35.js} +6 -6
  189. package/dist/{chunk-5EKIWVOR.js → chunk-PGRPNDWM.js} +2 -2
  190. package/dist/{chunk-LFJ6UJTI.js → chunk-PQNILU27.js} +9 -9
  191. package/dist/{chunk-QNCVHRZL.js → chunk-QVAFL2LE.js} +1 -1
  192. package/dist/{chunk-QEUY3A5P.js → chunk-QY7UU5ZB.js} +3 -2
  193. package/dist/{chunk-ITHXJHBB.js → chunk-R25RGPUB.js} +1 -0
  194. package/dist/{chunk-KLJCCMF3.js → chunk-R6735B37.js} +2 -2
  195. package/dist/{chunk-3ZP55QZE.js → chunk-R6FBDTP3.js} +4 -4
  196. package/dist/{chunk-7FZ53WDJ.js → chunk-RIAZM6L3.js} +1 -1
  197. package/dist/chunk-RJM4QCGG.js +550 -0
  198. package/dist/{chunk-NTRZGNEX.js → chunk-S3BCVWTU.js} +215 -46
  199. package/dist/chunk-S7KW47IQ.js +121 -0
  200. package/dist/{chunk-OFHBK7RI.js → chunk-SJQ546ID.js} +34 -14
  201. package/dist/{chunk-D35VTV2Z.js → chunk-SV7QAONL.js} +1 -1
  202. package/dist/{chunk-IAJLHVUA.js → chunk-TIWAHZZ6.js} +1 -1
  203. package/dist/{chunk-2PRH365R.js → chunk-UA7O3KKJ.js} +1 -1
  204. package/dist/{chunk-NPZY6YYL.js → chunk-UG5ZMAXW.js} +6 -6
  205. package/dist/{chunk-FEFTGVMF.js → chunk-V2N3BMOT.js} +7 -2
  206. package/dist/{chunk-NDCATSW7.js → chunk-V34H2YCY.js} +1 -1
  207. package/dist/chunk-WIATRXEJ.js +22 -0
  208. package/dist/{chunk-5C5YMZQU.js → chunk-WOFOMTGB.js} +16 -10
  209. package/dist/{chunk-QYOFACSP.js → chunk-WSOFKOLP.js} +3 -3
  210. package/dist/{chunk-MNAXYY3R.js → chunk-WUVZDFHS.js} +31 -11
  211. package/dist/{chunk-UG46QBLT.js → chunk-YIMOT5OO.js} +10 -10
  212. package/dist/{chunk-2ZQMA2WB.js → chunk-ZPSOF6VL.js} +2 -2
  213. package/dist/generated/index.d.ts +3 -0
  214. package/dist/generated/index.js +66 -62
  215. package/dist/index.js +66 -62
  216. package/dist/styles.css +2719 -799
  217. package/dist/utils/index.d.ts +1 -1
  218. package/dist/utils/tone.d.ts +7 -12
  219. package/package.json +4 -4
  220. package/scripts/check-css-literals.mjs +159 -23
  221. package/scripts/check-css-variables.mjs +5 -3
  222. package/scripts/css-source.mjs +97 -5
  223. package/dist/Avatar-P2KRQM2B.css +0 -156
  224. package/dist/Charts-D7G2BSXH.css +0 -277
  225. package/dist/CommandPalette-CSJDUCQA.css +0 -115
  226. package/dist/Kbd-W66MXQI5.css +0 -61
  227. package/dist/SearchTrigger-QXOYAUUY.css +0 -79
  228. package/dist/SidebarNav-QGSFKZYA.css +0 -319
  229. package/dist/StatCard-KYPKZUWX.css +0 -111
  230. package/dist/StatusDot-HA2L2FSX.css +0 -84
  231. package/dist/chunk-22O7LAW2.js +0 -41
  232. package/dist/chunk-2HQR4U4D.js +0 -143
  233. package/dist/chunk-ESCO4XYW.js +0 -144
  234. package/dist/chunk-F4PJZ4ED.js +0 -245
  235. package/dist/chunk-PNFASD6F.js +0 -98
  236. package/dist/chunk-PZSWF74H.js +0 -15
  237. /package/dist/{chunk-ZCR6YGQ4.js → chunk-PKIN4IMB.js} +0 -0
@@ -13,15 +13,54 @@ import type { HTMLAttributes, ReactNode } from 'react';
13
13
  * number is never that.
14
14
  */
15
15
  export type StatCardTone = 'neutral' | 'success' | 'warning' | 'danger' | 'info';
16
+ /**
17
+ * Whether a change is the one the reader wanted.
18
+ *
19
+ * NOT the direction. The sign in the value already says which way the number
20
+ * moved, and whether up is good is a property of what is counted rather than
21
+ * of the arithmetic: twelve percent more work completed is good news and
22
+ * twelve percent more tokens spent may not be. So the caller, who knows what
23
+ * the tile counts, says which it is, and `neutral` is a change that is neither
24
+ * (four more tasks in progress is not a verdict, it is a fact).
25
+ */
26
+ export type StatCardDeltaPolarity = 'good' | 'bad' | 'neutral';
27
+ /** A change against an earlier reading, drawn at the head of the second line. */
28
+ export interface StatCardDelta {
29
+ /** The change, already formatted by the caller and carrying its own sign: "+12%", "−3", "+4". */
30
+ value: ReactNode;
31
+ /** Whether it is the change the reader wanted. See the type. */
32
+ polarity: StatCardDeltaPolarity;
33
+ }
16
34
  export interface StatCardProps extends HTMLAttributes<HTMLDivElement> {
17
- /** What is being counted, for example "Total tokens". */
35
+ /** What is being counted, in sentence case: "Tasks in progress". */
18
36
  label: ReactNode;
19
37
  /** The headline value, already formatted by the caller. */
20
38
  value: ReactNode;
21
- /** A unit after the value, at a quieter weight: "ms", "/ 20K", "per turn". */
39
+ /** A unit after the value, at a quieter weight: "ms", "/ 7", "per turn". */
22
40
  unit?: ReactNode;
23
- /** A second line under the label: "3 working, 4 idle". Its line is reserved either way. */
41
+ /** The second line: "vs last week · 2 blocked". Its line is reserved either way. */
24
42
  sub?: ReactNode;
43
+ /**
44
+ * The STATE the second line reports, when it reports one: "Oldest waiting
45
+ * 2h 10m" is a person being kept waiting, so it is `warning`. Paints the
46
+ * line in that tone's ink, the step measured as text on every rung. The
47
+ * same rule as `tone`: most second lines are a fact, not a state, and stay
48
+ * in the quiet ink. A `delta` keeps the ink of its own polarity.
49
+ */
50
+ subTone?: StatCardTone;
51
+ /**
52
+ * A change against an earlier reading, drawn first on the second line in
53
+ * the ink of its polarity, with `sub` after it: "+12% vs previous 7 days".
54
+ */
55
+ delta?: StatCardDelta | undefined;
56
+ /**
57
+ * A small figure at the end of the value's line, such as a `Sparkline`, a
58
+ * `Meter` or a `SegmentedMeter`, or a small control that acts on the
59
+ * number. A figure fills the slot's width and a control keeps its own. The
60
+ * slot is `--crewlet-statcard-trend-width` wide, 96px unless a stylesheet
61
+ * says otherwise.
62
+ */
63
+ trend?: ReactNode;
25
64
  /** A glyph before the label. A component, not a name. */
26
65
  icon?: ReactNode;
27
66
  /** Colours the VALUE's ink. See the type for when that is right. */
@@ -39,18 +78,26 @@ export interface StatCardProps extends HTMLAttributes<HTMLDivElement> {
39
78
  /**
40
79
  * One number, with what it counts.
41
80
  *
42
- * THE LABEL SITS ABOVE THE VALUE, in the micro-caps register, which is the
43
- * engine's order and the one a board is actually read in: the labels are what
44
- * a reader scans to find the tile they want, and the number is the answer
45
- * underneath it. It is also the order a screen reader reads correctly, "live
46
- * nodes, four, holding an unexpired lease" rather than "four, live nodes".
47
- * The numbers still sit on one line across the row, because the label register
48
- * is one line at every tile and the value box is a fixed step.
81
+ * THE LABEL SITS ABOVE THE VALUE, in sentence case at the caption step, which
82
+ * is the approved design's tile and the order a board is actually read in:
83
+ * the labels are what a reader scans to find the tile they want, and the
84
+ * number is the answer underneath it. It is also the order a screen reader
85
+ * reads correctly, "tasks in progress, 18, +4 vs last week" rather than "18,
86
+ * tasks in progress". The label is set as it is written: the uppercased,
87
+ * tracked-open register is a table's column head, and five of them over five
88
+ * numbers shouted a heading at every tile.
89
+ *
90
+ * THE VALUE IS THE SCREEN'S ONE DISPLAY NUMBER, at `--font-size-display` with
91
+ * tabular figures, so a number that ticks up moves nothing beside it. A
92
+ * figure showing where it has been going sits at the END of the same line
93
+ * (`trend`), and a change against an earlier reading heads the line under it
94
+ * (`delta`), in the ink of whether it was the change the reader wanted.
49
95
  *
50
96
  * WHILE IT IS LOADING IT SAYS SO. It used to draw a literal `--`, which a
51
97
  * screen reader reads aloud as "dash dash" and which looks exactly like a
52
98
  * measured value of nothing. A placeholder line plus `aria-busy` on the tile
53
99
  * says the number has not arrived, which is a different fact from the number
54
- * being zero.
100
+ * being zero. The trend and the delta wait with it: both are readings of the
101
+ * number that has not arrived.
55
102
  */
56
- export declare const StatCard: ({ label, value, unit, sub, icon, tone, loading, loadingLabel, flush, className, ...rest }: StatCardProps) => import("react").JSX.Element;
103
+ export declare const StatCard: ({ label, value, unit, sub, subTone, delta, trend, icon, tone, loading, loadingLabel, flush, className, ...rest }: StatCardProps) => import("react").JSX.Element;
@@ -1,3 +1,3 @@
1
1
  import './StatCard.css';
2
2
  export { StatCard } from './StatCard.js';
3
- export type { StatCardProps, StatCardTone } from './StatCard.js';
3
+ export type { StatCardDelta, StatCardDeltaPolarity, StatCardProps, StatCardTone } from './StatCard.js';
@@ -1,3 +1,3 @@
1
- export { StatCard } from '../chunk-22O7LAW2.js';
1
+ export { StatCard } from '../chunk-IKB6HFGK.js';
2
2
  import '../chunk-BZFWDIV6.js';
3
3
  import '../chunk-ODEQTPFM.js';
@@ -0,0 +1,204 @@
1
+ /*
2
+ * The stat tile.
3
+ *
4
+ * THE TONE PAINTS THE VALUE, which is what the props always said and what the
5
+ * stylesheet never did: 0.2.0 tinted the ICON, so a caller who passed a tone
6
+ * and no icon got a tile identical to a neutral one. Ink only, and never a
7
+ * fill: a tinted block behind a 28px number reads as a button.
8
+ */
9
+
10
+ .crewlet-statcard {
11
+ /*
12
+ * The width of the figure at the end of the value's line. 96px is the
13
+ * approved design's sparkline, and its meters and state bars stand within
14
+ * four pixels of it: wide enough that a fortnight of points reads as a
15
+ * shape, narrow enough that five tiles in a row still leave the number its
16
+ * room.
17
+ */
18
+ --crewlet-statcard-trend-width: 96px;
19
+
20
+ display: flex;
21
+ flex-direction: column;
22
+ /* The design's 10px between the three lines, and its 16px inset with 14px
23
+ under the last line: half a scale step each, derived from the steps so
24
+ they follow the density with everything else. */
25
+ gap: calc(var(--spacing-2) + var(--spacing-1) / 2);
26
+ padding: var(--spacing-4) var(--spacing-4) calc(var(--spacing-3) + var(--spacing-1) / 2);
27
+ /*
28
+ * The card recipe: the card's surface, its hairline and its 12px corner,
29
+ * FLAT, as every card is, so a lone tile is the same object as the panel
30
+ * beside it rather than a raised cousin of it.
31
+ */
32
+ background: var(--color-surface-subtle);
33
+ border: 1px solid var(--color-border-default);
34
+ border-radius: var(--radius-lg);
35
+ color: var(--color-text-primary);
36
+ font-family: var(--font-family-sans);
37
+ min-width: 0;
38
+ }
39
+
40
+ /* Inside a StatGroup the row is one card and the tiles are its columns, so a
41
+ tile brings no surface of its own. */
42
+ .crewlet-statcard--flush {
43
+ background: transparent;
44
+ border: 0;
45
+ border-radius: var(--radius-none);
46
+ }
47
+
48
+ /*
49
+ * The label: SENTENCE CASE at the caption step, as the design sets it and as
50
+ * the caller wrote it. The uppercased, tracked-open micro-caps it used to wear
51
+ * are a table's column head: five of them over five numbers put a heading on
52
+ * every tile, and uppercasing is a transform a caller's own words should not
53
+ * have to survive.
54
+ */
55
+ .crewlet-statcard__label {
56
+ display: flex;
57
+ align-items: center;
58
+ gap: var(--spacing-1);
59
+ font-size: var(--font-size-xs);
60
+ font-weight: var(--font-weight-regular);
61
+ letter-spacing: var(--font-letter-spacing-normal);
62
+ color: var(--color-text-tertiary);
63
+ min-width: 0;
64
+ }
65
+
66
+ .crewlet-statcard__icon {
67
+ display: inline-flex;
68
+ flex: none;
69
+ }
70
+
71
+ /*
72
+ * The value's line: the number at its start, the figure at its end, both on
73
+ * the line's FOOT, so a 28px number and a 28px sparkline share a baseline
74
+ * rather than centring on each other.
75
+ */
76
+ .crewlet-statcard__reading {
77
+ display: flex;
78
+ align-items: flex-end;
79
+ justify-content: space-between;
80
+ gap: calc(var(--spacing-2) + var(--spacing-1) / 2);
81
+ min-width: 0;
82
+ }
83
+
84
+ /*
85
+ * THE SCREEN'S ONE DISPLAY NUMBER. The display step, semibold, on the tight
86
+ * track, with tabular figures so a number that ticks up moves nothing beside
87
+ * it.
88
+ *
89
+ * ITS LINE IS THE GLYPH'S OWN HEIGHT (a leading of 1). The value is one line
90
+ * that never wraps, and any leading over it is air under the digits that
91
+ * opens between the number and the line below it and stands the number
92
+ * higher than the figure it shares a foot with.
93
+ *
94
+ * A BLOCK, NOT A FLEX ROW, because it is one line of text that has to END
95
+ * rather than stop: `text-overflow` acts on a block container only, and as a
96
+ * flex row the number and its unit were anonymous flex items no rule could
97
+ * reach, so a value too long for its tile was cut mid-digit with nothing to
98
+ * say a digit was lost. The unit sits on the same line as inline text, on
99
+ * the number's baseline.
100
+ */
101
+ .crewlet-statcard__value {
102
+ display: block;
103
+ flex: 1 1 auto;
104
+ min-width: 0;
105
+ font-size: var(--font-size-display);
106
+ font-weight: var(--font-weight-semibold);
107
+ letter-spacing: var(--font-letter-spacing-tight);
108
+ line-height: 1;
109
+ font-variant-numeric: tabular-nums;
110
+ overflow: hidden;
111
+ text-overflow: ellipsis;
112
+ white-space: nowrap;
113
+ }
114
+
115
+ /* The unit, "/ 7" after the 4: the quiet ink at a text step, medium, so it
116
+ reads as part of the figure rather than as a second one. */
117
+ .crewlet-statcard__unit {
118
+ margin-inline-start: var(--spacing-1);
119
+ font-size: var(--font-size-sm);
120
+ font-weight: var(--font-weight-medium);
121
+ letter-spacing: var(--font-letter-spacing-normal);
122
+ color: var(--color-text-tertiary);
123
+ }
124
+
125
+ /*
126
+ * The figure at the end of the line. A figure (a sparkline, a meter, a state
127
+ * bar) FILLS the slot, because none of them has a width of its own to offer.
128
+ * A control keeps its own and stands at the slot's end: "Review" is a small
129
+ * button beside the number it acts on, not a bar the width of a sparkline.
130
+ */
131
+ .crewlet-statcard__trend {
132
+ display: flex;
133
+ flex-direction: column;
134
+ justify-content: flex-end;
135
+ flex: none;
136
+ width: var(--crewlet-statcard-trend-width);
137
+ min-width: 0;
138
+ }
139
+
140
+ .crewlet-statcard__trend > :where(button, a) {
141
+ align-self: flex-end;
142
+ }
143
+
144
+ /*
145
+ * The placeholder is a line, not a pair of dashes. `--` is read aloud as
146
+ * "dash dash" and looks exactly like a measured value of nothing; the tile
147
+ * carries aria-busy instead, and the line says the number is on its way.
148
+ */
149
+ .crewlet-statcard__placeholder {
150
+ display: inline-block;
151
+ width: 3ch;
152
+ height: 0.7em;
153
+ border-radius: var(--radius-xs);
154
+ background: var(--color-surface-inset);
155
+ }
156
+
157
+ /*
158
+ * The second line keeps its space whether or not there is one, so a row of
159
+ * tiles where only some carry one still stands at one height: its leading is
160
+ * set here and the reserve is exactly one line of it, where a reserve in `em`
161
+ * was a line shorter than the one a sub actually draws.
162
+ */
163
+ .crewlet-statcard__sub {
164
+ min-height: calc(1em * var(--font-line-height-body));
165
+ font-size: var(--font-size-xs);
166
+ line-height: var(--font-line-height-body);
167
+ /* The quiet step, with the label. The line qualifies the number rather than
168
+ being a second one. */
169
+ color: var(--color-text-tertiary);
170
+ overflow: hidden;
171
+ text-overflow: ellipsis;
172
+ white-space: nowrap;
173
+ }
174
+
175
+ /*
176
+ * A CHANGE IS COLOURED BY WHETHER IT WAS WANTED, not by its direction: the
177
+ * sign already says which way the number moved. Good news takes the success
178
+ * ink and bad news the danger ink, the steps measured as TEXT on every rung;
179
+ * a change that is neither takes the secondary ink, a step up from the words
180
+ * after it, so the figure still leads the sentence.
181
+ */
182
+ .crewlet-statcard__delta {
183
+ font-variant-numeric: tabular-nums;
184
+ }
185
+
186
+ .crewlet-statcard__delta--good { color: var(--color-feedback-success-ink); }
187
+ .crewlet-statcard__delta--bad { color: var(--color-feedback-danger-ink); }
188
+ .crewlet-statcard__delta--neutral { color: var(--color-text-secondary); }
189
+
190
+ /*
191
+ * A SECOND LINE THAT REPORTS A STATE takes that state's ink ("Oldest waiting
192
+ * 2h 10m" is a person kept waiting: warning), the step measured as text on
193
+ * every rung, as the value's tone does. The delta inside the line keeps its
194
+ * own ink, which is a class on the delta and outranks this one on the line.
195
+ */
196
+ .crewlet-statcard__sub--success { color: var(--color-feedback-success-ink); }
197
+ .crewlet-statcard__sub--warning { color: var(--color-feedback-warning-ink); }
198
+ .crewlet-statcard__sub--danger { color: var(--color-feedback-danger-ink); }
199
+ .crewlet-statcard__sub--info { color: var(--color-feedback-info-ink); }
200
+
201
+ .crewlet-statcard--success .crewlet-statcard__value { color: var(--color-feedback-success-ink); }
202
+ .crewlet-statcard--warning .crewlet-statcard__value { color: var(--color-feedback-warning-ink); }
203
+ .crewlet-statcard--danger .crewlet-statcard__value { color: var(--color-feedback-danger-ink); }
204
+ .crewlet-statcard--info .crewlet-statcard__value { color: var(--color-feedback-info-ink); }
@@ -1,2 +1,2 @@
1
- export { StatGroup } from '../chunk-QNCVHRZL.js';
1
+ export { StatGroup } from '../chunk-QVAFL2LE.js';
2
2
  import '../chunk-ODEQTPFM.js';
@@ -10,14 +10,13 @@
10
10
  .crewlet-stat-group {
11
11
  display: grid;
12
12
  grid-template-columns: repeat(var(--crewlet-stat-group-cols, 4), minmax(0, 1fr));
13
- /* The flush-panel recipe: the surface, the hairline, the 12px corner and
14
- `overflow: hidden`, which is what lets the tiles inside sit against the
15
- corners without their own hairlines escaping past them. The engine puts
16
- its stat row inside exactly this. */
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
17
  background: var(--color-surface-subtle);
18
18
  border: 1px solid var(--color-border-default);
19
19
  border-radius: var(--radius-lg);
20
- box-shadow: var(--shadow-xs), var(--shadow-hairline);
21
20
  overflow: hidden;
22
21
  }
23
22
 
@@ -38,7 +37,6 @@
38
37
  background: transparent;
39
38
  border: 0;
40
39
  border-radius: var(--radius-none);
41
- box-shadow: none;
42
40
  }
43
41
 
44
42
  /*
@@ -57,13 +55,14 @@
57
55
 
58
56
  /*
59
57
  * Two columns under the shell breakpoint, which is where the engine drops its
60
- * own stat row: 900px is a 280px rail plus a 620px content column, so it is
61
- * the width at which a four-up row of numbers stops having a column each. The
58
+ * own stat row, and strictly under it, as the shell switches. The step is
59
+ * 1024px, a 236px rail, the 8px inset and a 780px floor for the sheet, and it
60
+ * is the width at which the shell stops holding the page beside the rail. The
62
61
  * rules are written for the general case rather than per column count: the
63
62
  * first tile of each pair loses its left hairline, and everything on the
64
63
  * second row and below gains a top one.
65
64
  */
66
- @media (max-width: 900px) {
65
+ @media (width < 1024px) {
67
66
  .crewlet-stat-group {
68
67
  grid-template-columns: repeat(2, minmax(0, 1fr));
69
68
  }
@@ -1,12 +1,30 @@
1
- import type { PhaseTone, Tone } from '../utils/tone.js';
1
+ import type { ReactNode } from 'react';
2
+ import type { Tone } from '../utils/tone.js';
2
3
  export interface StatusDotProps {
3
- /** Which state, or which phase. Neutral says "nothing in particular". */
4
- tone?: Tone | PhaseTone | undefined;
5
4
  /**
6
- * A slow pulse, for a state that is still happening. Held still under a
7
- * reduced-motion preference, where the mark still reads as its tone.
5
+ * Which state. Neutral says "nothing in particular", and it is also the dot
6
+ * beside a category's word, such as a phase's: a category has no hue.
7
+ */
8
+ tone?: Tone | undefined;
9
+ /**
10
+ * A halo that breathes out round the dot and back, in the tone's soft step,
11
+ * for a state that is still happening: the approved design pulses the
12
+ * `info` dot, which is working. One round is `--motion-duration-breath`. The
13
+ * dot itself never fades, and the halo never touches it: it is cast from a
14
+ * ring 2px out, so the dot always stands on the surface its fill clears 3:1
15
+ * against. Held still under a reduced-motion preference, where the dot rests
16
+ * at its fill with no halo and the word beside it still says the work is
17
+ * under way. The ring is drawn on the dot's `::after`, and a `position` of
18
+ * your own on the dot still wins over the one the ring needs.
8
19
  */
9
20
  pulse?: boolean | undefined;
21
+ /**
22
+ * The word the dot belongs to: "Reviewing !231". Given one, the dot and the
23
+ * word are drawn as one line, `.crewlet-status`, with the room between them
24
+ * the kit decides rather than the caller (see the stylesheet), and
25
+ * `className` goes on that line. The word is read; the dot still is not.
26
+ */
27
+ children?: ReactNode;
10
28
  className?: string | undefined;
11
29
  }
12
30
  /**
@@ -22,4 +40,4 @@ export interface StatusDotProps {
22
40
  * it can sit on, because a mark is read the way a glyph is rather than the way
23
41
  * text is.
24
42
  */
25
- export declare function StatusDot({ tone, pulse, className }: StatusDotProps): import("react").JSX.Element;
43
+ export declare function StatusDot({ tone, pulse, children, className }: StatusDotProps): import("react").JSX.Element;
@@ -1,2 +1,2 @@
1
- export { StatusDot } from '../chunk-PZSWF74H.js';
1
+ export { StatusDot } from '../chunk-WIATRXEJ.js';
2
2
  import '../chunk-ODEQTPFM.js';
@@ -0,0 +1,186 @@
1
+ /*
2
+ * The status dot: a 7px mark in its tone's fill, beside the word it belongs
3
+ * to. See the component doc for why it is hidden from assistive technology.
4
+ *
5
+ * 7px is the approved design's dot. The size is written out rather than
6
+ * taken from a scale because it is the measure of one mark, not a step
7
+ * anything else shares, and it is fixed at every density: a mark read the
8
+ * way a glyph is does not shrink with the gaps around it.
9
+ *
10
+ * TWO VALUES PER TONE: the fill the dot is painted in, and the HALO a pulsing
11
+ * dot breathes out in, which is the same tone's soft step. The halo is held to
12
+ * being SEEN rather than to a contrast ratio: it never touches the dot (see the
13
+ * pulse below), so the dot clears 3:1 against the surface it stands on at every
14
+ * point of the round, and the word beside it says the state. The halo only has
15
+ * to stand off its ground by the dE 3 the palette suite holds every "can a
16
+ * reader notice it" difference to. Every soft step does, by 4.48 at the least.
17
+ */
18
+
19
+ .crewlet-status-dot {
20
+ display: inline-block;
21
+ width: 7px;
22
+ height: 7px;
23
+ border-radius: var(--radius-circle);
24
+ /*
25
+ * The quiet state is still a mark, so it takes the tertiary step rather than
26
+ * the decoration one the engine spends here: a 7px dot has to clear 3:1 to
27
+ * be seen at all, and --color-text-muted measures 2.33:1 on a light page and
28
+ * 2.25:1 on a dark one at their worst grounds. The tertiary step measures
29
+ * 4.87:1 and 4.65:1 on the same pair, and is the nearest step that holds.
30
+ */
31
+ background: var(--color-text-tertiary);
32
+ /*
33
+ * The neutral family has no soft step, because it has no hue to tint with,
34
+ * so its halo is a translucent overlay. Pressed is the one that reads like
35
+ * the tones' halos: it stands dE 6.09 off its faintest ground (the light
36
+ * frame) and 8.84 in dark, inside the 4.48 to 8.50 the soft steps span. The
37
+ * hover overlay stands 3.03, on the floor, and the inset well 1.79, under it.
38
+ */
39
+ --crewlet-status-dot-halo: var(--color-surface-pressed);
40
+ flex: none;
41
+ }
42
+
43
+ .crewlet-status-dot--info {
44
+ background: var(--color-feedback-info);
45
+ --crewlet-status-dot-halo: var(--color-feedback-info-soft);
46
+ }
47
+
48
+ .crewlet-status-dot--success {
49
+ background: var(--color-feedback-success);
50
+ --crewlet-status-dot-halo: var(--color-feedback-success-soft);
51
+ }
52
+
53
+ .crewlet-status-dot--warning {
54
+ background: var(--color-feedback-warning);
55
+ --crewlet-status-dot-halo: var(--color-feedback-warning-soft);
56
+ }
57
+
58
+ .crewlet-status-dot--danger {
59
+ background: var(--color-feedback-danger);
60
+ --crewlet-status-dot-halo: var(--color-feedback-danger-soft);
61
+ }
62
+
63
+ .crewlet-status-dot--brand {
64
+ background: var(--color-brand-accent);
65
+ --crewlet-status-dot-halo: var(--color-brand-accent-soft);
66
+ }
67
+
68
+ /*
69
+ * STILL HAPPENING: a halo breathes out round the dot and back in, the approved
70
+ * design's working pulse. Five things are deliberate.
71
+ *
72
+ * THE DOT NEVER FADES. The halo is a box-shadow and it is the only property
73
+ * the keyframes touch, so the fill stays at the step measured to 3:1 through
74
+ * the whole round. The pulse this replaced faded the dot itself to 0.35, and
75
+ * at the bottom of that fade every fill measured 1.35:1 to 2.17:1 against the
76
+ * surfaces it sits on: for part of every round, a mark under its own floor.
77
+ *
78
+ * NOR DOES THE HALO TOUCH IT. The design casts the halo from the dot itself,
79
+ * and a spread shadow starts at the edge of the box that casts it, so for the
80
+ * whole round the dot's ground would be its own soft step on the surface
81
+ * rather than the surface. On that ground the light info, success and warning
82
+ * fills measure 2.65:1 to 2.95:1 (warning and success on the frame, where they
83
+ * clear 3.00:1 and 3.01:1 bare): the same fault as the fade, smaller. So the
84
+ * halo is cast by a RING BOX 2px outside the dot, the offset the Avatar state
85
+ * ring and the outer focus ring stand at, and an outer shadow is never painted
86
+ * inside the box that casts it: a band of the real ground always stands
87
+ * between the dot and its halo, so the dot always stands on the surface its
88
+ * fill was measured against. The fill does not move. Nothing in this kit
89
+ * holds a mark to its own soft step, which is also why a Tag draws its dot in
90
+ * its ink.
91
+ *
92
+ * A SHADOW ON A PSEUDO-ELEMENT, not an outline at the same offset, because an
93
+ * outline's width is snapped to whole device pixels, as a border's is: at 1x
94
+ * a width breathing to 3px is drawn 1px and then 2px and reaches 3px for an
95
+ * instant, a flicker between two rings rather than a breath, where a spread
96
+ * shadow grows smoothly. The ring box is absolutely positioned, so it takes
97
+ * no room, and the pulsing dot is its containing block through a rule written
98
+ * in :where(), which weighs nothing, so a position of your own on the dot
99
+ * still wins, and any position but static keeps the ring on it.
100
+ *
101
+ * IT REACHES THE DESIGN'S 5PX, 2 of ground and 3 of halo, painted outside
102
+ * every box, so it moves nothing beside the dot. Like the 7px it surrounds,
103
+ * it is the measure of this one mark and is fixed at every density.
104
+ *
105
+ * ONE ROUND IS --motion-duration-breath, which is a PERIOD rather than a
106
+ * transition: out by the half, back by the end, and no `alternate`, which
107
+ * would play each half as a whole duration and take twice as long. That is
108
+ * 0.45 rounds a second, far under the three flashes a second that are a
109
+ * seizure risk, and the in-out ease makes both ends a rest. The halo is read
110
+ * through the custom property each tone sets above, which the ring box
111
+ * inherits, so whichever tone pulses breathes in its own soft step.
112
+ */
113
+ :where(.crewlet-status-dot.is-pulsing) {
114
+ position: relative;
115
+ }
116
+
117
+ .crewlet-status-dot.is-pulsing::after {
118
+ content: '';
119
+ position: absolute;
120
+ inset: -2px;
121
+ border-radius: var(--radius-circle);
122
+ /* Paint, never a target: the box reaches 2px past the dot. */
123
+ pointer-events: none;
124
+ animation: crewlet-status-dot-pulse var(--motion-duration-breath) var(--motion-easing-in-out) infinite;
125
+ }
126
+
127
+ /*
128
+ * The spread moves and nothing else: the rests and the peak are one shadow in
129
+ * one colour, so the only thing that interpolates is how far it reaches.
130
+ */
131
+ @keyframes crewlet-status-dot-pulse {
132
+ 0%,
133
+ 100% {
134
+ box-shadow: 0 0 0 0 var(--crewlet-status-dot-halo);
135
+ }
136
+
137
+ 50% {
138
+ box-shadow: 0 0 0 3px var(--crewlet-status-dot-halo);
139
+ }
140
+ }
141
+
142
+ /*
143
+ * A DOT WITH ITS WORD: one line, the dot and then the word, the way every
144
+ * dot in this kit is meant to be read.
145
+ *
146
+ * THE GAP CLEARS THE HALO. A pulsing dot's halo reaches 5px past its edge, 2
147
+ * of ground and 3 of halo, painted outside every box, so it takes no room and
148
+ * a gap narrower than that puts the halo on the first letter at every peak:
149
+ * at the 4px an ordinary mark stands off its word, it struck the R of
150
+ * "Reviewing". 7px is that reach and 2px of ground on the far side of it, the
151
+ * same band that stands between the dot and its halo, so at the peak the word
152
+ * stands off the halo exactly as the halo stands off the dot. It is written in
153
+ * pixels, not a spacing step, because what it clears is fixed at every
154
+ * density like the dot and the halo themselves, and it is the same for EVERY
155
+ * tone, pulsing or not, so a column of statuses starts its words on one line
156
+ * whichever of them is breathing.
157
+ */
158
+ .crewlet-status {
159
+ display: inline-flex;
160
+ align-items: center;
161
+ gap: 7px;
162
+ min-width: 0;
163
+ max-width: 100%;
164
+ }
165
+
166
+ /* A status is one line, and the word is what gives way: the dot never does. */
167
+ .crewlet-status__label {
168
+ min-width: 0;
169
+ overflow: hidden;
170
+ text-overflow: ellipsis;
171
+ white-space: nowrap;
172
+ }
173
+
174
+ /*
175
+ * HELD, not slowed: a mark that loops for as long as the work runs is exactly
176
+ * what the setting is for. The stop names the selector that starts the pulse
177
+ * and comes after it, so it wins on source order at the same specificity,
178
+ * which is the pairing the package's literal check holds every stylesheet to.
179
+ * The dot rests at its own fill with no halo, and the word beside it still
180
+ * says the work is under way.
181
+ */
182
+ @media (prefers-reduced-motion: reduce) {
183
+ .crewlet-status-dot.is-pulsing::after {
184
+ animation: none;
185
+ }
186
+ }