@slotted/react 0.1.0-beta.1 → 0.1.0-beta.3

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 (307) hide show
  1. package/README.md +4 -0
  2. package/dist/{action-bar-C7cGnEyJ.js → action-bar-OACchRZw.js} +1 -1
  3. package/dist/action-bar.js +1 -1
  4. package/dist/{action-sheet-D8Glxl7l.js → action-sheet-C60BWUW8.js} +1 -1
  5. package/dist/action-sheet.js +1 -1
  6. package/dist/{app-shell-CXwma4XA.js → app-shell-CmYvnu_7.js} +310 -310
  7. package/dist/app-shell.js +1 -1
  8. package/dist/button-Db9f3Bxn.js +99 -0
  9. package/dist/button.js +2 -2
  10. package/dist/cascader-D1AhTyBL.js +1097 -0
  11. package/dist/cascader.js +1 -1
  12. package/dist/chart-O0ZhkzJe.js +966 -0
  13. package/dist/chart.js +1 -1
  14. package/dist/{checkbox-CwUOc-3u.js → checkbox-DfxFHZaU.js} +3 -3
  15. package/dist/{checkbox-group-BYTjgAcX.js → checkbox-group-9sDgrV5Z.js} +2 -2
  16. package/dist/checkbox-group.js +1 -1
  17. package/dist/checkbox.js +1 -1
  18. package/dist/{color-picker-BlPR4g4H.js → color-picker-CwbWzCKg.js} +4 -4
  19. package/dist/color-picker.js +1 -1
  20. package/dist/{column-manager-CNZ7Xk5_.js → column-manager-CTtizVhm.js} +6 -6
  21. package/dist/column-manager.js +1 -1
  22. package/dist/{combobox-C46GRqAA.js → combobox-BVMI9lg8.js} +296 -292
  23. package/dist/combobox.js +1 -1
  24. package/dist/{command-palette-BqRyNR9Y.js → command-palette-DFLbSOiv.js} +1 -1
  25. package/dist/command-palette.js +1 -1
  26. package/dist/{context-menu-DMiHdggw.js → context-menu-BuST6W94.js} +1 -1
  27. package/dist/context-menu.js +1 -1
  28. package/dist/currency-field-DD9A5U3D.js +455 -0
  29. package/dist/currency-field.js +1 -1
  30. package/dist/dashboard-grid-CBMP_-JV.js +1043 -0
  31. package/dist/dashboard-grid.js +1 -1
  32. package/dist/{data-grid-BUgOJuGp.js → data-grid-BKaGMqIm.js} +19 -19
  33. package/dist/data-grid.js +1 -1
  34. package/dist/{data-list-2xfDpHVC.js → data-list-oICmxGkA.js} +5 -5
  35. package/dist/data-list.js +1 -1
  36. package/dist/{date-field-D_kLLTfL.js → date-field-CYcN6diW.js} +1 -1
  37. package/dist/date-field.js +1 -1
  38. package/dist/date-picker-4X-_2ltN.js +264 -0
  39. package/dist/date-picker.js +1 -1
  40. package/dist/date-range-picker-CNOAtHwU.js +471 -0
  41. package/dist/date-range-picker.js +1 -1
  42. package/dist/{datetime-field-T1gNdJ7t.js → datetime-field-B8TrmsDK.js} +1 -1
  43. package/dist/datetime-field.js +1 -1
  44. package/dist/datetime-picker-HDVlUhzy.js +629 -0
  45. package/dist/datetime-picker.js +1 -1
  46. package/dist/datetime-range-picker-IqOFJtdW.js +994 -0
  47. package/dist/datetime-range-picker.js +1 -1
  48. package/dist/{dialog-Dmy-m_pe.js → dialog-BHYDDj1S.js} +112 -113
  49. package/dist/dialog.js +1 -1
  50. package/dist/docs/AGENTS.snippet.md +10 -0
  51. package/dist/docs/app-shell.json +1 -1
  52. package/dist/docs/button-group.json +1 -0
  53. package/dist/docs/button-group.md +1 -1
  54. package/dist/docs/button.json +45 -11
  55. package/dist/docs/button.md +10 -6
  56. package/dist/docs/chart.json +7 -0
  57. package/dist/docs/chart.md +1 -0
  58. package/dist/docs/currency-field.json +32 -1
  59. package/dist/docs/currency-field.md +4 -1
  60. package/dist/docs/dialog.examples.md +26 -0
  61. package/dist/docs/dialog.json +14 -2
  62. package/dist/docs/dialog.md +1 -1
  63. package/dist/docs/event-calendar.json +7 -0
  64. package/dist/docs/event-calendar.md +1 -0
  65. package/dist/docs/guidelines/README.md +27 -0
  66. package/dist/docs/guidelines/async-feedback.md +108 -0
  67. package/dist/docs/guidelines/browsing.md +74 -0
  68. package/dist/docs/guidelines/builders.md +97 -0
  69. package/dist/docs/guidelines/composition.md +129 -0
  70. package/dist/docs/guidelines/conversations.md +59 -0
  71. package/dist/docs/guidelines/errors-and-conflicts.md +71 -0
  72. package/dist/docs/guidelines/forms.md +192 -0
  73. package/dist/docs/guidelines/index.md +121 -0
  74. package/dist/docs/guidelines/layout-alignment.md +95 -0
  75. package/dist/docs/guidelines/ledgers.md +45 -0
  76. package/dist/docs/guidelines/list-pages.md +165 -0
  77. package/dist/docs/guidelines/overviews.md +66 -0
  78. package/dist/docs/guidelines/own-elements.md +115 -0
  79. package/dist/docs/guidelines/reading-permissions.md +55 -0
  80. package/dist/docs/guidelines/record-pages.md +178 -0
  81. package/dist/docs/guidelines/reports.md +123 -0
  82. package/dist/docs/guidelines/shell-composition.md +94 -0
  83. package/dist/docs/guidelines/workspaces.md +46 -0
  84. package/dist/docs/index.md +12 -0
  85. package/dist/docs/list.json +26 -1
  86. package/dist/docs/list.md +4 -1
  87. package/dist/docs/popover.json +1 -1
  88. package/dist/docs/progress-indicator.json +1 -2
  89. package/dist/docs/progress-indicator.md +2 -2
  90. package/dist/docs/segmented-control.json +29 -1
  91. package/dist/docs/segmented-control.md +17 -1
  92. package/dist/docs/side-navigation.json +2 -2
  93. package/dist/docs/side-navigation.md +19 -4
  94. package/dist/docs/skills/build-own-element/SKILL.md +90 -0
  95. package/dist/docs/skills/compose-screen/SKILL.md +76 -0
  96. package/dist/docs/skills/index.md +9 -0
  97. package/dist/docs/skills/review-screen/SKILL.md +70 -0
  98. package/dist/docs/skills/theme-app/SKILL.md +79 -0
  99. package/dist/docs/skills/waiting-states/SKILL.md +139 -0
  100. package/dist/docs/split-button.json +1 -0
  101. package/dist/docs/split-button.md +1 -1
  102. package/dist/docs/stat-card.json +2 -0
  103. package/dist/docs/stat-card.md +1 -1
  104. package/dist/docs/table.examples.md +1 -1
  105. package/dist/docs/table.json +78 -2
  106. package/dist/docs/table.md +12 -1
  107. package/dist/docs/tabs.examples.md +1 -1
  108. package/dist/docs/tabs.json +2 -5
  109. package/dist/docs/tabs.md +1 -1
  110. package/dist/docs/toggle-group.json +14 -3
  111. package/dist/docs/toggle-group.md +3 -3
  112. package/dist/docs/toggle.json +12 -3
  113. package/dist/docs/toggle.md +3 -3
  114. package/dist/docs/tokens.md +448 -0
  115. package/dist/docs/top-navigation.examples.md +23 -5
  116. package/dist/docs/top-navigation.json +2 -2
  117. package/dist/docs/tour.json +1 -1
  118. package/dist/drawer-LXM44eso.js +757 -0
  119. package/dist/drawer.js +1 -1
  120. package/dist/entity-picker-CPDd73JR.js +1110 -0
  121. package/dist/entity-picker.js +1 -1
  122. package/dist/{event-calendar-BFdeGfC-.js → event-calendar-CnF3iIZD.js} +391 -390
  123. package/dist/event-calendar.js +1 -1
  124. package/dist/{field-BJh5HI7w.js → field-NJaCxl2h.js} +1 -1
  125. package/dist/{field-group-BDaspQPh.js → field-group-hAzVa2O9.js} +1 -1
  126. package/dist/field-group.js +1 -1
  127. package/dist/field.js +1 -1
  128. package/dist/{filter-bar-b2Q9BZHf.js → filter-bar-D_xDcAp2.js} +20 -20
  129. package/dist/filter-bar.js +1 -1
  130. package/dist/{hover-card-CSDbA6zd.js → hover-card-BJE5dtaQ.js} +1 -1
  131. package/dist/hover-card.js +1 -1
  132. package/dist/{icon-button-TnvMhK4o.js → icon-button-CCWkCDMs.js} +26 -24
  133. package/dist/import-export-center-DpY2DGBZ.js +813 -0
  134. package/dist/import-export-center.js +1 -1
  135. package/dist/index.js +85 -84
  136. package/dist/{list-C1Y8MWp2.js → list-WsQ6ZzCa.js} +16 -12
  137. package/dist/{list-item-DN_mcouU.js → list-item-DpCwZIrd.js} +1 -1
  138. package/dist/list-item.js +1 -1
  139. package/dist/list.js +1 -1
  140. package/dist/{listbox-4WvqR0JF.js → listbox-Dv856z9I.js} +1 -1
  141. package/dist/listbox.js +1 -1
  142. package/dist/{loading-overlay-B83XFctM.js → loading-overlay-COfnckse.js} +73 -73
  143. package/dist/loading-overlay.js +1 -1
  144. package/dist/{markdown-CpfDn1LF.js → markdown-CeG8mUbI.js} +2 -2
  145. package/dist/markdown.js +1 -1
  146. package/dist/menu-parts-W58pVNUt.js +786 -0
  147. package/dist/menu.js +1 -1
  148. package/dist/{menubar-CtGavUTO.js → menubar-b2CruimJ.js} +1 -1
  149. package/dist/menubar.js +1 -1
  150. package/dist/{multi-select-CfzsvAeI.js → multi-select-DQ5ds0fX.js} +432 -437
  151. package/dist/multi-select.js +1 -1
  152. package/dist/{notification-center-C4pEHJ3h.js → notification-center-Sz54IziY.js} +2 -2
  153. package/dist/notification-center.js +1 -1
  154. package/dist/{number-field-J_koud1r.js → number-field-BFIAmv-z.js} +1 -1
  155. package/dist/number-field.js +1 -1
  156. package/dist/{otp-input-Bf8JUiVR.js → otp-input-BNQhuKaT.js} +1 -1
  157. package/dist/otp-input.js +1 -1
  158. package/dist/popover-Be7JWbGJ.js +475 -0
  159. package/dist/popover.js +1 -1
  160. package/dist/press-selection-DjOllE2B.js +29 -0
  161. package/dist/press-selection.js +2 -0
  162. package/dist/{prompt-composer-B7MMcER0.js → prompt-composer-BxpdkTpZ.js} +1 -1
  163. package/dist/prompt-composer.js +1 -1
  164. package/dist/{radio-group-BFpjhDkV.js → radio-group-BaVIP9UH.js} +2 -2
  165. package/dist/radio-group.js +1 -1
  166. package/dist/{rating-D1EsADFM.js → rating-DYBQBzwB.js} +1 -1
  167. package/dist/rating.js +1 -1
  168. package/dist/{saved-views-BueW-Lyb.js → saved-views-DlE_--Z9.js} +5 -5
  169. package/dist/saved-views.js +1 -1
  170. package/dist/{segmented-control-Cy_5D3Nj.js → segmented-control-DmuOGiu6.js} +28 -24
  171. package/dist/segmented-control.js +1 -1
  172. package/dist/{select-UTwKjheK.js → select-DOFqPy26.js} +334 -347
  173. package/dist/select.js +1 -1
  174. package/dist/{side-navigation-YUiJRpng.js → side-navigation-CBLtCzuJ.js} +186 -187
  175. package/dist/side-navigation.js +1 -1
  176. package/dist/{slider-B432T6nD.js → slider-DTes4HLF.js} +1 -1
  177. package/dist/slider.js +1 -1
  178. package/dist/{split-button-DHF3v3PJ.js → split-button-CPgHiy9G.js} +2 -2
  179. package/dist/split-button.js +1 -1
  180. package/dist/styles.css +1 -1
  181. package/dist/{switch-4MHwKmkz.js → switch-DQzuIhPX.js} +1 -1
  182. package/dist/switch.js +1 -1
  183. package/dist/{table-CzBIw9ng.js → table-Cipi2c5X.js} +206 -173
  184. package/dist/table.js +2 -2
  185. package/dist/{tags-input-DLdHLWrH.js → tags-input-CcOkm0AW.js} +1 -1
  186. package/dist/tags-input.js +1 -1
  187. package/dist/{text-field-BktZbmzD.js → text-field-DLfIZ0fk.js} +1 -1
  188. package/dist/text-field.js +1 -1
  189. package/dist/{textarea-JAK2RJl0.js → textarea-CBJBJBi6.js} +1 -1
  190. package/dist/textarea.js +1 -1
  191. package/dist/{time-field-DCG_VtGO.js → time-field-DrhiCtUl.js} +1 -1
  192. package/dist/time-field.js +1 -1
  193. package/dist/{time-picker-DuT1tf5-.js → time-picker-CRQsMJbQ.js} +102 -102
  194. package/dist/time-picker.js +1 -1
  195. package/dist/{time-range-picker-HwBvrrXN.js → time-range-picker-DlZJsj1e.js} +202 -202
  196. package/dist/time-range-picker.js +1 -1
  197. package/dist/{toast-wI8BtPY5.js → toast-Bf3e0AgC.js} +157 -157
  198. package/dist/toast.js +1 -1
  199. package/dist/toggle-group-7iBR9Rn1.js +142 -0
  200. package/dist/toggle-group.js +1 -1
  201. package/dist/{toolbar-CDQTydDx.js → toolbar-DDZpEftQ.js} +1 -1
  202. package/dist/toolbar.js +1 -1
  203. package/dist/{tooltip-BggqPDcW.js → tooltip-DbKTPe_i.js} +108 -109
  204. package/dist/tooltip.js +1 -1
  205. package/dist/{top-navigation-COQZsNqW.js → top-navigation-e-tWMGNr.js} +255 -256
  206. package/dist/top-navigation.js +1 -1
  207. package/dist/{tour-C11DmYTC.js → tour-BTdt716T.js} +180 -180
  208. package/dist/tour.js +1 -1
  209. package/dist/{transfer-JA9TWjAw.js → transfer-CqZOTLMP.js} +6 -6
  210. package/dist/transfer.js +1 -1
  211. package/dist/types/app-shell/app-shell.d.ts.map +1 -1
  212. package/dist/types/button/button-link.d.ts +1 -1
  213. package/dist/types/button/button-link.d.ts.map +1 -1
  214. package/dist/types/button/button-root.d.ts +5 -3
  215. package/dist/types/button/button-root.d.ts.map +1 -1
  216. package/dist/types/button/button.constants.d.ts +2 -1
  217. package/dist/types/button/button.constants.d.ts.map +1 -1
  218. package/dist/types/button/button.d.ts +1 -1
  219. package/dist/types/button/button.d.ts.map +1 -1
  220. package/dist/types/button/button.types.d.ts +9 -2
  221. package/dist/types/button/button.types.d.ts.map +1 -1
  222. package/dist/types/button/index.d.ts +1 -1
  223. package/dist/types/button/index.d.ts.map +1 -1
  224. package/dist/types/button/toggle-button.d.ts +1 -1
  225. package/dist/types/button/toggle-button.d.ts.map +1 -1
  226. package/dist/types/chart/chart.d.ts.map +1 -1
  227. package/dist/types/combobox/combobox-collection.d.ts +1 -0
  228. package/dist/types/combobox/combobox-collection.d.ts.map +1 -1
  229. package/dist/types/combobox/combobox-parts.d.ts.map +1 -1
  230. package/dist/types/combobox/combobox.d.ts.map +1 -1
  231. package/dist/types/currency-field/currency-field.d.ts +1 -1
  232. package/dist/types/currency-field/currency-field.d.ts.map +1 -1
  233. package/dist/types/currency-field/currency-field.types.d.ts +14 -0
  234. package/dist/types/currency-field/currency-field.types.d.ts.map +1 -1
  235. package/dist/types/currency-field/index.d.ts +1 -1
  236. package/dist/types/currency-field/index.d.ts.map +1 -1
  237. package/dist/types/dashboard-grid/dashboard-grid.d.ts.map +1 -1
  238. package/dist/types/dashboard-grid/dashboard-widget.d.ts +1 -1
  239. package/dist/types/dashboard-grid/dashboard-widget.d.ts.map +1 -1
  240. package/dist/types/dialog/dialog-demo.d.ts +8 -0
  241. package/dist/types/dialog/dialog-demo.d.ts.map +1 -1
  242. package/dist/types/drawer/drawer-parts.d.ts.map +1 -1
  243. package/dist/types/event-calendar/event-calendar.d.ts +1 -1
  244. package/dist/types/event-calendar/event-calendar.d.ts.map +1 -1
  245. package/dist/types/event-calendar/event-calendar.types.d.ts +6 -0
  246. package/dist/types/event-calendar/event-calendar.types.d.ts.map +1 -1
  247. package/dist/types/filter-bar/filter-bar.d.ts.map +1 -1
  248. package/dist/types/index.d.ts +1 -0
  249. package/dist/types/index.d.ts.map +1 -1
  250. package/dist/types/list/index.d.ts +1 -1
  251. package/dist/types/list/index.d.ts.map +1 -1
  252. package/dist/types/list/list-parts.d.ts +1 -1
  253. package/dist/types/list/list-parts.d.ts.map +1 -1
  254. package/dist/types/list/list.types.d.ts +12 -0
  255. package/dist/types/list/list.types.d.ts.map +1 -1
  256. package/dist/types/menu/menu.types.d.ts +3 -1
  257. package/dist/types/menu/menu.types.d.ts.map +1 -1
  258. package/dist/types/multi-select/multi-select-collection.d.ts +0 -2
  259. package/dist/types/multi-select/multi-select-collection.d.ts.map +1 -1
  260. package/dist/types/multi-select/multi-select-parts.d.ts.map +1 -1
  261. package/dist/types/multi-select/multi-select.d.ts.map +1 -1
  262. package/dist/types/press-selection/index.d.ts +3 -0
  263. package/dist/types/press-selection/index.d.ts.map +1 -0
  264. package/dist/types/press-selection/press-selection.d.ts +23 -0
  265. package/dist/types/press-selection/press-selection.d.ts.map +1 -0
  266. package/dist/types/segmented-control/index.d.ts +1 -1
  267. package/dist/types/segmented-control/index.d.ts.map +1 -1
  268. package/dist/types/segmented-control/segmented-control-defaults.d.ts.map +1 -1
  269. package/dist/types/segmented-control/segmented-control.d.ts +1 -1
  270. package/dist/types/segmented-control/segmented-control.d.ts.map +1 -1
  271. package/dist/types/segmented-control/segmented-control.types.d.ts +10 -0
  272. package/dist/types/segmented-control/segmented-control.types.d.ts.map +1 -1
  273. package/dist/types/select/select-collection.d.ts +0 -2
  274. package/dist/types/select/select-collection.d.ts.map +1 -1
  275. package/dist/types/select/select.d.ts.map +1 -1
  276. package/dist/types/table/index.d.ts +2 -2
  277. package/dist/types/table/index.d.ts.map +1 -1
  278. package/dist/types/table/table-parts.d.ts +8 -2
  279. package/dist/types/table/table-parts.d.ts.map +1 -1
  280. package/dist/types/table/table.types.d.ts +28 -1
  281. package/dist/types/table/table.types.d.ts.map +1 -1
  282. package/dist/types/toggle/toggle.types.d.ts +1 -1
  283. package/dist/types/toggle/toggle.types.d.ts.map +1 -1
  284. package/dist/types/toggle-group/toggle-group.d.ts.map +1 -1
  285. package/dist/types/toggle-group/toggle-group.types.d.ts +6 -1
  286. package/dist/types/toggle-group/toggle-group.types.d.ts.map +1 -1
  287. package/dist/{upload-Bq_UiyMr.js → upload-DjnlVR8y.js} +2 -2
  288. package/dist/upload.js +1 -1
  289. package/dist/{wizard-B4GrlEqh.js → wizard-BxA08vXt.js} +1 -1
  290. package/dist/wizard.js +1 -1
  291. package/package.json +12 -7
  292. package/dist/button-DakQ-7Tm.js +0 -97
  293. package/dist/cascader-CARCYdHh.js +0 -1097
  294. package/dist/chart-BNzfIfQe.js +0 -948
  295. package/dist/currency-field-B7OZ0hk7.js +0 -436
  296. package/dist/dashboard-grid-nfhEewA4.js +0 -1005
  297. package/dist/date-picker-DQ5SIhdA.js +0 -264
  298. package/dist/date-range-picker-lpB08hK_.js +0 -471
  299. package/dist/datetime-picker-0F0kDW-8.js +0 -629
  300. package/dist/datetime-range-picker-ClnEleth.js +0 -994
  301. package/dist/drawer-Ci3wuCVa.js +0 -758
  302. package/dist/entity-picker-UGhbVwkC.js +0 -1111
  303. package/dist/import-export-center-D8xbCLWs.js +0 -813
  304. package/dist/menu-parts-BQej6eU9.js +0 -787
  305. package/dist/popover-DE22lSpV.js +0 -476
  306. package/dist/react-dom-DzrKNxo6.js +0 -273
  307. package/dist/toggle-group-DQBlI1TV.js +0 -140
@@ -0,0 +1,123 @@
1
+ ---
2
+ topic: reports
3
+ prefix: RE
4
+ triggers:
5
+ [
6
+ report,
7
+ analytics,
8
+ period,
9
+ comparison,
10
+ compare,
11
+ trend,
12
+ segment,
13
+ drill-down,
14
+ download,
15
+ csv,
16
+ anomaly,
17
+ annotation,
18
+ coverage,
19
+ history,
20
+ ranking,
21
+ ]
22
+ families: [page-header, select, stat-card, chart, table, list, section, inline-message]
23
+ ---
24
+
25
+ # Reports
26
+
27
+ How a screen that reads records over a chosen period is composed: what it
28
+ reads from the operational screens, how a period and its comparison are
29
+ chosen and kept, what it says where the records are not kept, how a figure
30
+ is flagged and how a breakdown is downloaded. The library gives `chart` a
31
+ period of data, `stat-card` a change and its base, `table` a summary row; it
32
+ does not say that a period lives in the address, that a figure the history
33
+ does not hold is no number, or which rule flags a figure.
34
+
35
+ ### RE-01 · A report reads a period; an overview reads today
36
+
37
+ Level: SHOULD
38
+ Applies to: a report that shows a state of today beside its period's flows — receivables, a backlog, stock on hand
39
+ Rule: A figure of the report is a flow over its period against a period of the same length; a state of today is read through the operational screen's own read, says "as of today", and opens the operational screen's door.
40
+ Why: Two reads of one state drift — a receivables figure computed twice says two numbers on two screens — and a state read beside a period reads as the period's.
41
+ Do: Read the overview's answer beside the report's and draw its figures from it, with the overview's door and the overview's thresholds; give the read a region of its own, so a failure of either leaves the other on screen.
42
+ Don't: Recompute an overview's figure inside the report, or draw a state of today without saying it is today's.
43
+ Check: Read each state of today on the report: it says "as of today", equals the figure of the operational screen it opens, and stays on screen when the report's own read fails.
44
+
45
+ ### RE-02 · The period is the address
46
+
47
+ Level: SHOULD
48
+ Applies to: the period, the comparison and the segment filters of a report
49
+ Rule: They are query parameters of the report's address; a report opened without them takes the ones last chosen on any report, and the back gesture from a list it opened returns to the same period.
50
+ Why: A period held in the page alone is lost on the way back from a drill-down, and a reader moving from one report to the next would choose it again on each.
51
+ Do: Write each choice into the address by replacing the current history entry, so a change of period is no step of the history and the back gesture leaves the report; remember the last choice for the next report opened without one.
52
+ Don't: Keep the period in a store the address does not name, or push a history entry per change.
53
+ Check: Choose a period, open a figure's list and go back: the report is on the same period. Open another report with no period in its address: it takes the period last chosen.
54
+
55
+ ### RE-03 · What the records do not cover is not a number
56
+
57
+ Level: MUST
58
+ Applies to: a period, a comparison or a measure whose records the backend does not keep for all of its days
59
+ Rule: The period control offers only the periods the report's records are kept for; a figure, a cell or a breakdown whose records start after its range says "not kept" and from when, and is never drawn as a number.
60
+ Why: A sum over the days that happen to be kept is a part drawn as a whole: a ninety-day ratio over thirty days of invoices read 84 days of sales outstanding where the book held about 35.
61
+ Do: State once, under the controls, from which day each kind of record is kept; leave a comparison that starts earlier as "kept from", and replace a breakdown that cannot be read with the sentence that says why and which period can.
62
+ Don't: Draw a zero, a dash or a short bar for days the history does not hold, or offer a period the report will answer with nothing.
63
+ Check: Choose the longest period offered: every figure whose records start after its range says "not kept" and from when, and the period control offers no period the records do not cover.
64
+
65
+ ### RE-04 · A change says its base
66
+
67
+ Level: SHOULD
68
+ Applies to: the change a `stat-card` draws against a comparison period
69
+ Rule: The comparison line names the value compared with and the period it belongs to; an amount and a count move by a percentage, a share by points, a duration in its own unit.
70
+ Why: "+7%" with no base is a number a reader cannot check, and a share that moves from 36% to 37% reads as a 3% rise when it is one point.
71
+ Do: Hand the card the change and write "vs $15.22M, the 30 days before" in its `comparison`, on one line cut with its title; tell the card from the measure which direction is good, so a rise in discounts or in days to ship reads as a fall in quality.
72
+ Don't: Draw a relative change of a share, or a change whose base period the page does not name.
73
+ Check: Read each card with a change: the base value and its period stand on its comparison line, and a share's change ends in "pts".
74
+
75
+ ### RE-05 · An anomaly says its rule
76
+
77
+ Level: SHOULD
78
+ Applies to: a figure or a bucket a report flags as unusual
79
+ Rule: A value is flagged only by a rule the page states in words, and the flag names the value, the range it fell in, the band it left and opens the records of that range.
80
+ Why: A flag with no rule is an opinion the reader cannot weigh, and a flag that fires on noise teaches the reader to ignore the flags.
81
+ Do: Flag a value outside the mean of its own history plus or minus two standard deviations — the six periods of the same length before it, or the earlier buckets of the period — and keep a count's band no narrower than its chance variation; state a threshold the product sets (OV-04) beside it as a second kind of flag.
82
+ Don't: Flag by a fixed number the screen chose for itself, or by a comparison with a single earlier period.
83
+ Check: Read each flag: the page states its rule in words, the flag names the value, its range and the band it left, and it opens the records of that range.
84
+
85
+ ### RE-06 · A report's filters stand in the header
86
+
87
+ Level: SHOULD
88
+ Applies to: the period, comparison and segment controls of a report
89
+ Rule: They stand in `page-header`'s `content`, under the header's `toggle` and `pin`; below 600 pixels the area opens collapsed, so the figures lead the screen.
90
+ Why: The header's area is the family's place for filters, and a pinned area keeps the period in sight over a long report; a block in the body scrolls away and, on a phone, filled the first screen before a single figure.
91
+ Do: Write the controls and the one sentence of what the records cover in the `content`, and let the `subheading` say the period on the title row, where it stays when the area collapses.
92
+ Don't: Put the controls as the first block of the body, or keep the area open on a phone.
93
+ Check: At 1280 pixels the controls stand in the header with the pin; at 390 pixels with a coarse pointer the first screen holds the figures and the collapsed area's toggle.
94
+
95
+ ### RE-07 · Every number of a report opens what it counts
96
+
97
+ Level: SHOULD
98
+ Applies to: a report's figures, the bars and points of its charts, and the cells of its tables
99
+ Rule: Each opens the list of the records it counts, with its condition and its period as the list's own pills and the same total, and a record named by its id is named in the pill by its record's words.
100
+ Why: A breakdown the reader cannot open is a claim, and a pill reading "Account is any of cus_000412" says nothing a reader can check.
101
+ Do: Carry the condition in the address, field by field, and the names of the records it names beside their ids; let the list read them into its bar as it reads any filter (OV-01).
102
+ Don't: Open the unfiltered list, a list whose total differs from the number, or a pill of raw ids.
103
+ Check: Open a figure, a bar and a cell: each list's pills name the condition and the period in words, and its total equals the number opened.
104
+
105
+ ### RE-08 · A ranking draws ten
106
+
107
+ Level: SHOULD
108
+ Applies to: a `horizontal` `chart` that ranks categories whose number grows with the period or the tenant — accounts, products, representatives
109
+ Rule: The chart draws at most the ten first categories and says so in its title; the table under it holds every row and its summary.
110
+ Why: Forty-four representatives drawn on one plot stacked their names into a column nobody could read.
111
+ Do: Rank in the answer, cut the chart's data at ten and keep the rest — or one "other" row — to the table; place the section whose table holds every row last, since the wait cannot know its length and its growth then moves nothing.
112
+ Don't: Grow the plot with the categories, or cut the table with the chart.
113
+ Check: Choose the longest period: the ranking chart holds at most ten bars and says so in its title, and its table holds every row and the summary.
114
+
115
+ ### RE-09 · A download is the table on screen
116
+
117
+ Level: SHOULD
118
+ Applies to: the file a report's section offers
119
+ Rule: The download is the section's table as the reader sees it — its columns, its rows and its summary row, in its words — built in the browser from the answer the page drew, for every reader of the report.
120
+ Why: A file built by another read can say other numbers than the screen, and a column the reader may not see on screen would reach them in the file.
121
+ Do: Offer "Download CSV" in the section's actions and write the file from the table's lines; name it by report, section and period.
122
+ Don't: Offer a server export the reader's permissions were not applied to, or a file of raw minor units the table does not show.
123
+ Check: Press Download CSV on a section: the file's rows are the table's rows and its summary, and a withheld column is absent from both.
@@ -0,0 +1,94 @@
1
+ ---
2
+ topic: shell composition
3
+ prefix: SC
4
+ triggers:
5
+ [
6
+ app-shell,
7
+ shell,
8
+ banner,
9
+ header bar,
10
+ top-navigation,
11
+ search,
12
+ command palette,
13
+ magnifier,
14
+ mobile,
15
+ narrow,
16
+ overlay,
17
+ drawer,
18
+ dialog,
19
+ layer,
20
+ host,
21
+ popover,
22
+ notification-center,
23
+ brand,
24
+ ]
25
+ families: [app-shell, top-navigation, command-palette, popover, drawer, dialog, notification-center]
26
+ ---
27
+
28
+ # Shell composition
29
+
30
+ How the application frame is put together from `app-shell`, the bar inside its
31
+ banner and the layers the bar opens. Each family states its own anatomy; the
32
+ seams between them — what stands in the search slot, what a component host
33
+ costs in a flex row, how wide a panel is when its content has no width — are
34
+ the consumer's to get right.
35
+
36
+ ### SC-01 · A palette trigger is not a search field
37
+
38
+ Level: MUST
39
+ Applies to: `top-navigation`'s `search` region when what stands in it opens a `command-palette` rather than filtering in place
40
+ Rule: Below the bar's medium step, the magnifier opens the palette directly; the search region is never expanded over the bar.
41
+ Why: The bar's fold is written for a text field — open the region, move focus to its input. A region holding a trigger button costs the reader a second press and shows a button beside a close control, aligned with nothing.
42
+ Do: Answer the bar's request to open the search by cancelling it and opening the palette. Above the step the region shows the trigger as it always did.
43
+ Don't: Let the region open, or hide the magnifier and leave a narrow bar with no way to the palette.
44
+ Check: At a width under the medium step, one press on the magnifier shows the palette and the bar does not carry the open-search state.
45
+
46
+ ### SC-02 · Layer hosts leave the banner's row
47
+
48
+ Level: MUST
49
+ Applies to: a consumer component placed inside `app-shell`'s `banner` whose only output is a layer — a palette, a drawer, a dialog
50
+ Rule: A component host inside the banner that draws no box of its own contributes no box to the banner's row.
51
+ Why: The banner is a flex row with a gap; an empty host is still a flex item and costs one gap, which is air on one end of the bar and not the other.
52
+ Do: Give such a host no box — the library's own layer hosts have none — or place the component outside the banner.
53
+ Don't: Leave a consumer host in the row because its content is portalled anyway.
54
+ Check: The bar's first and last controls stand the same distance from the frame's two edges.
55
+
56
+ ### SC-03 · A panel around a query container states its measure
57
+
58
+ Level: SHOULD
59
+ Applies to: a `popover` whose content is a family that is a container query — `notification-center`, any consumer region with inline-size containment
60
+ Rule: The consumer states the content's inline size, and its block cap, on the content; the popover's measure alone does not size it.
61
+ Why: A query container contributes no intrinsic width, so a panel sized to its content settles at the family's floor whatever the popover's measure says, and a panel with no cap runs to the bottom of the viewport.
62
+ Do: Size the content to the popover's measure less the layer's own gap, bounded by the viewport on a phone, and cap its block size so the family's scrolling part scrolls.
63
+ Don't: Retune the popover's measure and expect a query container to grow into it.
64
+ Check: The panel is as wide as the popover's measure allows and no taller than the stated cap; the feed scrolls inside it.
65
+
66
+ ### SC-04 · The search slot stands one space step off the brand
67
+
68
+ Level: SHOULD
69
+ Applies to: `top-navigation`'s `search` region when nothing — no context, no destinations — stands between it and `brand`
70
+ Rule: The search region carries one space step of leading margin beyond the bar's own gap.
71
+ Why: The bar's gap is the air between the mark and the wordmark; a bordered field at that distance reads as a third part of the brand.
72
+ Do: Add one space step at the region's start. When the region takes the whole bar below the medium step it has its own inset and the margin does not apply.
73
+ Don't: Widen the bar's gap, which also moves the actions apart.
74
+ Check: The field's left edge stands one space step further from the wordmark than the wordmark stands from the mark.
75
+
76
+ ### SC-05 · A phone's bar holds five controls
77
+
78
+ Level: SHOULD
79
+ Applies to: what a consumer places in `top-navigation`'s `actions` — `action` controls of the product's own, beside the family's bell, help and account
80
+ Rule: Below the bar's high step the actions hold the search toggle, the bell, the help and the account; a product's own `action` leaves the bar and stays reachable from the navigation column or the palette.
81
+ Why: On a touch screen every control is a 44-pixel target; nine of them with the mark and the shell's toggle are wider than a phone, and the family folds none of a consumer's actions.
82
+ Do: Hide the product's own actions under the bar's own container query at the high step, and keep each one a destination in the column or a command in the palette.
83
+ Don't: Keep every action in the bar and let the cluster overflow, or shrink the controls under the touch target.
84
+ Check: At 390px with a coarse pointer, the bar's first and last controls are whole and no control overlaps another.
85
+
86
+ ### SC-06 · No key legends where there are no keys
87
+
88
+ Level: SHOULD
89
+ Applies to: a `kbd` or `shortcut` drawn as a hint beside a control — the search trigger's hotkey, a menu item's shortcut, a footer of hints
90
+ Rule: Where the primary input is a touch screen — `(hover: none) and (pointer: coarse)` — a shortcut drawn as a hint is not shown.
91
+ Why: The legend names a key the reader has no way to press; on a phone it is noise beside the control it decorates.
92
+ Do: Hide the hint under the media query. Keep a `kbd` that is content — a settings page listing the application's shortcuts — because it documents rather than hints.
93
+ Don't: Hide the control the hint stands beside, or key the rule on width: a narrow window on a laptop still has a keyboard.
94
+ Check: On a touch screen the search trigger shows the magnifier and the words alone, and the palette's footer is absent.
@@ -0,0 +1,46 @@
1
+ ---
2
+ topic: workspaces
3
+ prefix: WS
4
+ triggers:
5
+ [
6
+ workspace,
7
+ reconciliation,
8
+ match,
9
+ candidate,
10
+ confidence,
11
+ score,
12
+ queue,
13
+ three columns,
14
+ dense,
15
+ phone,
16
+ ]
17
+ families: [detail-panel, list, list-item, table, filter-bar, scroll-area, tag]
18
+ ---
19
+
20
+ # Workspaces
21
+
22
+ How a dense screen that works a queue against candidates is composed: what a
23
+ phone keeps of its regions, and how a machine's score is put before a person
24
+ who confirms it. The library gives `detail-panel` a main column and an aside,
25
+ `list` rows that lead somewhere and `table` a summary row; it does not say
26
+ how three regions become one on a phone, or that a score is shown taken apart.
27
+
28
+ ### WS-01 · A phone reads one region at a time
29
+
30
+ Level: SHOULD
31
+ Applies to: a workspace of three regions — a queue, the record opened from it, and what the record is matched against
32
+ Rule: Below 600 pixels the workspace shows the queue, and opening a row goes to the row's own address, where the record's page holds the other two regions, the third under the second; the back gesture returns to the queue.
33
+ Why: Three columns in 390 pixels are three columns nobody can read, and a region hidden on a phone is work a phone reader cannot finish.
34
+ Do: Make the opened record a place in the address at every width, so the selection is a link and the back gesture walks it back. From 600 pixels keep the queue beside the record and draw the record as a `detail-panel` whose `aside` is the third region, so the family decides whether it stands beside or under. Drop nothing: the phone reaches every region, one at a time.
35
+ Don't: Scroll the workspace sideways, hide the third region on a phone, or keep the selection in the page's state alone.
36
+ Check: At 390 pixels, open a row of the queue: the address changes, the record and the third region stand one under the other with no sideways scroll, and the back gesture returns to the queue.
37
+
38
+ ### WS-02 · A score that decides is taken apart
39
+
40
+ Level: SHOULD
41
+ Applies to: a score a person confirms or refuses — a match confidence, a risk rating the reader acts on
42
+ Rule: The score is shown as a table of its criteria, each with the points it earned or none of its points, ending in the summary row that adds back up to the score and says where a cap applies, and its band is one mark beside one sentence giving the thresholds.
43
+ Why: A number or a band alone asks the reader to trust the machine, and a confirmation given on trust is the one a person was asked to give.
44
+ Do: Map each criterion the backend reports to its points, draw the ones the candidate did not earn as "0 of N", sum them in the table's `summary` (RP-07), and state the bands once ("high from 85, medium from 60"). Say the difference between the two compared amounts beside the command that confirms.
45
+ Don't: Show the band twice at two weights (CP-06), or put the reasons in a tooltip.
46
+ Check: Read one score: its criteria rows add up to the summary row, the summary equals the score or names its cap, and the band is stated once with its thresholds.
@@ -139,3 +139,15 @@ Each family is documented in `./<family>.md`.
139
139
  - splitter: Resizable panes divided by a handle.
140
140
  - stack: Column of items with a gap.
141
141
  - visually-hidden: Hides content visually, keeps it for readers.
142
+
143
+ ## Tokens
144
+
145
+ What each theme token is for, with its default value: `./tokens.md`.
146
+
147
+ ## Guidelines
148
+
149
+ Rules for composing screens from these families: `./guidelines/index.md`. Read it before writing a screen.
150
+
151
+ ## Skills
152
+
153
+ Procedures for whole tasks, each with when it applies: `./skills/index.md`.
@@ -51,6 +51,7 @@
51
51
  "root",
52
52
  "section",
53
53
  "section-label",
54
+ "section-end",
54
55
  "section-list",
55
56
  "empty"
56
57
  ]
@@ -78,7 +79,13 @@
78
79
  "part": "section-label",
79
80
  "element": "h1 to h6, or a div",
80
81
  "required": false,
81
- "purpose": "The group name. It carries the id the nested list names itself by, and data-sticky when it has to hold still while its own rows scroll past."
82
+ "purpose": "The group name. It carries the id the nested list names itself by, data-sticky when it has to hold still while its own rows scroll past, and data-variant: caption, the small muted name, or ruled, the name in the text colour over a rule with no ground behind it."
83
+ },
84
+ {
85
+ "part": "section-end",
86
+ "element": "span",
87
+ "required": false,
88
+ "purpose": "What stands at the end of the heading, on the line of the name: a day balance, a count. Set in tabular figures. It is rendered from the end prop."
82
89
  },
83
90
  {
84
91
  "part": "section-list",
@@ -150,6 +157,20 @@
150
157
  "appliesTo": "ListSection",
151
158
  "description": "Keeps a group name in place while its own rows scroll past it"
152
159
  },
160
+ {
161
+ "name": "end",
162
+ "type": "ReactNode",
163
+ "defaultValue": "—",
164
+ "appliesTo": "ListSection",
165
+ "description": "What stands at the end of the group heading, on the line of the name, in tabular figures"
166
+ },
167
+ {
168
+ "name": "labelVariant",
169
+ "type": "'caption' | 'ruled'",
170
+ "defaultValue": "caption",
171
+ "appliesTo": "ListSection",
172
+ "description": "How the group heading is drawn: the small muted name, or the name over a rule with no ground"
173
+ },
153
174
  {
154
175
  "name": "label",
155
176
  "type": "ReactNode",
@@ -213,6 +234,7 @@
213
234
  "--slotted-control-padding-inline-md",
214
235
  "--slotted-control-padding-inline-sm",
215
236
  "--slotted-font-size-xs",
237
+ "--slotted-font-weight-medium",
216
238
  "--slotted-font-weight-semibold",
217
239
  "--slotted-line-height-sm",
218
240
  "--slotted-list-background",
@@ -236,6 +258,8 @@
236
258
  "--slotted-list-section-padding-block",
237
259
  "--slotted-list-section-padding-block-lg",
238
260
  "--slotted-list-section-padding-block-sm",
261
+ "--slotted-list-section-rule-color",
262
+ "--slotted-list-section-ruled-color",
239
263
  "--slotted-radius-md",
240
264
  "--slotted-space-2",
241
265
  "--slotted-space-3",
@@ -245,6 +269,7 @@
245
269
  "--slotted-space-8",
246
270
  "--slotted-space-9",
247
271
  "--slotted-surface",
272
+ "--slotted-text",
248
273
  "--slotted-text-muted",
249
274
  "--slotted-z-index-sticky"
250
275
  ],
package/dist/docs/list.md CHANGED
@@ -33,6 +33,7 @@ Excerpt — not a complete module
33
33
  | `root` | ul or ol, or the element render returns | yes |
34
34
  | `section` | li | no |
35
35
  | `section-label` | h1 to h6, or a div | no |
36
+ | `section-end` | span | no |
36
37
  | `section-list` | ul or ol | no |
37
38
  | `empty` | li | no |
38
39
 
@@ -48,6 +49,8 @@ Excerpt — not a complete module
48
49
  | `loading` | `boolean` | false | List | Writes aria-busy on the set. What stands in for the rows is Skeleton, composed by the page |
49
50
  | `level` | `'none' \| '1' \| '2' \| '3' \| '4' \| '5' \| '6'` | 3 | ListSection | The heading a group name is set as. none renders a div and announces no heading |
50
51
  | `sticky` | `boolean` | false | ListSection | Keeps a group name in place while its own rows scroll past it |
52
+ | `end` | `ReactNode` | — | ListSection | What stands at the end of the group heading, on the line of the name, in tabular figures |
53
+ | `labelVariant` | `'caption' \| 'ruled'` | caption | ListSection | How the group heading is drawn: the small muted name, or the name over a rule with no ground |
51
54
  | `label` | `ReactNode` | — | ListSection | The group name, which the nested list is named by |
52
55
  | `labelProps / listProps` | `HTMLAttributes` | — | ListSection | Reach the heading and the nested list, for an id or a class the page owns |
53
56
  | `render` | `(props) => ReactNode` | — | List, ListSection, ListEmpty | Renders the wiring into another element — a nav, a router own list |
@@ -75,7 +78,7 @@ Excerpt — not a complete module
75
78
 
76
79
  ## Tokens
77
80
 
78
- `--slotted-border-subtle`, `--slotted-border-width-thin`, `--slotted-control-padding-inline-lg`, `--slotted-control-padding-inline-md`, `--slotted-control-padding-inline-sm`, `--slotted-font-size-xs`, `--slotted-font-weight-semibold`, `--slotted-line-height-sm`, `--slotted-list-background`, `--slotted-list-border-color`, `--slotted-list-border-width`, `--slotted-list-empty-color`, `--slotted-list-empty-padding`, `--slotted-list-empty-padding-lg`, `--slotted-list-empty-padding-sm`, `--slotted-list-gap`, `--slotted-list-gap-lg`, `--slotted-list-gap-sm`, `--slotted-list-padding-inline`, `--slotted-list-padding-inline-lg`, `--slotted-list-padding-inline-sm`, `--slotted-list-radius`, `--slotted-list-section-color`, `--slotted-list-section-font-size`, `--slotted-list-section-font-weight`, `--slotted-list-section-letter-spacing`, `--slotted-list-section-padding-block`, `--slotted-list-section-padding-block-lg`, `--slotted-list-section-padding-block-sm`, `--slotted-radius-md`, `--slotted-space-2`, `--slotted-space-3`, `--slotted-space-4`, `--slotted-space-5`, `--slotted-space-6`, `--slotted-space-8`, `--slotted-space-9`, `--slotted-surface`, `--slotted-text-muted`, `--slotted-z-index-sticky`
81
+ `--slotted-border-subtle`, `--slotted-border-width-thin`, `--slotted-control-padding-inline-lg`, `--slotted-control-padding-inline-md`, `--slotted-control-padding-inline-sm`, `--slotted-font-size-xs`, `--slotted-font-weight-medium`, `--slotted-font-weight-semibold`, `--slotted-line-height-sm`, `--slotted-list-background`, `--slotted-list-border-color`, `--slotted-list-border-width`, `--slotted-list-empty-color`, `--slotted-list-empty-padding`, `--slotted-list-empty-padding-lg`, `--slotted-list-empty-padding-sm`, `--slotted-list-gap`, `--slotted-list-gap-lg`, `--slotted-list-gap-sm`, `--slotted-list-padding-inline`, `--slotted-list-padding-inline-lg`, `--slotted-list-padding-inline-sm`, `--slotted-list-radius`, `--slotted-list-section-color`, `--slotted-list-section-font-size`, `--slotted-list-section-font-weight`, `--slotted-list-section-letter-spacing`, `--slotted-list-section-padding-block`, `--slotted-list-section-padding-block-lg`, `--slotted-list-section-padding-block-sm`, `--slotted-list-section-rule-color`, `--slotted-list-section-ruled-color`, `--slotted-radius-md`, `--slotted-space-2`, `--slotted-space-3`, `--slotted-space-4`, `--slotted-space-5`, `--slotted-space-6`, `--slotted-space-8`, `--slotted-space-9`, `--slotted-surface`, `--slotted-text`, `--slotted-text-muted`, `--slotted-z-index-sticky`
79
82
 
80
83
  ## Examples
81
84
 
@@ -144,7 +144,7 @@
144
144
  "part": "content",
145
145
  "element": "div",
146
146
  "required": true,
147
- "purpose": "The panel, with role=\"dialog\" and tabindex=\"-1\". It is named by its title and described by its description when those parts are present. aria-modal is never written, because the popover is not modal."
147
+ "purpose": "The panel, with role=\"dialog\" and tabindex=\"-1\". It is named by its title and described by its description when those parts are present. aria-modal is never written, because the popover is not modal. It draws no padding: PopoverHeader, PopoverBody and PopoverFooter carry the panel inset, set by --slotted-popover-padding-inline and --slotted-popover-padding-block."
148
148
  },
149
149
  {
150
150
  "part": "header",
@@ -330,7 +330,6 @@
330
330
  "--slotted-progress-indicator-wave-phase",
331
331
  "--slotted-radius-full",
332
332
  "--slotted-radius-none",
333
- "--slotted-space-1",
334
333
  "--slotted-space-2",
335
334
  "--slotted-space-3",
336
335
  "--slotted-space-4",
@@ -419,7 +418,7 @@
419
418
  {
420
419
  "id": "waveSizes",
421
420
  "title": "The wave is measured in thicknesses",
422
- "note": "One wavelength is ten thicknesses and a crest is three quarters of one at every size, so the small bar’s wave is twenty pixels long and the large bar’s eighty. Every ring carries eight crests, because the wave is wound on the viewBox and the viewBox scales.",
421
+ "note": "One wavelength is ten thicknesses and a crest is three quarters of one at every size, so the small bar’s wave is forty pixels long and the large bar’s eighty. Every ring carries eight crests, because the wave is wound on the viewBox and the viewBox scales.",
423
422
  "language": "tsx",
424
423
  "source": "<ProgressBar label=\"Small\" size=\"sm\" value={55} wave />;\n<ProgressBar label=\"Large\" size=\"lg\" value={55} wave />;\n<ProgressCircle label=\"Saving\" size=\"lg\" value={55} wave />;\n",
425
424
  "verdict": "excerpt"
@@ -82,7 +82,7 @@ Excerpt — not a complete module
82
82
 
83
83
  ## Tokens
84
84
 
85
- `--slotted-border-strong`, `--slotted-border-width-thin`, `--slotted-control-font-family`, `--slotted-control-font-size-lg`, `--slotted-control-font-size-md`, `--slotted-control-font-size-sm`, `--slotted-control-height-lg`, `--slotted-control-height-md`, `--slotted-control-height-sm`, `--slotted-duration-long`, `--slotted-duration-loop`, `--slotted-duration-loop-slow`, `--slotted-duration-medium`, `--slotted-duration-short`, `--slotted-easing-emphasized`, `--slotted-easing-enter`, `--slotted-easing-exit`, `--slotted-easing-standard`, `--slotted-line-height-md`, `--slotted-progress-indicator-buffer-color`, `--slotted-progress-indicator-buffer-percent`, `--slotted-progress-indicator-gap`, `--slotted-progress-indicator-indicator-color`, `--slotted-progress-indicator-percent`, `--slotted-progress-indicator-position`, `--slotted-progress-indicator-radius`, `--slotted-progress-indicator-size`, `--slotted-progress-indicator-stroke`, `--slotted-progress-indicator-thickness`, `--slotted-progress-indicator-track-color`, `--slotted-progress-indicator-travel-size`, `--slotted-progress-indicator-travel-start`, `--slotted-progress-indicator-wave-amplitude`, `--slotted-progress-indicator-wave-phase`, `--slotted-radius-full`, `--slotted-radius-none`, `--slotted-space-1`, `--slotted-space-2`, `--slotted-space-3`, `--slotted-space-4`, `--slotted-surface`, `--slotted-text`, `--slotted-text-muted`, `--slotted-tone-accent-text`, `--slotted-tone-danger-text`, `--slotted-tone-success-text`, `--slotted-tone-warning-text`, `--slotted-z-index-sticky`
85
+ `--slotted-border-strong`, `--slotted-border-width-thin`, `--slotted-control-font-family`, `--slotted-control-font-size-lg`, `--slotted-control-font-size-md`, `--slotted-control-font-size-sm`, `--slotted-control-height-lg`, `--slotted-control-height-md`, `--slotted-control-height-sm`, `--slotted-duration-long`, `--slotted-duration-loop`, `--slotted-duration-loop-slow`, `--slotted-duration-medium`, `--slotted-duration-short`, `--slotted-easing-emphasized`, `--slotted-easing-enter`, `--slotted-easing-exit`, `--slotted-easing-standard`, `--slotted-line-height-md`, `--slotted-progress-indicator-buffer-color`, `--slotted-progress-indicator-buffer-percent`, `--slotted-progress-indicator-gap`, `--slotted-progress-indicator-indicator-color`, `--slotted-progress-indicator-percent`, `--slotted-progress-indicator-position`, `--slotted-progress-indicator-radius`, `--slotted-progress-indicator-size`, `--slotted-progress-indicator-stroke`, `--slotted-progress-indicator-thickness`, `--slotted-progress-indicator-track-color`, `--slotted-progress-indicator-travel-size`, `--slotted-progress-indicator-travel-start`, `--slotted-progress-indicator-wave-amplitude`, `--slotted-progress-indicator-wave-phase`, `--slotted-radius-full`, `--slotted-radius-none`, `--slotted-space-2`, `--slotted-space-3`, `--slotted-space-4`, `--slotted-surface`, `--slotted-text`, `--slotted-text-muted`, `--slotted-tone-accent-text`, `--slotted-tone-danger-text`, `--slotted-tone-success-text`, `--slotted-tone-warning-text`, `--slotted-z-index-sticky`
86
86
 
87
87
  ## Examples
88
88
 
@@ -191,7 +191,7 @@ Excerpt — not a complete module
191
191
 
192
192
  ### The wave is measured in thicknesses
193
193
 
194
- One wavelength is ten thicknesses and a crest is three quarters of one at every size, so the small bar’s wave is twenty pixels long and the large bar’s eighty. Every ring carries eight crests, because the wave is wound on the viewBox and the viewBox scales.
194
+ One wavelength is ten thicknesses and a crest is three quarters of one at every size, so the small bar’s wave is forty pixels long and the large bar’s eighty. Every ring carries eight crests, because the wave is wound on the viewBox and the viewBox scales.
195
195
 
196
196
  Excerpt — not a complete module
197
197
 
@@ -19,6 +19,10 @@
19
19
  "condense": [
20
20
  "none",
21
21
  "icons"
22
+ ],
23
+ "variant": [
24
+ "track",
25
+ "underline"
22
26
  ]
23
27
  },
24
28
  "members": {
@@ -29,7 +33,8 @@
29
33
  "orientation": "horizontal",
30
34
  "condense": "none",
31
35
  "fullWidth": false,
32
- "disabled": false
36
+ "disabled": false,
37
+ "variant": "track"
33
38
  },
34
39
  "capabilities": [
35
40
  "selection",
@@ -143,6 +148,13 @@
143
148
  "appliesTo": "SegmentedControl",
144
149
  "description": "How the segments flow and which way the thumb travels. A horizontal set writes aria-orientation, because radiogroup already implies vertical"
145
150
  },
151
+ {
152
+ "name": "variant",
153
+ "type": "'track' | 'underline'",
154
+ "defaultValue": "track",
155
+ "appliesTo": "SegmentedControl",
156
+ "description": "How the choice is drawn: a track with a thumb, or the words alone with the chosen one underlined"
157
+ },
146
158
  {
147
159
  "name": "condense",
148
160
  "type": "'none' | 'icons'",
@@ -269,6 +281,7 @@
269
281
  },
270
282
  "tokens": [
271
283
  "--slotted-border-subtle",
284
+ "--slotted-border-width-thick",
272
285
  "--slotted-control-border-color",
273
286
  "--slotted-control-border-width",
274
287
  "--slotted-control-font-family",
@@ -304,7 +317,9 @@
304
317
  "--slotted-easing-standard",
305
318
  "--slotted-focus-ring-color",
306
319
  "--slotted-focus-ring-color-invalid",
320
+ "--slotted-focus-ring-offset",
307
321
  "--slotted-focus-ring-width",
322
+ "--slotted-font-weight-medium",
308
323
  "--slotted-radius-xs",
309
324
  "--slotted-segmented-control-active-background",
310
325
  "--slotted-segmented-control-background",
@@ -324,9 +339,14 @@
324
339
  "--slotted-segmented-control-invalid-focus-ring-color",
325
340
  "--slotted-segmented-control-radius",
326
341
  "--slotted-segmented-control-shadow",
342
+ "--slotted-segmented-control-underline-checked-color",
343
+ "--slotted-segmented-control-underline-color",
344
+ "--slotted-segmented-control-underline-gap",
327
345
  "--slotted-space-1",
346
+ "--slotted-space-6",
328
347
  "--slotted-target-min",
329
348
  "--slotted-text",
349
+ "--slotted-text-muted",
330
350
  "--slotted-tone-accent-border",
331
351
  "--slotted-tone-accent-subtle-active",
332
352
  "--slotted-tone-accent-text",
@@ -375,6 +395,14 @@
375
395
  "source": "<SegmentedControl aria-label=\"Alinhamento\" defaultValue=\"center\">\n <Segment aria-label=\"Início\" icon={<AlignStartIcon />} value=\"start\" />\n <Segment aria-label=\"Centro\" icon={<AlignCenterIcon />} value=\"center\" />\n</SegmentedControl>;\n",
376
396
  "verdict": "excerpt"
377
397
  },
398
+ {
399
+ "id": "variants",
400
+ "title": "A track, or the words alone",
401
+ "note": "underline draws the same radio group as words: each as wide as itself, the chosen one in the text colour and underlined, the others muted. One tab stop, the arrows move the value, and inside a field the label names the set.",
402
+ "language": "tsx",
403
+ "source": "<SegmentedControl aria-label=\"Período\" defaultValue=\"month\" variant=\"underline\">\n <Segment value=\"day\">Dia</Segment>\n <Segment value=\"week\">Semana</Segment>\n <Segment value=\"month\">Mês</Segment>\n</SegmentedControl>;\n",
404
+ "verdict": "excerpt"
405
+ },
378
406
  {
379
407
  "id": "condense",
380
408
  "title": "Narrower than its words",
@@ -41,6 +41,7 @@ Excerpt — not a complete module
41
41
  | `name` | `string` | — | SegmentedControl | The submission name the segments share, and the reason the platform treats them as one radio group. Generated when none is written, and the cost is that such a control submits under a generated key |
42
42
  | `size` | `'sm' \| 'md' \| 'lg'` | md | SegmentedControl | The control step. The track measures its segments back from it, so the whole control is exactly as tall as the field beside it |
43
43
  | `orientation` | `'horizontal' \| 'vertical'` | horizontal | SegmentedControl | How the segments flow and which way the thumb travels. A horizontal set writes aria-orientation, because radiogroup already implies vertical |
44
+ | `variant` | `'track' \| 'underline'` | track | SegmentedControl | How the choice is drawn: a track with a thumb, or the words alone with the chosen one underlined |
44
45
  | `condense` | `'none' \| 'icons'` | none | SegmentedControl | What the control does when it is narrower than its labels need. icons keeps the marks and hides the words, and makes the control take its parent’s width so there is a width to ask a question about |
45
46
  | `fullWidth` | `boolean` | false | SegmentedControl | Whether the equal columns spread across the whole line. Left alone every column is the widest label’s |
46
47
  | `disabled` | `boolean` | false | SegmentedControl | Unstated rather than false, so the control defers to the field around it. Stated, it reaches every radio as the native attribute, which is also what makes the browser skip it with the arrows |
@@ -70,6 +71,7 @@ Excerpt — not a complete module
70
71
  | `size` | `sm`, `md`, `lg` | `md` |
71
72
  | `orientation` | `horizontal`, `vertical` | `horizontal` |
72
73
  | `condense` | `none`, `icons` | `none` |
74
+ | `variant` | `track`, `underline` | `track` |
73
75
 
74
76
  ## Rules
75
77
 
@@ -83,7 +85,7 @@ Excerpt — not a complete module
83
85
 
84
86
  ## Tokens
85
87
 
86
- `--slotted-border-subtle`, `--slotted-control-border-color`, `--slotted-control-border-width`, `--slotted-control-font-family`, `--slotted-control-font-size-lg`, `--slotted-control-font-size-md`, `--slotted-control-font-size-sm`, `--slotted-control-font-weight`, `--slotted-control-gap-lg`, `--slotted-control-gap-md`, `--slotted-control-gap-sm`, `--slotted-control-height-lg`, `--slotted-control-height-md`, `--slotted-control-height-sm`, `--slotted-control-icon-size-lg`, `--slotted-control-icon-size-md`, `--slotted-control-icon-size-sm`, `--slotted-control-invalid-edge-width`, `--slotted-control-letter-spacing`, `--slotted-control-line-height`, `--slotted-control-padding-inline-lg`, `--slotted-control-padding-inline-md`, `--slotted-control-padding-inline-sm`, `--slotted-control-radius`, `--slotted-control-shadow`, `--slotted-control-surface`, `--slotted-control-transition-duration`, `--slotted-control-transition-easing`, `--slotted-disabled-background`, `--slotted-disabled-border`, `--slotted-disabled-foreground`, `--slotted-duration-instant`, `--slotted-duration-medium`, `--slotted-easing-standard`, `--slotted-focus-ring-color`, `--slotted-focus-ring-color-invalid`, `--slotted-focus-ring-width`, `--slotted-radius-xs`, `--slotted-segmented-control-active-background`, `--slotted-segmented-control-background`, `--slotted-segmented-control-border-color`, `--slotted-segmented-control-checked-color`, `--slotted-segmented-control-color`, `--slotted-segmented-control-disabled-border-color`, `--slotted-segmented-control-disabled-color`, `--slotted-segmented-control-disabled-indicator-background`, `--slotted-segmented-control-divider-color`, `--slotted-segmented-control-hover-background`, `--slotted-segmented-control-indicator-background`, `--slotted-segmented-control-indicator-border-color`, `--slotted-segmented-control-inset`, `--slotted-segmented-control-invalid-border-color`, `--slotted-segmented-control-invalid-edge-width`, `--slotted-segmented-control-invalid-focus-ring-color`, `--slotted-segmented-control-radius`, `--slotted-segmented-control-shadow`, `--slotted-space-1`, `--slotted-target-min`, `--slotted-text`, `--slotted-tone-accent-border`, `--slotted-tone-accent-subtle-active`, `--slotted-tone-accent-text`, `--slotted-tone-danger-border`, `--slotted-tone-secondary-subtle-active`, `--slotted-tone-secondary-subtle-hover`
88
+ `--slotted-border-subtle`, `--slotted-border-width-thick`, `--slotted-control-border-color`, `--slotted-control-border-width`, `--slotted-control-font-family`, `--slotted-control-font-size-lg`, `--slotted-control-font-size-md`, `--slotted-control-font-size-sm`, `--slotted-control-font-weight`, `--slotted-control-gap-lg`, `--slotted-control-gap-md`, `--slotted-control-gap-sm`, `--slotted-control-height-lg`, `--slotted-control-height-md`, `--slotted-control-height-sm`, `--slotted-control-icon-size-lg`, `--slotted-control-icon-size-md`, `--slotted-control-icon-size-sm`, `--slotted-control-invalid-edge-width`, `--slotted-control-letter-spacing`, `--slotted-control-line-height`, `--slotted-control-padding-inline-lg`, `--slotted-control-padding-inline-md`, `--slotted-control-padding-inline-sm`, `--slotted-control-radius`, `--slotted-control-shadow`, `--slotted-control-surface`, `--slotted-control-transition-duration`, `--slotted-control-transition-easing`, `--slotted-disabled-background`, `--slotted-disabled-border`, `--slotted-disabled-foreground`, `--slotted-duration-instant`, `--slotted-duration-medium`, `--slotted-easing-standard`, `--slotted-focus-ring-color`, `--slotted-focus-ring-color-invalid`, `--slotted-focus-ring-offset`, `--slotted-focus-ring-width`, `--slotted-font-weight-medium`, `--slotted-radius-xs`, `--slotted-segmented-control-active-background`, `--slotted-segmented-control-background`, `--slotted-segmented-control-border-color`, `--slotted-segmented-control-checked-color`, `--slotted-segmented-control-color`, `--slotted-segmented-control-disabled-border-color`, `--slotted-segmented-control-disabled-color`, `--slotted-segmented-control-disabled-indicator-background`, `--slotted-segmented-control-divider-color`, `--slotted-segmented-control-hover-background`, `--slotted-segmented-control-indicator-background`, `--slotted-segmented-control-indicator-border-color`, `--slotted-segmented-control-inset`, `--slotted-segmented-control-invalid-border-color`, `--slotted-segmented-control-invalid-edge-width`, `--slotted-segmented-control-invalid-focus-ring-color`, `--slotted-segmented-control-radius`, `--slotted-segmented-control-shadow`, `--slotted-segmented-control-underline-checked-color`, `--slotted-segmented-control-underline-color`, `--slotted-segmented-control-underline-gap`, `--slotted-space-1`, `--slotted-space-6`, `--slotted-target-min`, `--slotted-text`, `--slotted-text-muted`, `--slotted-tone-accent-border`, `--slotted-tone-accent-subtle-active`, `--slotted-tone-accent-text`, `--slotted-tone-danger-border`, `--slotted-tone-secondary-subtle-active`, `--slotted-tone-secondary-subtle-hover`
87
89
 
88
90
  ## Examples
89
91
 
@@ -143,6 +145,20 @@ Excerpt — not a complete module
143
145
  </SegmentedControl>;
144
146
  ```
145
147
 
148
+ ### A track, or the words alone
149
+
150
+ underline draws the same radio group as words: each as wide as itself, the chosen one in the text colour and underlined, the others muted. One tab stop, the arrows move the value, and inside a field the label names the set.
151
+
152
+ Excerpt — not a complete module
153
+
154
+ ```tsx
155
+ <SegmentedControl aria-label="Período" defaultValue="month" variant="underline">
156
+ <Segment value="day">Dia</Segment>
157
+ <Segment value="week">Semana</Segment>
158
+ <Segment value="month">Mês</Segment>
159
+ </SegmentedControl>;
160
+ ```
161
+
146
162
  ### Narrower than its words
147
163
 
148
164
  Below the width its labels need, a control told to condense keeps its marks and hides its words — hidden, never removed, so every segment is announced the same at every width.
@@ -553,9 +553,9 @@
553
553
  {
554
554
  "id": "current",
555
555
  "title": "Where the reader is",
556
- "note": "value on the root names the destination and a press asks it to move; a link that states current itself wins. The parent of a hidden destination is marked until its group opens, and autoExpand opens it.",
556
+ "note": "value on the root names the destination and a press asks it to move; a link that states current itself wins. The parent of a hidden destination is marked until its group opens, and autoExpand opens it. With a router, usePressSelection paints the press before the route renders: the item is current at once, and the navigation runs after the frame that shows it. A click carrying a modifier key is left to the browser.",
557
557
  "language": "tsx",
558
- "source": "const [value, setValue] = useState<string | null>('orders');\n\n<SideNavigation value={value} onValueChange={(next) => setValue(next)}>\n …\n</SideNavigation>;\n",
558
+ "source": "const { pathname } = useLocation();\nconst navigate = useNavigate();\nconst { selected, select } = usePressSelection(pathname);\n\nconst press = (to: string) => (event: MouseEvent) => {\n if (event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) {\n return;\n }\n event.preventDefault();\n select(to, () => navigate(to));\n};\n\n<SideNavigation value={selected ?? null}>\n …\n <SideNavigationItem value=\"/orders\">\n <SideNavigationLink href=\"/orders\" onClick={press('/orders')}>\n Orders\n </SideNavigationLink>\n </SideNavigationItem>\n</SideNavigation>;\n",
559
559
  "verdict": "excerpt"
560
560
  },
561
561
  {
@@ -272,15 +272,30 @@ Excerpt — not a complete module
272
272
 
273
273
  ### Where the reader is
274
274
 
275
- value on the root names the destination and a press asks it to move; a link that states current itself wins. The parent of a hidden destination is marked until its group opens, and autoExpand opens it.
275
+ value on the root names the destination and a press asks it to move; a link that states current itself wins. The parent of a hidden destination is marked until its group opens, and autoExpand opens it. With a router, usePressSelection paints the press before the route renders: the item is current at once, and the navigation runs after the frame that shows it. A click carrying a modifier key is left to the browser.
276
276
 
277
277
  Excerpt — not a complete module
278
278
 
279
279
  ```tsx
280
- const [value, setValue] = useState<string | null>('orders');
281
-
282
- <SideNavigation value={value} onValueChange={(next) => setValue(next)}>
280
+ const { pathname } = useLocation();
281
+ const navigate = useNavigate();
282
+ const { selected, select } = usePressSelection(pathname);
283
+
284
+ const press = (to: string) => (event: MouseEvent) => {
285
+ if (event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) {
286
+ return;
287
+ }
288
+ event.preventDefault();
289
+ select(to, () => navigate(to));
290
+ };
291
+
292
+ <SideNavigation value={selected ?? null}>
283
293
  …
294
+ <SideNavigationItem value="/orders">
295
+ <SideNavigationLink href="/orders" onClick={press('/orders')}>
296
+ Orders
297
+ </SideNavigationLink>
298
+ </SideNavigationItem>
284
299
  </SideNavigation>;
285
300
  ```
286
301