cursedbelt 5.40.0 โ†’ 5.45.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 (499) hide show
  1. package/dist/react/Toast.d.ts +12 -2
  2. package/dist/react/Toast.d.ts.map +1 -1
  3. package/dist/react/Toast.js +32 -3
  4. package/dist/react/Toast.js.map +1 -1
  5. package/dist/react/analytics/MetricDrilldown.js +1 -1
  6. package/dist/react/charts/AreaChart.d.ts.map +1 -1
  7. package/dist/react/charts/AreaChart.js +5 -5
  8. package/dist/react/charts/AreaChart.js.map +1 -1
  9. package/dist/react/charts/BarChart.d.ts.map +1 -1
  10. package/dist/react/charts/BarChart.js +3 -3
  11. package/dist/react/charts/BarChart.js.map +1 -1
  12. package/dist/react/charts/ChartCard.d.ts +53 -0
  13. package/dist/react/charts/ChartCard.d.ts.map +1 -0
  14. package/dist/react/charts/ChartCard.js +46 -0
  15. package/dist/react/charts/ChartCard.js.map +1 -0
  16. package/dist/react/charts/ChartFrame.d.ts +12 -5
  17. package/dist/react/charts/ChartFrame.d.ts.map +1 -1
  18. package/dist/react/charts/ChartFrame.js +12 -5
  19. package/dist/react/charts/ChartFrame.js.map +1 -1
  20. package/dist/react/charts/ChartLegend.js +1 -1
  21. package/dist/react/charts/ChartLegend.js.map +1 -1
  22. package/dist/react/charts/HeatmapChart.js +3 -3
  23. package/dist/react/charts/HeatmapChart.js.map +1 -1
  24. package/dist/react/charts/IntervalTimeline.js +1 -1
  25. package/dist/react/charts/IntervalTimeline.js.map +1 -1
  26. package/dist/react/charts/LineChart.d.ts.map +1 -1
  27. package/dist/react/charts/LineChart.js +3 -3
  28. package/dist/react/charts/LineChart.js.map +1 -1
  29. package/dist/react/charts/TimeSeriesChart.d.ts.map +1 -1
  30. package/dist/react/charts/TimeSeriesChart.js +6 -6
  31. package/dist/react/charts/TimeSeriesChart.js.map +1 -1
  32. package/dist/react/charts/chartBox.d.ts +46 -0
  33. package/dist/react/charts/chartBox.d.ts.map +1 -0
  34. package/dist/react/charts/chartBox.js +45 -0
  35. package/dist/react/charts/chartBox.js.map +1 -0
  36. package/dist/react/charts/index.d.ts +2 -0
  37. package/dist/react/charts/index.d.ts.map +1 -1
  38. package/dist/react/charts/index.js +2 -0
  39. package/dist/react/charts/index.js.map +1 -1
  40. package/dist/react/charts/shared.d.ts +13 -2
  41. package/dist/react/charts/shared.d.ts.map +1 -1
  42. package/dist/react/charts/shared.js +14 -3
  43. package/dist/react/charts/shared.js.map +1 -1
  44. package/dist/react/chat/Bubble.js +4 -4
  45. package/dist/react/chat/Bubble.js.map +1 -1
  46. package/dist/react/chat/MessageScroller.js +1 -1
  47. package/dist/react/chat/MessageScroller.js.map +1 -1
  48. package/dist/react/components/ActionBar.d.ts.map +1 -1
  49. package/dist/react/components/ActionBar.js +63 -1
  50. package/dist/react/components/ActionBar.js.map +1 -1
  51. package/dist/react/components/AddItemsMenu.js +1 -1
  52. package/dist/react/components/AddItemsMenu.js.map +1 -1
  53. package/dist/react/components/Alert.d.ts +16 -2
  54. package/dist/react/components/Alert.d.ts.map +1 -1
  55. package/dist/react/components/Alert.js +35 -2
  56. package/dist/react/components/Alert.js.map +1 -1
  57. package/dist/react/components/AppShell.d.ts +55 -33
  58. package/dist/react/components/AppShell.d.ts.map +1 -1
  59. package/dist/react/components/AppShell.js +121 -31
  60. package/dist/react/components/AppShell.js.map +1 -1
  61. package/dist/react/components/AsyncPanel.d.ts +21 -3
  62. package/dist/react/components/AsyncPanel.d.ts.map +1 -1
  63. package/dist/react/components/AsyncPanel.js +49 -5
  64. package/dist/react/components/AsyncPanel.js.map +1 -1
  65. package/dist/react/components/BannerLane.d.ts +32 -0
  66. package/dist/react/components/BannerLane.d.ts.map +1 -0
  67. package/dist/react/components/BannerLane.js +41 -0
  68. package/dist/react/components/BannerLane.js.map +1 -0
  69. package/dist/react/components/Button.d.ts.map +1 -1
  70. package/dist/react/components/Button.js +2 -1
  71. package/dist/react/components/Button.js.map +1 -1
  72. package/dist/react/components/ChipFilterStrip.js +1 -1
  73. package/dist/react/components/ChipFilterStrip.js.map +1 -1
  74. package/dist/react/components/ComboboxField.d.ts.map +1 -1
  75. package/dist/react/components/ComboboxField.js +14 -4
  76. package/dist/react/components/ComboboxField.js.map +1 -1
  77. package/dist/react/components/CommentThread.js +2 -2
  78. package/dist/react/components/CommentThread.js.map +1 -1
  79. package/dist/react/components/ConfirmDialog.js +1 -1
  80. package/dist/react/components/ConfirmDialog.js.map +1 -1
  81. package/dist/react/components/DataTable/DataTable.d.ts +18 -2
  82. package/dist/react/components/DataTable/DataTable.d.ts.map +1 -1
  83. package/dist/react/components/DataTable/DataTable.js +51 -12
  84. package/dist/react/components/DataTable/DataTable.js.map +1 -1
  85. package/dist/react/components/DataTable/Pagination.js +1 -1
  86. package/dist/react/components/DataTable/Pagination.js.map +1 -1
  87. package/dist/react/components/DataTable/RowActions.d.ts +7 -1
  88. package/dist/react/components/DataTable/RowActions.d.ts.map +1 -1
  89. package/dist/react/components/DataTable/RowActions.js +10 -3
  90. package/dist/react/components/DataTable/RowActions.js.map +1 -1
  91. package/dist/react/components/DataTable/TableFilterBuilder.js +1 -1
  92. package/dist/react/components/DataTable/TableFilterBuilder.js.map +1 -1
  93. package/dist/react/components/DataTable/cells/CodeCell.js +1 -1
  94. package/dist/react/components/DataTable/cells/CodeCell.js.map +1 -1
  95. package/dist/react/components/DataTable/cells/LinkCell.js +1 -1
  96. package/dist/react/components/DataTable/cells/LinkCell.js.map +1 -1
  97. package/dist/react/components/DataTable/index.d.ts +1 -1
  98. package/dist/react/components/DataTable/index.d.ts.map +1 -1
  99. package/dist/react/components/DataTable/index.js.map +1 -1
  100. package/dist/react/components/DataTable/types.d.ts +20 -0
  101. package/dist/react/components/DataTable/types.d.ts.map +1 -1
  102. package/dist/react/components/DataTable/types.js +22 -0
  103. package/dist/react/components/DataTable/types.js.map +1 -1
  104. package/dist/react/components/DateTimeField.d.ts.map +1 -1
  105. package/dist/react/components/DateTimeField.js +4 -1
  106. package/dist/react/components/DateTimeField.js.map +1 -1
  107. package/dist/react/components/DeleteButton.js +2 -0
  108. package/dist/react/components/DeleteButton.js.map +1 -1
  109. package/dist/react/components/Drawer.js +3 -3
  110. package/dist/react/components/Drawer.js.map +1 -1
  111. package/dist/react/components/DropdownMenu.d.ts +16 -0
  112. package/dist/react/components/DropdownMenu.d.ts.map +1 -1
  113. package/dist/react/components/DropdownMenu.js +22 -6
  114. package/dist/react/components/DropdownMenu.js.map +1 -1
  115. package/dist/react/components/EmptyState.d.ts +10 -2
  116. package/dist/react/components/EmptyState.d.ts.map +1 -1
  117. package/dist/react/components/EmptyState.js +10 -5
  118. package/dist/react/components/EmptyState.js.map +1 -1
  119. package/dist/react/components/EventTimeline.js +1 -1
  120. package/dist/react/components/EventTimeline.js.map +1 -1
  121. package/dist/react/components/FileDropZone.js +1 -1
  122. package/dist/react/components/FileDropZone.js.map +1 -1
  123. package/dist/react/components/Grid.d.ts +9 -1
  124. package/dist/react/components/Grid.d.ts.map +1 -1
  125. package/dist/react/components/Grid.js +20 -2
  126. package/dist/react/components/Grid.js.map +1 -1
  127. package/dist/react/components/Guide.d.ts +31 -0
  128. package/dist/react/components/Guide.d.ts.map +1 -0
  129. package/dist/react/components/Guide.js +18 -0
  130. package/dist/react/components/Guide.js.map +1 -0
  131. package/dist/react/components/InfoHintImpl.d.ts +0 -13
  132. package/dist/react/components/InfoHintImpl.d.ts.map +1 -1
  133. package/dist/react/components/InfoHintImpl.js +17 -1
  134. package/dist/react/components/InfoHintImpl.js.map +1 -1
  135. package/dist/react/components/InlineEditableText.js +1 -1
  136. package/dist/react/components/InlineEditableText.js.map +1 -1
  137. package/dist/react/components/IsolatedFrame.js +1 -1
  138. package/dist/react/components/IsolatedFrame.js.map +1 -1
  139. package/dist/react/components/ListToolbar.d.ts.map +1 -1
  140. package/dist/react/components/ListToolbar.js +2 -2
  141. package/dist/react/components/ListToolbar.js.map +1 -1
  142. package/dist/react/components/LogViewer.d.ts +26 -2
  143. package/dist/react/components/LogViewer.d.ts.map +1 -1
  144. package/dist/react/components/LogViewer.js +41 -26
  145. package/dist/react/components/LogViewer.js.map +1 -1
  146. package/dist/react/components/Modal.d.ts +5 -1
  147. package/dist/react/components/Modal.d.ts.map +1 -1
  148. package/dist/react/components/Modal.js +18 -8
  149. package/dist/react/components/Modal.js.map +1 -1
  150. package/dist/react/components/Page.d.ts +51 -7
  151. package/dist/react/components/Page.d.ts.map +1 -1
  152. package/dist/react/components/Page.js +53 -8
  153. package/dist/react/components/Page.js.map +1 -1
  154. package/dist/react/components/PageGuideButton.d.ts +11 -0
  155. package/dist/react/components/PageGuideButton.d.ts.map +1 -0
  156. package/dist/react/components/PageGuideButton.js +13 -0
  157. package/dist/react/components/PageGuideButton.js.map +1 -0
  158. package/dist/react/components/PanelSeparator.js +1 -1
  159. package/dist/react/components/PanelSeparator.js.map +1 -1
  160. package/dist/react/components/Popover.d.ts.map +1 -1
  161. package/dist/react/components/Popover.js +2 -1
  162. package/dist/react/components/Popover.js.map +1 -1
  163. package/dist/react/components/PromptDialog.js +1 -1
  164. package/dist/react/components/PromptDialog.js.map +1 -1
  165. package/dist/react/components/ScrollArea.d.ts +9 -1
  166. package/dist/react/components/ScrollArea.d.ts.map +1 -1
  167. package/dist/react/components/ScrollArea.js +9 -3
  168. package/dist/react/components/ScrollArea.js.map +1 -1
  169. package/dist/react/components/Section.d.ts +5 -2
  170. package/dist/react/components/Section.d.ts.map +1 -1
  171. package/dist/react/components/Section.js +5 -2
  172. package/dist/react/components/Section.js.map +1 -1
  173. package/dist/react/components/Skeleton.d.ts +19 -1
  174. package/dist/react/components/Skeleton.d.ts.map +1 -1
  175. package/dist/react/components/Skeleton.js +24 -2
  176. package/dist/react/components/Skeleton.js.map +1 -1
  177. package/dist/react/components/StatStrip.js +1 -1
  178. package/dist/react/components/StatStrip.js.map +1 -1
  179. package/dist/react/components/StatTile.d.ts +30 -3
  180. package/dist/react/components/StatTile.d.ts.map +1 -1
  181. package/dist/react/components/StatTile.js +35 -9
  182. package/dist/react/components/StatTile.js.map +1 -1
  183. package/dist/react/components/StatTileGrid.d.ts +10 -1
  184. package/dist/react/components/StatTileGrid.d.ts.map +1 -1
  185. package/dist/react/components/StatTileGrid.js +50 -33
  186. package/dist/react/components/StatTileGrid.js.map +1 -1
  187. package/dist/react/components/StatusPill.d.ts.map +1 -1
  188. package/dist/react/components/StatusPill.js +26 -1
  189. package/dist/react/components/StatusPill.js.map +1 -1
  190. package/dist/react/components/Surface.d.ts +1 -1
  191. package/dist/react/components/Surface.d.ts.map +1 -1
  192. package/dist/react/components/Surface.js +20 -11
  193. package/dist/react/components/Surface.js.map +1 -1
  194. package/dist/react/components/SwatchPicker.d.ts.map +1 -1
  195. package/dist/react/components/SwatchPicker.js +5 -1
  196. package/dist/react/components/SwatchPicker.js.map +1 -1
  197. package/dist/react/components/Switch.js +1 -1
  198. package/dist/react/components/Switch.js.map +1 -1
  199. package/dist/react/components/WidgetHeader.js +1 -1
  200. package/dist/react/components/WidgetHeader.js.map +1 -1
  201. package/dist/react/components/calendar/CalendarLegend.js +1 -1
  202. package/dist/react/components/calendar/CalendarLegend.js.map +1 -1
  203. package/dist/react/components/calendar/DayAgenda.js +1 -1
  204. package/dist/react/components/calendar/DayAgenda.js.map +1 -1
  205. package/dist/react/components/calendar/EventChip.js +1 -1
  206. package/dist/react/components/calendar/EventChip.js.map +1 -1
  207. package/dist/react/components/calendar/MonthGrid.js +1 -1
  208. package/dist/react/components/calendar/MonthGrid.js.map +1 -1
  209. package/dist/react/components/calendar/WeekView.js +2 -2
  210. package/dist/react/components/calendar/WeekView.js.map +1 -1
  211. package/dist/react/components/cardFrame.d.ts +16 -0
  212. package/dist/react/components/cardFrame.d.ts.map +1 -0
  213. package/dist/react/components/cardFrame.js +24 -0
  214. package/dist/react/components/cardFrame.js.map +1 -0
  215. package/dist/react/components/dialog.d.ts.map +1 -1
  216. package/dist/react/components/dialog.js +2 -1
  217. package/dist/react/components/dialog.js.map +1 -1
  218. package/dist/react/dashboard-grid/WidgetFrame.js +2 -2
  219. package/dist/react/dashboard-grid/WidgetFrame.js.map +1 -1
  220. package/dist/react/emoji/EmojiPicker.js +1 -1
  221. package/dist/react/emoji/EmojiPicker.js.map +1 -1
  222. package/dist/react/file-tree/FileTree.d.ts +8 -1
  223. package/dist/react/file-tree/FileTree.d.ts.map +1 -1
  224. package/dist/react/file-tree/FileTree.js +29 -4
  225. package/dist/react/file-tree/FileTree.js.map +1 -1
  226. package/dist/react/filter-rail/FilterRail.js +1 -1
  227. package/dist/react/filter-rail/FilterRail.js.map +1 -1
  228. package/dist/react/icons.js +1 -1
  229. package/dist/react/icons.js.map +1 -1
  230. package/dist/react/index.d.ts +8 -5
  231. package/dist/react/index.d.ts.map +1 -1
  232. package/dist/react/index.js +5 -2
  233. package/dist/react/index.js.map +1 -1
  234. package/dist/react/lib/menuSections.d.ts +8 -0
  235. package/dist/react/lib/menuSections.d.ts.map +1 -0
  236. package/dist/react/lib/menuSections.js +37 -0
  237. package/dist/react/lib/menuSections.js.map +1 -0
  238. package/dist/react/markdown/Markdown.js +2 -2
  239. package/dist/react/markdown/Markdown.js.map +1 -1
  240. package/dist/react/media/HoverScrubVideoThumb.js +1 -1
  241. package/dist/react/media/HoverScrubVideoThumb.js.map +1 -1
  242. package/dist/react/media/MaskPainter.js +1 -1
  243. package/dist/react/media/MediaUploadControl.js +1 -1
  244. package/dist/react/media/MediaUploadControl.js.map +1 -1
  245. package/dist/react/media/VideoTrimmer.js +1 -1
  246. package/dist/react/media/VideoTrimmer.js.map +1 -1
  247. package/dist/react/media/denseGallery.css +5 -1
  248. package/dist/react/namespace/NamespaceTargetCapsule.js +1 -1
  249. package/dist/react/namespace/NamespaceTargetCapsule.js.map +1 -1
  250. package/dist/react/nav/BreadcrumbTrail.js +1 -1
  251. package/dist/react/nav/BreadcrumbTrail.js.map +1 -1
  252. package/dist/react/nav/CommandBar.d.ts +7 -1
  253. package/dist/react/nav/CommandBar.d.ts.map +1 -1
  254. package/dist/react/nav/CommandBar.js +5 -3
  255. package/dist/react/nav/CommandBar.js.map +1 -1
  256. package/dist/react/nav/PlaceBar.d.ts.map +1 -1
  257. package/dist/react/nav/PlaceBar.js +7 -9
  258. package/dist/react/nav/PlaceBar.js.map +1 -1
  259. package/dist/react/nav/SideNav.d.ts +12 -2
  260. package/dist/react/nav/SideNav.d.ts.map +1 -1
  261. package/dist/react/nav/SideNav.js +42 -22
  262. package/dist/react/nav/SideNav.js.map +1 -1
  263. package/dist/react/nav/TopBar.d.ts +65 -31
  264. package/dist/react/nav/TopBar.d.ts.map +1 -1
  265. package/dist/react/nav/TopBar.js +59 -24
  266. package/dist/react/nav/TopBar.js.map +1 -1
  267. package/dist/react/nav/index.d.ts +1 -1
  268. package/dist/react/nav/index.d.ts.map +1 -1
  269. package/dist/react/nav/index.js +1 -1
  270. package/dist/react/nav/index.js.map +1 -1
  271. package/dist/react/nav/navShared.d.ts +10 -1
  272. package/dist/react/nav/navShared.d.ts.map +1 -1
  273. package/dist/react/nav/navShared.js +23 -0
  274. package/dist/react/nav/navShared.js.map +1 -1
  275. package/dist/react/notifications/NotificationFeed.js +2 -2
  276. package/dist/react/notifications/NotificationFeed.js.map +1 -1
  277. package/dist/react/palette/Command.d.ts.map +1 -1
  278. package/dist/react/palette/Command.js +1 -1
  279. package/dist/react/palette/Command.js.map +1 -1
  280. package/dist/react/palette/CommandPalette.d.ts +13 -1
  281. package/dist/react/palette/CommandPalette.d.ts.map +1 -1
  282. package/dist/react/palette/CommandPalette.js +44 -8
  283. package/dist/react/palette/CommandPalette.js.map +1 -1
  284. package/dist/react/palette/commandSources.d.ts +57 -0
  285. package/dist/react/palette/commandSources.d.ts.map +1 -0
  286. package/dist/react/palette/commandSources.js +129 -0
  287. package/dist/react/palette/commandSources.js.map +1 -0
  288. package/dist/react/palette/index.d.ts +1 -0
  289. package/dist/react/palette/index.d.ts.map +1 -1
  290. package/dist/react/palette/index.js +1 -0
  291. package/dist/react/palette/index.js.map +1 -1
  292. package/dist/react/rich-text/RichTextEditor.js +1 -1
  293. package/dist/react/rich-text/RichTextEditor.js.map +1 -1
  294. package/dist/react/rich-text/RichTextToolbar.js +1 -1
  295. package/dist/react/rich-text/RichTextToolbar.js.map +1 -1
  296. package/dist/scripts/guardrailsEnforce.d.ts.map +1 -1
  297. package/dist/styles-areas/analytics.css +16 -16
  298. package/dist/styles-areas/auth.css +3 -3
  299. package/dist/styles-areas/calendar.css +6 -6
  300. package/dist/styles-areas/chart-table.css +1 -1
  301. package/dist/styles-areas/charts.css +3 -3
  302. package/dist/styles-areas/chat.css +7 -6
  303. package/dist/styles-areas/companion-link.css +2 -2
  304. package/dist/styles-areas/core.css +98 -89
  305. package/dist/styles-areas/dashboard-grid.css +4 -4
  306. package/dist/styles-areas/data-table.css +16 -16
  307. package/dist/styles-areas/disk-usage.css +5 -5
  308. package/dist/styles-areas/emoji.css +2 -2
  309. package/dist/styles-areas/fields.css +13 -14
  310. package/dist/styles-areas/filter-rail.css +4 -4
  311. package/dist/styles-areas/folder-tree.css +3 -3
  312. package/dist/styles-areas/markdown.css +2 -1
  313. package/dist/styles-areas/master-detail.css +3 -3
  314. package/dist/styles-areas/media-gallery.css +8 -8
  315. package/dist/styles-areas/media.css +12 -13
  316. package/dist/styles-areas/nav.css +28 -14
  317. package/dist/styles-areas/notifications.css +4 -4
  318. package/dist/styles-areas/overlays.css +4 -4
  319. package/dist/styles-areas/palette.css +4 -3
  320. package/dist/styles-areas/rich-text.css +3 -3
  321. package/dist/styles-areas/sharing.css +4 -3
  322. package/dist/styles-areas/stats.css +9 -8
  323. package/dist/styles-areas/test-report.css +3 -3
  324. package/dist/styles-areas/wizard.css +6 -5
  325. package/dist/styles-areas/workbench.css +10 -9
  326. package/dist/styles-areas/workbook-viewer.css +2 -2
  327. package/dist/styles-utilities.css +272 -187
  328. package/dist/testing/designAudit.d.ts.map +1 -1
  329. package/dist/testing/designAudit.js +4 -0
  330. package/dist/testing/designAudit.js.map +1 -1
  331. package/dist/testing/designBaseline.d.ts.map +1 -1
  332. package/dist/testing/designBaseline.js +4 -0
  333. package/dist/testing/designBaseline.js.map +1 -1
  334. package/dist/theme.css +103 -2
  335. package/package.json +3 -2
  336. package/scripts/guardrails-baseline.json +2 -1
  337. package/scripts/guardrailsEnforce.spec.ts +64 -0
  338. package/scripts/guardrailsEnforce.ts +65 -8
  339. package/scripts/styleAreas.ts +1 -0
  340. package/src/nodeTypesDeclared.spec.ts +47 -0
  341. package/src/react/Toast.spec.tsx +43 -0
  342. package/src/react/Toast.tsx +45 -2
  343. package/src/react/analytics/MetricDrilldown.tsx +1 -1
  344. package/src/react/charts/AreaChart.tsx +9 -8
  345. package/src/react/charts/BarChart.tsx +11 -10
  346. package/src/react/charts/ChartCard.tsx +146 -0
  347. package/src/react/charts/ChartFrame.tsx +28 -10
  348. package/src/react/charts/ChartLegend.tsx +1 -1
  349. package/src/react/charts/HeatmapChart.tsx +5 -5
  350. package/src/react/charts/IntervalTimeline.tsx +2 -2
  351. package/src/react/charts/LineChart.tsx +9 -8
  352. package/src/react/charts/TimeSeriesChart.tsx +11 -10
  353. package/src/react/charts/chartBox.spec.ts +40 -0
  354. package/src/react/charts/chartBox.ts +75 -0
  355. package/src/react/charts/index.ts +2 -0
  356. package/src/react/charts/shared.ts +16 -3
  357. package/src/react/chat/Bubble.tsx +5 -5
  358. package/src/react/chat/MessageScroller.tsx +1 -1
  359. package/src/react/components/ActionBar.spec.tsx +90 -0
  360. package/src/react/components/ActionBar.tsx +82 -2
  361. package/src/react/components/AddItemsMenu.tsx +1 -1
  362. package/src/react/components/Alert.spec.tsx +32 -2
  363. package/src/react/components/Alert.tsx +47 -3
  364. package/src/react/components/AppShell.spec.tsx +199 -13
  365. package/src/react/components/AppShell.tsx +235 -92
  366. package/src/react/components/AsyncPanel.spec.tsx +7 -1
  367. package/src/react/components/AsyncPanel.tsx +85 -5
  368. package/src/react/components/BannerLane.tsx +128 -0
  369. package/src/react/components/Button.tsx +2 -0
  370. package/src/react/components/ChipFilterStrip.tsx +1 -1
  371. package/src/react/components/ComboboxField.tsx +20 -3
  372. package/src/react/components/CommentThread.tsx +2 -2
  373. package/src/react/components/ConfirmDialog.tsx +1 -1
  374. package/src/react/components/DataTable/DataTable.tsx +80 -8
  375. package/src/react/components/DataTable/Pagination.tsx +1 -1
  376. package/src/react/components/DataTable/RowActions.tsx +55 -2
  377. package/src/react/components/DataTable/TableFilterBuilder.tsx +1 -1
  378. package/src/react/components/DataTable/cells/CodeCell.tsx +1 -1
  379. package/src/react/components/DataTable/cells/LinkCell.tsx +1 -1
  380. package/src/react/components/DataTable/index.ts +1 -0
  381. package/src/react/components/DataTable/numericColumn.spec.ts +19 -0
  382. package/src/react/components/DataTable/types.ts +36 -0
  383. package/src/react/components/DateTimeField.tsx +3 -1
  384. package/src/react/components/DeleteButton.tsx +3 -0
  385. package/src/react/components/Drawer.tsx +3 -3
  386. package/src/react/components/DropdownMenu.spec.tsx +55 -0
  387. package/src/react/components/DropdownMenu.tsx +73 -20
  388. package/src/react/components/EmptyState.tsx +26 -7
  389. package/src/react/components/EventTimeline.tsx +1 -1
  390. package/src/react/components/Field.width.spec.tsx +11 -0
  391. package/src/react/components/FileDropZone.tsx +1 -1
  392. package/src/react/components/Grid.spec.tsx +44 -0
  393. package/src/react/components/Grid.tsx +41 -11
  394. package/src/react/components/Guide.tsx +77 -0
  395. package/src/react/components/InfoHint.spec.tsx +21 -0
  396. package/src/react/components/InfoHintImpl.tsx +22 -1
  397. package/src/react/components/InlineEditableText.tsx +1 -1
  398. package/src/react/components/IsolatedFrame.tsx +1 -1
  399. package/src/react/components/ListToolbar.spec.tsx +12 -0
  400. package/src/react/components/ListToolbar.tsx +8 -5
  401. package/src/react/components/LogViewer.tsx +118 -18
  402. package/src/react/components/Modal.spec.tsx +17 -2
  403. package/src/react/components/Modal.tsx +25 -10
  404. package/src/react/components/MultiSelectField.spec.tsx +6 -0
  405. package/src/react/components/Page.spec.tsx +89 -5
  406. package/src/react/components/Page.tsx +100 -16
  407. package/src/react/components/PageGuideButton.tsx +42 -0
  408. package/src/react/components/PanelSeparator.tsx +1 -1
  409. package/src/react/components/Popover.tsx +3 -1
  410. package/src/react/components/PromptDialog.tsx +1 -1
  411. package/src/react/components/ScrollArea.spec.tsx +20 -0
  412. package/src/react/components/ScrollArea.tsx +19 -0
  413. package/src/react/components/Section.spec.tsx +82 -1
  414. package/src/react/components/Section.tsx +10 -4
  415. package/src/react/components/Skeleton.tsx +50 -2
  416. package/src/react/components/StatStrip.tsx +1 -1
  417. package/src/react/components/StatTile.tsx +84 -11
  418. package/src/react/components/StatTileGrid.spec.tsx +6 -1
  419. package/src/react/components/StatTileGrid.tsx +25 -0
  420. package/src/react/components/StatusPill.tsx +26 -1
  421. package/src/react/components/Surface.tsx +22 -14
  422. package/src/react/components/SwatchPicker.tsx +4 -0
  423. package/src/react/components/Switch.tsx +1 -1
  424. package/src/react/components/WidgetHeader.tsx +1 -1
  425. package/src/react/components/calendar/CalendarLegend.tsx +1 -1
  426. package/src/react/components/calendar/DayAgenda.tsx +1 -1
  427. package/src/react/components/calendar/EventChip.tsx +1 -1
  428. package/src/react/components/calendar/MonthGrid.tsx +1 -1
  429. package/src/react/components/calendar/WeekView.tsx +2 -2
  430. package/src/react/components/cardFrame.ts +28 -0
  431. package/src/react/components/dataDisplay.spec.tsx +176 -0
  432. package/src/react/components/dialog.tsx +4 -1
  433. package/src/react/dashboard-grid/WidgetFrame.tsx +2 -2
  434. package/src/react/emoji/EmojiPicker.tsx +1 -1
  435. package/src/react/file-tree/FileTree.spec.tsx +49 -0
  436. package/src/react/file-tree/FileTree.tsx +37 -4
  437. package/src/react/filter-rail/FilterRail.tsx +1 -1
  438. package/src/react/icons.tsx +1 -1
  439. package/src/react/index.ts +28 -3
  440. package/src/react/lib/menuSections.ts +33 -0
  441. package/src/react/markdown/Markdown.tsx +2 -2
  442. package/src/react/media/HoverScrubVideoThumb.tsx +2 -2
  443. package/src/react/media/MaskPainter.tsx +1 -1
  444. package/src/react/media/MediaUploadControl.tsx +1 -1
  445. package/src/react/media/VideoTrimmer.tsx +1 -1
  446. package/src/react/media/denseGallery.css +5 -1
  447. package/src/react/namespace/NamespaceTargetCapsule.tsx +1 -1
  448. package/src/react/nav/BreadcrumbTrail.tsx +2 -2
  449. package/src/react/nav/CommandBar.tsx +14 -3
  450. package/src/react/nav/PlaceBar.tsx +18 -8
  451. package/src/react/nav/SideNav.tsx +99 -17
  452. package/src/react/nav/TopBar.spec.tsx +78 -21
  453. package/src/react/nav/TopBar.tsx +270 -98
  454. package/src/react/nav/index.ts +8 -1
  455. package/src/react/nav/nav.spec.tsx +46 -2
  456. package/src/react/nav/navShared.tsx +23 -2
  457. package/src/react/notifications/NotificationFeed.tsx +2 -2
  458. package/src/react/palette/Command.tsx +1 -1
  459. package/src/react/palette/CommandPalette.spec.tsx +31 -0
  460. package/src/react/palette/CommandPalette.tsx +108 -11
  461. package/src/react/palette/commandSources.tsx +186 -0
  462. package/src/react/palette/index.ts +7 -0
  463. package/src/react/rich-text/RichTextEditor.tsx +1 -1
  464. package/src/react/rich-text/RichTextToolbar.tsx +1 -1
  465. package/src/styles-areas/analytics.css +16 -16
  466. package/src/styles-areas/auth.css +3 -3
  467. package/src/styles-areas/calendar.css +6 -6
  468. package/src/styles-areas/chart-table.css +1 -1
  469. package/src/styles-areas/charts.css +3 -3
  470. package/src/styles-areas/chat.css +7 -6
  471. package/src/styles-areas/companion-link.css +2 -2
  472. package/src/styles-areas/core.css +98 -89
  473. package/src/styles-areas/dashboard-grid.css +4 -4
  474. package/src/styles-areas/data-table.css +16 -16
  475. package/src/styles-areas/disk-usage.css +5 -5
  476. package/src/styles-areas/emoji.css +2 -2
  477. package/src/styles-areas/fields.css +13 -14
  478. package/src/styles-areas/filter-rail.css +4 -4
  479. package/src/styles-areas/folder-tree.css +3 -3
  480. package/src/styles-areas/markdown.css +2 -1
  481. package/src/styles-areas/master-detail.css +3 -3
  482. package/src/styles-areas/media-gallery.css +8 -8
  483. package/src/styles-areas/media.css +12 -13
  484. package/src/styles-areas/nav.css +28 -14
  485. package/src/styles-areas/notifications.css +4 -4
  486. package/src/styles-areas/overlays.css +4 -4
  487. package/src/styles-areas/palette.css +4 -3
  488. package/src/styles-areas/rich-text.css +3 -3
  489. package/src/styles-areas/sharing.css +4 -3
  490. package/src/styles-areas/stats.css +9 -8
  491. package/src/styles-areas/test-report.css +3 -3
  492. package/src/styles-areas/wizard.css +6 -5
  493. package/src/styles-areas/workbench.css +10 -9
  494. package/src/styles-areas/workbook-viewer.css +2 -2
  495. package/src/styles-utilities.css +272 -187
  496. package/src/testing/designAudit.ts +3 -0
  497. package/src/testing/designBaseline.ts +4 -0
  498. package/src/theme.css +103 -2
  499. package/src/themeDarkScopeAliases.spec.ts +65 -0
@@ -11,7 +11,7 @@ import { Drawer } from '../components/Drawer.js';
11
11
  import { IconButton } from '../components/IconButton.js';
12
12
  import { cn } from '../lib/cn.js';
13
13
  import {
14
- isPathWithin,
14
+ isDomainActive,
15
15
  NAV_BADGE_TONE,
16
16
  type NavBadgeTone,
17
17
  NavLink,
@@ -168,9 +168,10 @@ export function PlaceBar({
168
168
  onClick={() => setMoreOpen(true)}
169
169
  className={cn(
170
170
  'relative flex min-w-0 flex-1 flex-col items-center justify-center gap-0.5 rounded-md px-1 py-1.5 text-xs font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring',
171
- overflowActive ? 'text-foreground' : 'text-muted-foreground hover:bg-muted hover:text-foreground',
171
+ overflowActive ? 'bg-accent/10 text-foreground' : 'text-muted-foreground hover:bg-muted hover:text-foreground',
172
172
  )}
173
173
  >
174
+ {overflowActive && <ActiveBar />}
174
175
  {/* Accent tints the icon only โ€” see the PlaceTab comment above (cbux-101). */}
175
176
  <span
176
177
  className='relative grid size-6 place-items-center [&_svg]:size-5'
@@ -244,11 +245,6 @@ export function PlaceBar({
244
245
  );
245
246
  }
246
247
 
247
- /** A place is active when the route is its landing or lives within it (rail-consistent). */
248
- function isDomainActive(domain: NavDomain, activeHref: string | undefined): boolean {
249
- if (isPathWithin(domain.path, activeHref)) return true;
250
- return domain.groups.some((g) => g.items.some((it) => isPathWithin(it.path, activeHref)));
251
- }
252
248
 
253
249
  interface PlaceTabProps extends NavNavigationProps {
254
250
  place: NavDomain;
@@ -292,9 +288,12 @@ function PlaceTab({
292
288
  ariaLabel={place.label}
293
289
  className={cn(
294
290
  'relative flex min-w-0 flex-1 flex-col items-center justify-center gap-0.5 rounded-md px-1 py-1.5 text-xs font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring',
295
- active ? 'text-foreground' : 'text-muted-foreground hover:bg-muted hover:text-foreground',
291
+ active ? 'bg-accent/10 text-foreground' : 'text-muted-foreground hover:bg-muted hover:text-foreground',
296
292
  )}
297
293
  >
294
+ {/* NAV-6 on a bottom bar: its leading edge is the top one, facing the page. With the
295
+ tint and the foreground caption that is three marks โ€” never color alone. */}
296
+ {active && <ActiveBar />}
298
297
  {/* The accent only ever tints the icon (graphical, 3:1 floor โ€” axe doesn't
299
298
  score it as text) โ€” never the label. `navAccent`/`--accent-solid` stays
300
299
  saturated in both modes for white-on-solid-fill use; as real label text
@@ -333,3 +332,14 @@ function PlaceTab({
333
332
  </NavLink>
334
333
  );
335
334
  }
335
+
336
+ /** The 3px accent bar across the top of the current tab (NAV-6). */
337
+ function ActiveBar() {
338
+ return (
339
+ <span
340
+ aria-hidden='true'
341
+ data-cb-active-indicator=''
342
+ className='absolute inset-x-3 top-0 h-[var(--indicator-w)] rounded-full bg-accent-solid'
343
+ />
344
+ );
345
+ }
@@ -2,10 +2,12 @@ import { Fragment, type ReactNode, Suspense, useState } from 'react';
2
2
  import {
3
3
  allowAllGate,
4
4
  CURRENT_NAV_PREFS_VERSION,
5
+ deriveDomainItems,
5
6
  deriveSideNavDomains,
6
7
  type GateFn,
7
8
  type NavDomain,
8
9
  type NavigationModel,
10
+ type NavItem,
9
11
  type NavPreferences,
10
12
  } from 'cursedbelt-core/navigation';
11
13
  import { DisclosureButton } from '../components/DisclosureButton.js';
@@ -15,6 +17,7 @@ import { Tooltip } from '../components/Tooltip.js';
15
17
  import type { DragItemApi } from '../hooks/dragShared.js';
16
18
  import { cn } from '../lib/cn.js';
17
19
  import {
20
+ isDomainActive,
18
21
  isPathWithin,
19
22
  NAV_BADGE_TONE,
20
23
  type NavBadgeTone,
@@ -76,8 +79,18 @@ export interface SideNavProps extends NavNavigationProps {
76
79
  badgeTone?: NavBadgeTone;
77
80
  /** App slot above the list (logo / brand). */
78
81
  header?: ReactNode;
79
- /** App slot below the list (theme toggle / avatar). */
82
+ /**
83
+ * App slot below the list โ€” the version, `BuildFreshness` and a Settings link (NAV-13). Set
84
+ * in 12px muted type, under a 1px rule; a tool has no marketing footer anywhere else. Not
85
+ * drawn in the `collapsed` icon rail, which is 64px wide.
86
+ */
80
87
  footer?: ReactNode;
88
+ /**
89
+ * Show the ACTIVE place's own items beneath it, each label aligned under the parent's label
90
+ * text (NAV-7) โ€” so a reader sees where they are inside a place without a second nav.
91
+ * Default `true`. Never in the icon rail, which has no labels to align to.
92
+ */
93
+ expandActive?: boolean;
81
94
  className?: string;
82
95
  }
83
96
 
@@ -109,6 +122,7 @@ export function SideNav({
109
122
  badgeTone = 'alert',
110
123
  header,
111
124
  footer,
125
+ expandActive = true,
112
126
  className,
113
127
  }: SideNavProps) {
114
128
  const domains = deriveSideNavDomains(model, gate);
@@ -159,11 +173,18 @@ export function SideNav({
159
173
  sections.sort((a, b) => Number(b.section === undefined) - Number(a.section === undefined));
160
174
  }
161
175
 
162
- const renderRow = (domain: NavDomain, drag?: DragItemApi): ReactNode => (
176
+ const renderRow = (domain: NavDomain, drag?: DragItemApi): ReactNode => {
177
+ const active = isDomainActive(domain, activeHref);
178
+ const children = active && expandActive && !collapsed ? deriveDomainItems(domain, gate) : [];
179
+ const activeChild = children.find((it) => isPathWithin(it.path, activeHref));
180
+ const row = (
163
181
  <DomainRow
164
182
  key={domain.id}
165
183
  domain={domain}
166
- active={isDomainActive(domain, activeHref)}
184
+ active={active}
185
+ // When a child is the current page, IT carries the bar and the tint; the place keeps
186
+ // its foreground label so the reader still sees which place they are inside.
187
+ activeIsChild={Boolean(activeChild)}
167
188
  color={prefs?.colors?.[domain.id]}
168
189
  badge={badges?.[domain.id]}
169
190
  badgeTone={badgeTone}
@@ -179,11 +200,26 @@ export function SideNav({
179
200
  }}
180
201
  {...navProps}
181
202
  />
182
- );
203
+ );
204
+ if (children.length === 0) return row;
205
+ return (
206
+ <Fragment key={domain.id}>
207
+ {row}
208
+ <ul data-cb-sidenav-children='' className='mt-0.5 space-y-0.5'>
209
+ {children.map((item) => (
210
+ <li key={item.id}>
211
+ <ChildRow item={item} active={item === activeChild} {...navProps} />
212
+ </li>
213
+ ))}
214
+ </ul>
215
+ </Fragment>
216
+ );
217
+ };
183
218
 
184
219
  return (
185
220
  <nav
186
221
  data-cb-sidenav=''
222
+ data-cb-nav-collapsed={collapsed ? '' : undefined}
187
223
  aria-label='Primary'
188
224
  className={cn('flex h-full flex-col', collapsed ? 'w-16' : 'w-full', className)}
189
225
  >
@@ -256,8 +292,10 @@ export function SideNav({
256
292
  )}
257
293
  </ScrollArea>
258
294
 
259
- {(footer || (canCustomize && hiddenDomains.length > 0)) && (
260
- <div className='shrink-0 space-y-2 border-t border-border px-3 py-3'>
295
+ {/* The footer is words in a 240px column (NAV-13); the 64px icon rail has no room for
296
+ them, so it leaves them to the expanded rail and Settings. */}
297
+ {((footer && !collapsed) || (canCustomize && hiddenDomains.length > 0)) && (
298
+ <div data-cb-sidenav-footer='' className='shrink-0 space-y-2 border-t border-border px-3 py-3 text-xs text-muted-foreground'>
261
299
  {canCustomize && hiddenDomains.length > 0 && (
262
300
  <Suspense fallback={null}>
263
301
  <RestoreHiddenMenu
@@ -267,22 +305,19 @@ export function SideNav({
267
305
  />
268
306
  </Suspense>
269
307
  )}
270
- {footer}
308
+ {collapsed ? null : footer}
271
309
  </div>
272
310
  )}
273
311
  </nav>
274
312
  );
275
313
  }
276
314
 
277
- /** A domain is active when the route is its landing or lives within it. */
278
- function isDomainActive(domain: NavDomain, activeHref: string | undefined): boolean {
279
- if (isPathWithin(domain.path, activeHref)) return true;
280
- return domain.groups.some((g) => g.items.some((it) => isPathWithin(it.path, activeHref)));
281
- }
282
315
 
283
316
  interface DomainRowProps extends NavNavigationProps {
284
317
  domain: NavDomain;
285
318
  active: boolean;
319
+ /** The current page is one of this place's items, shown beneath it. */
320
+ activeIsChild?: boolean;
286
321
  color?: string;
287
322
  badge?: number | string;
288
323
  badgeTone: NavBadgeTone;
@@ -296,6 +331,7 @@ interface DomainRowProps extends NavNavigationProps {
296
331
  function DomainRow({
297
332
  domain,
298
333
  active,
334
+ activeIsChild = false,
299
335
  color,
300
336
  badge,
301
337
  badgeTone,
@@ -327,7 +363,7 @@ function DomainRow({
327
363
  linkComponent={linkComponent}
328
364
  onNavigate={onNavigate}
329
365
  onAfterNavigate={onAfterNavigate}
330
- ariaCurrent={active ? 'page' : undefined}
366
+ ariaCurrent={active && !activeIsChild ? 'page' : undefined}
331
367
  disabled={limited}
332
368
  // When there IS a host limit the wrapper below carries the richer hint, so the
333
369
  // link must not open a second, nested one.
@@ -345,7 +381,13 @@ function DomainRow({
345
381
  collapsed
346
382
  ? `size-10 justify-center ${TAP_TARGET}`
347
383
  : `w-full gap-3 px-3 py-2 ${TAP_TARGET_HEIGHT}`,
348
- active ? 'bg-muted text-foreground' : 'text-foreground hover:bg-muted',
384
+ // NAV-6: the current place is marked three ways โ€” the bar below, this tint, and a
385
+ // foreground label against the muted ones around it. Color alone fails.
386
+ active && !activeIsChild
387
+ ? 'bg-accent/10 text-foreground'
388
+ : active
389
+ ? 'text-foreground hover:bg-muted'
390
+ : 'text-muted-foreground hover:bg-muted hover:text-foreground',
349
391
  )}
350
392
  >
351
393
  {/* Active accent bar โ€” colored by the per-row override or theme accent. The
@@ -359,12 +401,13 @@ function DomainRow({
359
401
  caught a domain green at 2.67:1 on the dark-mode muted background);
360
402
  the label stays on the guaranteed-contrast `text-foreground` token
361
403
  regardless of which accent a domain picks. */}
362
- {active && (
404
+ {active && !activeIsChild && (
363
405
  <span
364
406
  aria-hidden='true'
407
+ data-cb-active-indicator=''
365
408
  className={cn(
366
- 'absolute left-0 rounded-full',
367
- collapsed ? 'inset-y-1 left-0 w-[3px]' : 'inset-y-1.5 w-0.5',
409
+ 'absolute left-0 w-[var(--indicator-w)] rounded-full',
410
+ collapsed ? 'inset-y-1' : 'inset-y-1.5',
368
411
  )}
369
412
  style={{ backgroundColor: accent }}
370
413
  />
@@ -432,3 +475,42 @@ function DomainRow({
432
475
  </div>
433
476
  );
434
477
  }
478
+
479
+ /**
480
+ * One of the active place's items (NAV-7). Its label starts exactly under the parent's label:
481
+ * the parent row's `px-3` + its 20px icon + its `gap-3` is 44px, so the child's padding is 44px
482
+ * (`pl-11`) and its text lands on the same x. Marked like the place when it is the current page.
483
+ */
484
+ function ChildRow({
485
+ item,
486
+ active,
487
+ linkComponent,
488
+ onNavigate,
489
+ onAfterNavigate,
490
+ }: NavNavigationProps & { item: NavItem; active: boolean }) {
491
+ return (
492
+ <NavLink
493
+ path={item.path}
494
+ linkComponent={linkComponent}
495
+ onNavigate={onNavigate}
496
+ onAfterNavigate={onAfterNavigate}
497
+ ariaCurrent={active ? 'page' : undefined}
498
+ className={cn(
499
+ 'relative flex w-full items-center rounded-md py-1.5 pl-11 pr-3 text-sm transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring',
500
+ TAP_TARGET_HEIGHT,
501
+ active ? 'bg-accent/10 font-medium text-foreground' : 'text-muted-foreground hover:bg-muted hover:text-foreground',
502
+ )}
503
+ >
504
+ {active && (
505
+ <span
506
+ aria-hidden='true'
507
+ data-cb-active-indicator=''
508
+ className='absolute inset-y-1.5 left-0 w-[var(--indicator-w)] rounded-full bg-accent-solid'
509
+ />
510
+ )}
511
+ <span data-cb-nav-child-label='' className='min-w-0 flex-1 truncate text-left'>
512
+ {item.label}
513
+ </span>
514
+ </NavLink>
515
+ );
516
+ }
@@ -13,34 +13,89 @@ const items: TopBarItem[] = [
13
13
 
14
14
  const brand = { icon: <Glyph name='brand' />, label: 'Music', href: '/' };
15
15
 
16
- describe('TopBar โ€” icons, not words (owner, 2026-09-25)', () => {
17
- test('๐Ÿ”ด an item paints its ICON and no words; the label is its accessible name', () => {
16
+ describe('TopBar โ€” destinations have words (NAV-2, owner review 2026-10-01)', () => {
17
+ test('๐Ÿ”ด an item paints its icon AND its label from md up; the label is its accessible name', () => {
18
18
  const { getByRole } = render(<TopBar brand={brand} items={items} />);
19
19
  const link = getByRole('link', { name: 'Downloads' });
20
20
  expect(link.querySelector('[data-glyph="downloads"]')).not.toBeNull();
21
- // No text at all inside the link โ€” the word lives only in aria-label.
22
- expect(link.textContent).toBe('');
21
+ const word = Array.from(link.querySelectorAll('span')).find((s) => s.textContent === 'Downloads');
22
+ expect(word?.className).toContain('hidden');
23
+ expect(word?.className).toContain('md:inline');
23
24
  expect(link.getAttribute('href')).toBe('/downloads');
24
25
  });
25
26
 
26
- test('the active place is lit and announced as the current page', () => {
27
+ test('a router nav is marked primary for the design audit; an iconOnly utility bar is not', () => {
28
+ const { container } = render(<TopBar brand={brand} items={items} />);
29
+ const nav = container.querySelector('[data-cb-topbar-nav]') as HTMLElement;
30
+ expect(nav.hasAttribute('data-cb-primary-nav')).toBe(true);
31
+ cleanup();
32
+ const utility = render(<TopBar brand={brand} items={items} iconOnly />);
33
+ const bar = utility.container.querySelector('[data-cb-topbar-nav]') as HTMLElement;
34
+ expect(bar.hasAttribute('data-cb-primary-nav')).toBe(false);
35
+ expect(bar.hasAttribute('data-cb-nav-utility')).toBe(true);
36
+ // A utility bar paints glyphs only, at every width.
37
+ expect(utility.getByRole('link', { name: 'Downloads' }).textContent).toBe('');
38
+ });
39
+
40
+ test('๐Ÿ”ด the active place is marked three ways (NAV-6): bar, tint, foreground โ€” and aria-current', () => {
27
41
  const { getByRole } = render(<TopBar brand={brand} items={items} />);
28
- expect(getByRole('link', { name: 'Library' }).getAttribute('aria-current')).toBe('page');
29
- expect(getByRole('link', { name: 'Downloads' }).getAttribute('aria-current')).toBeNull();
42
+ const active = getByRole('link', { name: 'Library' });
43
+ expect(active.getAttribute('aria-current')).toBe('page');
44
+ expect(active.querySelector('[data-cb-active-indicator]')).not.toBeNull();
45
+ expect(active.className).toContain('bg-accent/10');
46
+ expect(active.className).toContain('text-foreground');
47
+ const idle = getByRole('link', { name: 'Downloads' });
48
+ expect(idle.getAttribute('aria-current')).toBeNull();
49
+ expect(idle.querySelector('[data-cb-active-indicator]')).toBeNull();
50
+ expect(idle.className).toContain('text-muted-foreground');
30
51
  });
31
52
 
32
- test('words appear ONLY with a stated reason, and even then drop below sm', () => {
33
- const withReason: TopBarItem[] = [{ ...items[1], wordsBecause: 'two identical glyphs side by side' }];
34
- const { getByRole } = render(<TopBar brand={brand} items={withReason} />);
35
- const words = Array.from(getByRole('link', { name: 'Downloads' }).querySelectorAll('span')).find(
36
- (s) => s.textContent === 'Downloads',
37
- );
38
- expect(words?.className).toContain('hidden');
39
- expect(words?.className).toContain('sm:inline');
40
- const blank: TopBarItem[] = [{ ...items[1], wordsBecause: ' ' }];
53
+ test('๐Ÿ”ด a count is never hidden: beside the word from md up, on the glyph\'s corner below, and in the name', () => {
54
+ const counted: TopBarItem[] = [items[0] as TopBarItem, { ...(items[1] as TopBarItem), badge: 1234 }];
55
+ const { getByRole } = render(<TopBar brand={brand} items={counted} />);
56
+ // Read as part of the name, so a screen reader hears the figure the eye sees.
57
+ const link = getByRole('link', { name: 'Downloads ยท 99+' });
58
+ const badge = link.querySelector('[data-cb-nav-badge]') as HTMLElement;
59
+ expect(badge.textContent).toBe('99+');
60
+ expect(badge.className).not.toContain('hidden');
61
+ expect(badge.className).toContain('max-md:absolute');
41
62
  cleanup();
42
- const again = render(<TopBar brand={brand} items={blank} />);
43
- expect(again.getByRole('link', { name: 'Downloads' }).textContent).toBe('');
63
+ const utility = render(<TopBar brand={brand} items={counted} iconOnly />);
64
+ const corner = utility.getByRole('link', { name: 'Downloads ยท 99+' }).querySelector('[data-cb-nav-badge]') as HTMLElement;
65
+ expect(corner.className).toContain('absolute');
66
+ });
67
+
68
+ test('header geometry (NAV-1): the --header-h token, a 1px bottom border, three zones', () => {
69
+ const { container } = render(<TopBar brand={brand} items={items} trailing={<span>x</span>} />);
70
+ const bar = container.querySelector('[data-cb-topbar]') as HTMLElement;
71
+ expect(bar.className).toContain('h-[var(--header-h)]');
72
+ expect(bar.className).toContain('border-b');
73
+ expect(bar.className).not.toContain('shadow');
74
+ const zones = Array.from(bar.children).map((z) => z.getAttribute('data-cb-topbar-zone'));
75
+ expect(zones).toEqual(['left', 'center', 'right']);
76
+ cleanup();
77
+ const dense = render(<TopBar brand={brand} items={items} density='dense' />);
78
+ expect((dense.container.querySelector('[data-cb-topbar]') as HTMLElement).className).toContain(
79
+ 'h-[var(--header-h-dense)]',
80
+ );
81
+ });
82
+
83
+ test("phonePlaces='none' hands the places to a PlaceBar below md", () => {
84
+ const { container } = render(<TopBar brand={brand} items={items} phonePlaces='none' />);
85
+ expect((container.querySelector('[data-cb-topbar-nav]') as HTMLElement).className).toContain('max-md:hidden');
86
+ });
87
+
88
+ test('six or more places warn in dev โ€” NAV-3 puts them in a sectioned SideNav', () => {
89
+ const warn = console.warn;
90
+ const said: string[] = [];
91
+ console.warn = (m: string) => said.push(m);
92
+ try {
93
+ const six = Array.from({ length: 6 }, (_, i) => ({ ...items[1], id: `p${i}`, href: `/p${i}` }));
94
+ render(<TopBar brand={{ ...brand, label: 'Six-place app' }} items={six} />);
95
+ } finally {
96
+ console.warn = warn;
97
+ }
98
+ expect(said.some((m) => m.includes('NAV-3'))).toBe(true);
44
99
  });
45
100
 
46
101
  test('๐Ÿ”ด the row cannot widen the page: clamped, and the places scroll inside themselves', () => {
@@ -55,15 +110,17 @@ describe('TopBar โ€” icons, not words (owner, 2026-09-25)', () => {
55
110
  // Brand and trailing controls never shrink โ€” the account menu stays reachable.
56
111
  const brandLink = container.querySelector('[data-cb-topbar-brand]') as HTMLElement;
57
112
  expect(brandLink.className).toContain('shrink-0');
58
- expect((nav.nextElementSibling as HTMLElement).className).toContain('shrink-0');
113
+ const right = container.querySelector('[data-cb-topbar-zone="right"]') as HTMLElement;
114
+ expect(right.querySelector('[data-trailing]')).not.toBeNull();
115
+ expect(right.className).toContain('shrink-0');
59
116
  });
60
117
 
61
118
  test('a leading control sits BEFORE the brand and never shrinks โ€” the phone sidebar button', () => {
62
119
  const { container } = render(
63
120
  <TopBar brand={brand} items={items} leading={<span data-leading=''>โ˜ฐ</span>} />,
64
121
  );
65
- const bar = container.querySelector('[data-cb-topbar]') as HTMLElement;
66
- const first = bar.firstElementChild as HTMLElement;
122
+ const left = container.querySelector('[data-cb-topbar-zone="left"]') as HTMLElement;
123
+ const first = left.firstElementChild as HTMLElement;
67
124
  expect(first.querySelector('[data-leading]')).not.toBeNull();
68
125
  expect(first.className).toContain('shrink-0');
69
126
  expect(first.nextElementSibling?.hasAttribute('data-cb-topbar-brand')).toBe(true);