basalt-ui 1.30.2 → 1.32.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 (357) hide show
  1. package/AGENTS.md +1 -1
  2. package/CHANGELOG.md +54 -0
  3. package/MIGRATING.md +256 -12
  4. package/agent/rules/basalt-controls.md +19 -19
  5. package/agent/rules/basalt-mantine.md +5 -5
  6. package/configs/oxlint-plugin.js +371 -4
  7. package/configs/oxlint-plugin.test.ts +327 -2
  8. package/configs/oxlint.json +2 -1
  9. package/dist/agent-chat/composer.d.ts.map +1 -1
  10. package/dist/agent-chat/composer.js +41 -43
  11. package/dist/agent-chat/thread-workspace.d.ts +2 -2
  12. package/dist/agent-chat/thread-workspace.d.ts.map +1 -1
  13. package/dist/agent-chat/thread-workspace.js +3 -4
  14. package/dist/agent-chat/use-keyboard-inset.d.ts +2 -0
  15. package/dist/agent-chat/use-keyboard-inset.d.ts.map +1 -0
  16. package/dist/agent-chat/use-keyboard-inset.js +34 -0
  17. package/dist/charts/cursor/touch-pin.d.ts +45 -0
  18. package/dist/charts/cursor/touch-pin.d.ts.map +1 -0
  19. package/dist/charts/cursor/touch-pin.js +79 -0
  20. package/dist/charts/hooks/use-discrete-cursor.d.ts +66 -0
  21. package/dist/charts/hooks/use-discrete-cursor.d.ts.map +1 -0
  22. package/dist/charts/hooks/use-discrete-cursor.js +198 -0
  23. package/dist/charts/hooks/use-hysteresis.d.ts +18 -0
  24. package/dist/charts/hooks/use-hysteresis.d.ts.map +1 -0
  25. package/dist/charts/hooks/use-hysteresis.js +12 -0
  26. package/dist/charts/hooks/useBandPlot.d.ts +7 -0
  27. package/dist/charts/hooks/useBandPlot.d.ts.map +1 -1
  28. package/dist/charts/hooks/useBandPlot.js +62 -18
  29. package/dist/charts/hooks/useChartCursor.d.ts +40 -11
  30. package/dist/charts/hooks/useChartCursor.d.ts.map +1 -1
  31. package/dist/charts/hooks/useChartCursor.js +102 -11
  32. package/dist/charts/index.d.ts +0 -1
  33. package/dist/charts/index.d.ts.map +1 -1
  34. package/dist/charts/index.js +0 -10
  35. package/dist/charts/kinds/BandStrip.d.ts.map +1 -1
  36. package/dist/charts/kinds/BandStrip.js +47 -82
  37. package/dist/charts/kinds/Donut.d.ts +9 -3
  38. package/dist/charts/kinds/Donut.d.ts.map +1 -1
  39. package/dist/charts/kinds/Donut.js +110 -48
  40. package/dist/charts/kinds/DualPanel.d.ts.map +1 -1
  41. package/dist/charts/kinds/DualPanel.js +138 -145
  42. package/dist/charts/kinds/Heatmap.d.ts +7 -0
  43. package/dist/charts/kinds/Heatmap.d.ts.map +1 -1
  44. package/dist/charts/kinds/Heatmap.js +37 -16
  45. package/dist/charts/kinds/MirroredBars.d.ts.map +1 -1
  46. package/dist/charts/kinds/MirroredBars.js +68 -111
  47. package/dist/charts/kinds/band-chrome.d.ts +31 -0
  48. package/dist/charts/kinds/band-chrome.d.ts.map +1 -0
  49. package/dist/charts/kinds/band-chrome.js +71 -0
  50. package/dist/charts/kinds/donut-layout.d.ts +47 -0
  51. package/dist/charts/kinds/donut-layout.d.ts.map +1 -0
  52. package/dist/charts/kinds/donut-layout.js +52 -0
  53. package/dist/charts/layout/auto-margin.d.ts +7 -2
  54. package/dist/charts/layout/auto-margin.d.ts.map +1 -1
  55. package/dist/charts/layout/auto-margin.js +12 -3
  56. package/dist/charts/layout/end-labels.d.ts +64 -0
  57. package/dist/charts/layout/end-labels.d.ts.map +1 -0
  58. package/dist/charts/layout/end-labels.js +76 -0
  59. package/dist/charts/primitives/Axes.d.ts +32 -4
  60. package/dist/charts/primitives/Axes.d.ts.map +1 -1
  61. package/dist/charts/primitives/Axes.js +62 -16
  62. package/dist/charts/primitives/CartesianChart.d.ts +7 -6
  63. package/dist/charts/primitives/CartesianChart.d.ts.map +1 -1
  64. package/dist/charts/primitives/CartesianChart.js +264 -145
  65. package/dist/charts/primitives/ChartCard.d.ts +0 -14
  66. package/dist/charts/primitives/ChartCard.d.ts.map +1 -1
  67. package/dist/charts/primitives/ChartCard.js +56 -21
  68. package/dist/charts/primitives/ChartFrame.d.ts +28 -22
  69. package/dist/charts/primitives/ChartFrame.d.ts.map +1 -1
  70. package/dist/charts/primitives/ChartFrame.js +116 -34
  71. package/dist/charts/primitives/ChartLegend.d.ts +19 -15
  72. package/dist/charts/primitives/ChartLegend.d.ts.map +1 -1
  73. package/dist/charts/primitives/ChartLegend.js +86 -73
  74. package/dist/charts/primitives/ChartTooltip.d.ts +5 -0
  75. package/dist/charts/primitives/ChartTooltip.d.ts.map +1 -1
  76. package/dist/charts/primitives/ChartTooltip.js +20 -4
  77. package/dist/charts/primitives/Crosshair.js +2 -2
  78. package/dist/charts/primitives/HoverOverlay.d.ts +29 -9
  79. package/dist/charts/primitives/HoverOverlay.d.ts.map +1 -1
  80. package/dist/charts/primitives/HoverOverlay.js +54 -27
  81. package/dist/charts/primitives/HoverOverlay.module.css +13 -0
  82. package/dist/charts/primitives/HoverOverlay.module.css.d.ts +8 -0
  83. package/dist/charts/primitives/chart-card-context.d.ts +33 -0
  84. package/dist/charts/primitives/chart-card-context.d.ts.map +1 -0
  85. package/dist/charts/primitives/chart-card-context.js +18 -0
  86. package/dist/charts/primitives/chart-frame-layout.d.ts +93 -113
  87. package/dist/charts/primitives/chart-frame-layout.d.ts.map +1 -1
  88. package/dist/charts/primitives/chart-frame-layout.js +75 -34
  89. package/dist/charts/primitives/chart-layout.d.ts +112 -0
  90. package/dist/charts/primitives/chart-layout.d.ts.map +1 -0
  91. package/dist/charts/primitives/chart-layout.js +175 -0
  92. package/dist/charts/primitives/chart-tier.d.ts +13 -11
  93. package/dist/charts/primitives/chart-tier.d.ts.map +1 -1
  94. package/dist/charts/primitives/chart-tier.js +42 -13
  95. package/dist/charts/primitives/legend-disclosure.d.ts +27 -0
  96. package/dist/charts/primitives/legend-disclosure.d.ts.map +1 -0
  97. package/dist/charts/primitives/legend-disclosure.js +153 -0
  98. package/dist/charts/series.d.ts +4 -1
  99. package/dist/charts/series.d.ts.map +1 -1
  100. package/dist/charts/utils/ticks.d.ts +27 -8
  101. package/dist/charts/utils/ticks.d.ts.map +1 -1
  102. package/dist/charts/utils/ticks.js +35 -11
  103. package/dist/common/errors.d.ts +11 -1
  104. package/dist/common/errors.d.ts.map +1 -1
  105. package/dist/common/errors.js +16 -2
  106. package/dist/common/hit-floor.d.ts +10 -0
  107. package/dist/common/hit-floor.d.ts.map +1 -0
  108. package/dist/common/hit-floor.js +6 -0
  109. package/dist/{shell → common}/isomorphic-layout-effect.d.ts +4 -3
  110. package/dist/common/isomorphic-layout-effect.d.ts.map +1 -0
  111. package/dist/common/use-measured-widths.d.ts +37 -0
  112. package/dist/common/use-measured-widths.d.ts.map +1 -0
  113. package/dist/common/use-measured-widths.js +51 -0
  114. package/dist/common/use-media-query.d.ts +6 -0
  115. package/dist/common/use-media-query.d.ts.map +1 -0
  116. package/dist/common/use-media-query.js +40 -0
  117. package/dist/common/validate.d.ts +9 -0
  118. package/dist/common/validate.d.ts.map +1 -1
  119. package/dist/common/validate.js +9 -4
  120. package/dist/content/article-layout.d.ts +4 -2
  121. package/dist/content/article-layout.d.ts.map +1 -1
  122. package/dist/content/article-layout.js +43 -3
  123. package/dist/content/article-layout.module.css +45 -4
  124. package/dist/content/article-layout.module.css.d.ts +3 -0
  125. package/dist/content/code-block.d.ts.map +1 -1
  126. package/dist/content/code-block.js +40 -2
  127. package/dist/content/code-block.module.css +32 -2
  128. package/dist/content/prose.module.css +13 -8
  129. package/dist/controls/actions.d.ts +29 -6
  130. package/dist/controls/actions.d.ts.map +1 -1
  131. package/dist/controls/actions.js +158 -27
  132. package/dist/controls/actions.module.css +14 -1
  133. package/dist/controls/actions.module.css.d.ts +1 -0
  134. package/dist/controls/controls.module.css +13 -31
  135. package/dist/controls/enum-filter.js +2 -2
  136. package/dist/controls/filter-context.d.ts +10 -0
  137. package/dist/controls/filter-context.d.ts.map +1 -1
  138. package/dist/controls/filter-context.js +2 -0
  139. package/dist/controls/filter-pill.d.ts.map +1 -1
  140. package/dist/controls/filter-pill.js +1 -0
  141. package/dist/controls/index.d.ts +1 -1
  142. package/dist/controls/index.d.ts.map +1 -1
  143. package/dist/controls/index.js +0 -2
  144. package/dist/controls/multi-select-filter.js +2 -2
  145. package/dist/controls/sync-button.module.css +2 -1
  146. package/dist/dashboard/section.d.ts.map +1 -1
  147. package/dist/dashboard/section.js +1 -0
  148. package/dist/dashboard/section.module.css +1 -26
  149. package/dist/dashboard/stat-card.d.ts +1 -1
  150. package/dist/dashboard/stat-card.d.ts.map +1 -1
  151. package/dist/dashboard/stat-card.js +4 -1
  152. package/dist/dashboard/stat-card.module.css +6 -9
  153. package/dist/dashboard/stat-group.module.css +33 -66
  154. package/dist/dashboard/widget-grid.d.ts.map +1 -1
  155. package/dist/dashboard/widget-grid.module.css +11 -38
  156. package/dist/dashboard/widget-header.d.ts +14 -4
  157. package/dist/dashboard/widget-header.d.ts.map +1 -1
  158. package/dist/dashboard/widget-header.js +23 -6
  159. package/dist/dashboard/widget-header.module.css +145 -133
  160. package/dist/dashboard/widget-header.module.css.d.ts +2 -0
  161. package/dist/data/data-table-state.d.ts +83 -0
  162. package/dist/data/data-table-state.d.ts.map +1 -0
  163. package/dist/data/data-table-state.js +139 -0
  164. package/dist/data/data-table.d.ts +56 -2
  165. package/dist/data/data-table.d.ts.map +1 -1
  166. package/dist/data/data-table.js +436 -336
  167. package/dist/data/data-table.module.css +94 -0
  168. package/dist/data/data-table.module.css.d.ts +11 -0
  169. package/dist/data/virtual-list.d.ts.map +1 -1
  170. package/dist/data/virtual-list.js +10 -0
  171. package/dist/forms/form-layout.d.ts.map +1 -1
  172. package/dist/forms/form-layout.js +3 -3
  173. package/dist/forms/form-layout.module.css +20 -5
  174. package/dist/forms/form-layout.module.css.d.ts +1 -0
  175. package/dist/guard/index.d.ts +8 -2
  176. package/dist/guard/index.d.ts.map +1 -1
  177. package/dist/guard/index.js +68 -2
  178. package/dist/guard/types.d.ts +3 -3
  179. package/dist/guard/types.d.ts.map +1 -1
  180. package/dist/index.d.ts +1 -1
  181. package/dist/index.d.ts.map +1 -1
  182. package/dist/index.js +3 -1
  183. package/dist/notifications/center.d.ts.map +1 -1
  184. package/dist/provider/index.d.ts +20 -1
  185. package/dist/provider/index.d.ts.map +1 -1
  186. package/dist/provider/index.js +30 -8
  187. package/dist/shell/app-brand.d.ts.map +1 -1
  188. package/dist/shell/app-brand.js +1 -0
  189. package/dist/shell/app-brand.module.css +2 -2
  190. package/dist/shell/app-header.module.css +18 -8
  191. package/dist/shell/app-main.module.css +54 -3
  192. package/dist/shell/app-main.module.css.d.ts +1 -0
  193. package/dist/shell/app-mobile-nav.module.css +16 -4
  194. package/dist/shell/app-sidebar.module.css +4 -6
  195. package/dist/shell/aside-docking.d.ts +31 -0
  196. package/dist/shell/aside-docking.d.ts.map +1 -0
  197. package/dist/shell/aside-docking.js +19 -0
  198. package/dist/shell/index.d.ts +1 -0
  199. package/dist/shell/index.d.ts.map +1 -1
  200. package/dist/shell/index.js +56 -16
  201. package/dist/shell/mobile-nav-model.d.ts +1 -1
  202. package/dist/shell/page-aside.d.ts +22 -3
  203. package/dist/shell/page-aside.d.ts.map +1 -1
  204. package/dist/shell/page-aside.js +27 -13
  205. package/dist/shell/page-bar.d.ts.map +1 -1
  206. package/dist/shell/page-bar.js +10 -5
  207. package/dist/shell/page-bar.module.css +10 -34
  208. package/dist/shell/use-breakpoint.d.ts +3 -4
  209. package/dist/shell/use-breakpoint.d.ts.map +1 -1
  210. package/dist/shell/use-breakpoint.js +3 -25
  211. package/dist/shell/use-size-class.d.ts +6 -0
  212. package/dist/shell/use-size-class.d.ts.map +1 -0
  213. package/dist/shell/use-size-class.js +19 -0
  214. package/dist/state/persisted-or-local.d.ts +4 -1
  215. package/dist/state/persisted-or-local.d.ts.map +1 -1
  216. package/dist/state/persisted-or-local.js +4 -3
  217. package/dist/state/persisted.d.ts +10 -0
  218. package/dist/state/persisted.d.ts.map +1 -1
  219. package/dist/state/persisted.js +44 -14
  220. package/dist/styles.css +41 -0
  221. package/dist/surfaces.d.ts +4 -4
  222. package/dist/surfaces.d.ts.map +1 -1
  223. package/dist/surfaces.js +11 -3
  224. package/dist/theme/controls.module.css +7 -0
  225. package/dist/theme/ctl-theme.d.ts +1 -0
  226. package/dist/theme/ctl-theme.d.ts.map +1 -1
  227. package/dist/theme/ctl-theme.js +12 -4
  228. package/dist/theme/floating.module.css +37 -0
  229. package/dist/theme/floating.module.css.d.ts +3 -0
  230. package/dist/theme/index.d.ts +2 -2
  231. package/dist/theme/index.d.ts.map +1 -1
  232. package/dist/theme/index.js +34 -5
  233. package/dist/theme/nav-link.module.css +7 -0
  234. package/dist/theme-lab/derive-controls.d.ts.map +1 -1
  235. package/dist/tokens/index.d.ts +7 -16
  236. package/dist/tokens/index.d.ts.map +1 -1
  237. package/dist/tokens/index.js +23 -28
  238. package/dist/tokens/palette.d.ts +5 -27
  239. package/dist/tokens/palette.d.ts.map +1 -1
  240. package/dist/tokens/palette.js +8 -30
  241. package/dist/tokens/size-classes.d.ts +40 -0
  242. package/dist/tokens/size-classes.d.ts.map +1 -0
  243. package/dist/tokens/size-classes.js +29 -0
  244. package/dist/tokens.css +8 -4
  245. package/llms.txt +3 -3
  246. package/package.json +18 -17
  247. package/src/agent-chat/composer.tsx +74 -47
  248. package/src/agent-chat/thread-workspace.tsx +8 -11
  249. package/src/agent-chat/use-keyboard-inset.ts +68 -0
  250. package/src/charts/cursor/touch-pin.ts +138 -0
  251. package/src/charts/hooks/use-discrete-cursor.ts +335 -0
  252. package/src/charts/hooks/use-hysteresis.ts +26 -0
  253. package/src/charts/hooks/useBandPlot.ts +90 -27
  254. package/src/charts/hooks/useChartCursor.ts +211 -26
  255. package/src/charts/index.ts +0 -8
  256. package/src/charts/kinds/BandStrip.tsx +25 -61
  257. package/src/charts/kinds/Donut.tsx +153 -62
  258. package/src/charts/kinds/DualPanel.tsx +21 -26
  259. package/src/charts/kinds/Heatmap.tsx +61 -22
  260. package/src/charts/kinds/MirroredBars.tsx +23 -65
  261. package/src/charts/kinds/band-chrome.tsx +91 -0
  262. package/src/charts/kinds/donut-layout.ts +82 -0
  263. package/src/charts/layout/auto-margin.ts +24 -5
  264. package/src/charts/layout/end-labels.ts +135 -0
  265. package/src/charts/primitives/Axes.tsx +112 -21
  266. package/src/charts/primitives/CartesianChart.tsx +282 -111
  267. package/src/charts/primitives/ChartCard.tsx +119 -48
  268. package/src/charts/primitives/ChartFrame.tsx +204 -60
  269. package/src/charts/primitives/ChartLegend.tsx +115 -78
  270. package/src/charts/primitives/ChartTooltip.tsx +24 -3
  271. package/src/charts/primitives/Crosshair.tsx +2 -2
  272. package/src/charts/primitives/HoverOverlay.module.css +13 -0
  273. package/src/charts/primitives/HoverOverlay.module.css.d.ts +8 -0
  274. package/src/charts/primitives/HoverOverlay.tsx +62 -20
  275. package/src/charts/primitives/chart-card-context.ts +46 -0
  276. package/src/charts/primitives/chart-frame-layout.ts +207 -182
  277. package/src/charts/primitives/chart-layout.ts +318 -0
  278. package/src/charts/primitives/chart-tier.tsx +66 -21
  279. package/src/charts/primitives/legend-disclosure.tsx +177 -0
  280. package/src/charts/series.ts +4 -1
  281. package/src/charts/utils/ticks.ts +95 -19
  282. package/src/common/errors.ts +25 -1
  283. package/src/common/hit-floor.ts +9 -0
  284. package/src/{shell → common}/isomorphic-layout-effect.ts +4 -3
  285. package/src/common/use-measured-widths.ts +88 -0
  286. package/src/common/use-media-query.ts +56 -0
  287. package/src/common/validate.ts +17 -4
  288. package/src/content/article-layout.module.css +45 -4
  289. package/src/content/article-layout.module.css.d.ts +3 -0
  290. package/src/content/article-layout.tsx +60 -5
  291. package/src/content/code-block.module.css +32 -2
  292. package/src/content/code-block.tsx +47 -3
  293. package/src/content/prose.module.css +13 -8
  294. package/src/controls/actions.module.css +14 -1
  295. package/src/controls/actions.module.css.d.ts +1 -0
  296. package/src/controls/actions.tsx +223 -75
  297. package/src/controls/controls.module.css +13 -31
  298. package/src/controls/enum-filter.tsx +2 -2
  299. package/src/controls/filter-context.tsx +11 -0
  300. package/src/controls/filter-pill.tsx +1 -0
  301. package/src/controls/index.ts +0 -1
  302. package/src/controls/multi-select-filter.tsx +2 -2
  303. package/src/controls/sync-button.module.css +2 -1
  304. package/src/dashboard/section.module.css +1 -26
  305. package/src/dashboard/section.tsx +1 -0
  306. package/src/dashboard/stat-card.module.css +6 -9
  307. package/src/dashboard/stat-card.tsx +6 -3
  308. package/src/dashboard/stat-group.module.css +33 -66
  309. package/src/dashboard/widget-grid.module.css +11 -38
  310. package/src/dashboard/widget-grid.tsx +7 -6
  311. package/src/dashboard/widget-header.module.css +145 -133
  312. package/src/dashboard/widget-header.module.css.d.ts +2 -0
  313. package/src/dashboard/widget-header.tsx +45 -11
  314. package/src/data/data-table-state.ts +218 -0
  315. package/src/data/data-table.module.css +94 -0
  316. package/src/data/data-table.module.css.d.ts +11 -0
  317. package/src/data/data-table.tsx +547 -299
  318. package/src/data/virtual-list.tsx +31 -0
  319. package/src/forms/form-layout.module.css +20 -5
  320. package/src/forms/form-layout.module.css.d.ts +1 -0
  321. package/src/forms/form-layout.tsx +12 -10
  322. package/src/guard/index.ts +188 -3
  323. package/src/guard/types.ts +3 -2
  324. package/src/index.ts +2 -0
  325. package/src/notifications/center.tsx +3 -0
  326. package/src/provider/index.tsx +60 -7
  327. package/src/shell/app-brand.module.css +2 -2
  328. package/src/shell/app-brand.tsx +1 -0
  329. package/src/shell/app-header.module.css +18 -8
  330. package/src/shell/app-main.module.css +54 -3
  331. package/src/shell/app-main.module.css.d.ts +1 -0
  332. package/src/shell/app-mobile-nav.module.css +16 -4
  333. package/src/shell/app-sidebar.module.css +4 -6
  334. package/src/shell/aside-docking.ts +54 -0
  335. package/src/shell/index.tsx +178 -129
  336. package/src/shell/mobile-nav-model.ts +1 -1
  337. package/src/shell/page-aside.tsx +70 -21
  338. package/src/shell/page-bar.module.css +10 -34
  339. package/src/shell/page-bar.tsx +10 -5
  340. package/src/shell/use-breakpoint.ts +9 -45
  341. package/src/shell/use-size-class.ts +31 -0
  342. package/src/state/persisted-or-local.ts +10 -4
  343. package/src/state/persisted.ts +76 -17
  344. package/src/styles.css +41 -0
  345. package/src/surfaces.ts +9 -1
  346. package/src/theme/controls.module.css +7 -0
  347. package/src/theme/ctl-theme.tsx +15 -3
  348. package/src/theme/floating.module.css +37 -0
  349. package/src/theme/floating.module.css.d.ts +3 -0
  350. package/src/theme/index.ts +46 -8
  351. package/src/theme/nav-link.module.css +7 -0
  352. package/src/theme-lab/derive-controls.tsx +2 -0
  353. package/src/tokens/index.ts +20 -30
  354. package/src/tokens/palette.ts +6 -28
  355. package/src/tokens/size-classes.ts +46 -0
  356. package/dist/shell/isomorphic-layout-effect.d.ts.map +0 -1
  357. /package/dist/{shell → common}/isomorphic-layout-effect.js +0 -0
@@ -18,6 +18,7 @@
18
18
  * query at all).
19
19
  */
20
20
  .root {
21
+ container: basalt-card / inline-size;
21
22
  display: flex;
22
23
  flex-direction: column;
23
24
  gap: var(--vx-space-section-gap, 0.75rem);
@@ -95,29 +96,3 @@
95
96
  .chevron[data-open='false'] svg {
96
97
  transform: rotate(-90deg);
97
98
  }
98
-
99
- /*
100
- * Law C15 — the chevron is a 12px glyph in a 20px box, which is a fine mouse target and an
101
- * unusable thumb one. Below `sm` an `::after` overlay lifts the HIT area to
102
- * `--vx-space-touch-control-height` (36px at level 0) while the visible glyph stays put — the same
103
- * overlay `shell/page-bar.module.css` draws for the bar's own controls. `overflow: visible` is part
104
- * of the fix, not tidying: an overlay that extends past the box is clipped by any `overflow:
105
- * hidden` on the host (which is what made the identical overlay a no-op on Mantine's Button roots).
106
- */
107
- @media (max-width: 47.99375em) {
108
- .chevron {
109
- overflow: visible;
110
- }
111
-
112
- .chevron::after {
113
- content: '';
114
- position: absolute;
115
- top: 50%;
116
- left: 50%;
117
- translate: -50% -50%;
118
- width: 100%;
119
- height: 100%;
120
- min-width: var(--vx-space-touch-control-height, 2.25rem);
121
- min-height: var(--vx-space-touch-control-height, 2.25rem);
122
- }
123
- }
@@ -102,7 +102,7 @@ export type StatCardProps = BasaltProps & SlotStylesProps<StatCardSlot> & Widget
102
102
  */
103
103
  sparkline?: ReactNode | ((size: StatCardSparklineSize) => ReactNode);
104
104
  /** Where `sparkline` sits. `'bleed'` (default) is today's full-width row bled to the card edges;
105
- * `'right'` sits it beside the hero value row. Collapses to `'bleed'` below `sm`. */
105
+ * `'right'` sits it beside the hero value row. Collapses to `'bleed'` in a card narrower than 480px. */
106
106
  sparklinePlacement?: 'bleed' | 'right';
107
107
  /** Header-right slot (e.g. a ghost "..." menu trigger) — wrapped in `CtlSlot tier="widget"`, so a
108
108
  * raw `ActionIcon` with no `size` lands on the 24px step the 28px header row holds (C1/C5). */
@@ -1 +1 @@
1
- {"version":3,"file":"stat-card.d.ts","sourceRoot":"","sources":["../../src/dashboard/stat-card.tsx"],"names":[],"mappings":"AAgGA,OAAO,KAAK,EAAiB,SAAS,EAAE,MAAM,OAAO,CAAA;AAErD,OAAO,KAAK,EACV,sBAAsB,EACtB,uBAAuB,EACvB,sBAAsB,EACvB,MAAM,iBAAiB,CAAA;AAIxB,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAA;AAEzE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAGnD;;;;GAIG;AACH,MAAM,MAAM,YAAY,GAAG,IAAI,CAAA;AAE/B;;;;GAIG;AACH,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,QAAQ,GAAG,MAAM,GAAG,WAAW,CAAA;AAEnE;;;;;;;GAOG;AACH,MAAM,MAAM,oBAAoB,GAAG;IACjC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,IAAI,CAAC,EAAE,YAAY,CAAA;CAC7B,CAAA;AAcD;;;;;;;;GAQG;AACH,MAAM,MAAM,qBAAqB,GAAG;IAClC,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;CACf,CAAA;AAkDD;;;;;;;;;;;;;;GAcG;AACH,MAAM,MAAM,aAAa,GAAG,WAAW,GACrC,eAAe,CAAC,YAAY,CAAC,GAC7B,sBAAsB,GACtB,IAAI,CAAC,uBAAuB,EAAE,OAAO,CAAC,GACtC,sBAAsB,GAAG;IACvB;iEAC6D;IAC7D,KAAK,EAAE,MAAM,CAAA;IACb;;;;;;;;;;;;OAYG;IACH,SAAS,CAAC,EAAE,SAAS,oBAAoB,EAAE,CAAA;IAC3C;;;;;;;;;;;;;OAaG;IACH,KAAK,CAAC,EAAE,cAAc,CAAC,OAAO,CAAC,CAAA;IAC/B;;;;;;;;;;;OAWG;IACH,SAAS,CAAC,EAAE,SAAS,GAAG,CAAC,CAAC,IAAI,EAAE,qBAAqB,KAAK,SAAS,CAAC,CAAA;IACpE;yFACqF;IACrF,kBAAkB,CAAC,EAAE,OAAO,GAAG,OAAO,CAAA;IACtC;mGAC+F;IAC/F,OAAO,CAAC,EAAE,SAAS,CAAA;IACnB;;;+EAG2E;IAC3E,IAAI,CAAC,EAAE,YAAY,CAAA;CACpB,CAAA;AAEH,wBAAgB,QAAQ,CAAC,EACvB,KAAK,EACL,IAAI,EACJ,QAAQ,EACR,IAAI,EACJ,KAAK,EACL,IAAI,EACJ,SAAS,EACT,KAAK,EACL,KAAK,EACL,WAAW,EACX,aAAa,EACb,WAAW,EACX,UAAU,EACV,SAAS,EACT,kBAA4B,EAC5B,OAAO,EACP,IAAI,EACJ,SAAS,EACT,KAAK,EACL,UAAU,GACX,EAAE,aAAa,+BAkKf"}
1
+ {"version":3,"file":"stat-card.d.ts","sourceRoot":"","sources":["../../src/dashboard/stat-card.tsx"],"names":[],"mappings":"AAgGA,OAAO,KAAK,EAAiB,SAAS,EAAE,MAAM,OAAO,CAAA;AAErD,OAAO,KAAK,EACV,sBAAsB,EACtB,uBAAuB,EACvB,sBAAsB,EACvB,MAAM,iBAAiB,CAAA;AAIxB,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAA;AAEzE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAGnD;;;;GAIG;AACH,MAAM,MAAM,YAAY,GAAG,IAAI,CAAA;AAE/B;;;;GAIG;AACH,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,QAAQ,GAAG,MAAM,GAAG,WAAW,CAAA;AAEnE;;;;;;;GAOG;AACH,MAAM,MAAM,oBAAoB,GAAG;IACjC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,IAAI,CAAC,EAAE,YAAY,CAAA;CAC7B,CAAA;AAcD;;;;;;;;GAQG;AACH,MAAM,MAAM,qBAAqB,GAAG;IAClC,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;CACf,CAAA;AAkDD;;;;;;;;;;;;;;GAcG;AACH,MAAM,MAAM,aAAa,GAAG,WAAW,GACrC,eAAe,CAAC,YAAY,CAAC,GAC7B,sBAAsB,GACtB,IAAI,CAAC,uBAAuB,EAAE,OAAO,CAAC,GACtC,sBAAsB,GAAG;IACvB;iEAC6D;IAC7D,KAAK,EAAE,MAAM,CAAA;IACb;;;;;;;;;;;;OAYG;IACH,SAAS,CAAC,EAAE,SAAS,oBAAoB,EAAE,CAAA;IAC3C;;;;;;;;;;;;;OAaG;IACH,KAAK,CAAC,EAAE,cAAc,CAAC,OAAO,CAAC,CAAA;IAC/B;;;;;;;;;;;OAWG;IACH,SAAS,CAAC,EAAE,SAAS,GAAG,CAAC,CAAC,IAAI,EAAE,qBAAqB,KAAK,SAAS,CAAC,CAAA;IACpE;4GACwG;IACxG,kBAAkB,CAAC,EAAE,OAAO,GAAG,OAAO,CAAA;IACtC;mGAC+F;IAC/F,OAAO,CAAC,EAAE,SAAS,CAAA;IACnB;;;+EAG2E;IAC3E,IAAI,CAAC,EAAE,YAAY,CAAA;CACpB,CAAA;AAEH,wBAAgB,QAAQ,CAAC,EACvB,KAAK,EACL,IAAI,EACJ,QAAQ,EACR,IAAI,EACJ,KAAK,EACL,IAAI,EACJ,SAAS,EACT,KAAK,EACL,KAAK,EACL,WAAW,EACX,aAAa,EACb,WAAW,EACX,UAAU,EACV,SAAS,EACT,kBAA4B,EAC5B,OAAO,EACP,IAAI,EACJ,SAAS,EACT,KAAK,EACL,UAAU,GACX,EAAE,aAAa,+BAqKf"}
@@ -88,7 +88,7 @@ function StatCard({
88
88
  ),
89
89
  ...!bleeds && {
90
90
  // CUSTOM PROPERTIES, not `flexBasis`/`height` directly. A React inline style beats every
91
- // stylesheet rule, so an inline `flexBasis: 72` also applied below `sm` — where `'right'`
91
+ // stylesheet rule, so an inline `flexBasis: 72` also applied in a narrow card — where `'right'`
92
92
  // collapses `.metricsRow` to a COLUMN and flex-basis is therefore the main-axis HEIGHT.
93
93
  // The mobile sparkline rendered in a 72px-tall box holding 26px of bars, which is the dead
94
94
  // band under every KPI value on a phone. Handed to CSS as values instead, the media query
@@ -128,6 +128,9 @@ function StatCard({
128
128
  // Anchors the tone rail. Set unconditionally so a card's stacking context does not change
129
129
  // depending on whether it happens to have crossed a threshold this render.
130
130
  position: "relative",
131
+ // The card's own width drives its chrome (`widget-header.module.css`, `.metricsRow`).
132
+ containerType: "inline-size",
133
+ containerName: "basalt-card",
131
134
  ...style
132
135
  },
133
136
  "data-tone": tone,
@@ -1,11 +1,8 @@
1
1
  /*
2
- * StatCard's sparkline placement (docs/CONTROLS-SPEC.md §2.2). `bleed` (default) keeps the historic
3
- * full-width row beneath the hero value, bled past the card's own inset padding — same negative
4
- * margins the pre-WidgetHeader version drew inline. `right` sits the sparkline beside the
5
- * BREAKDOWN row instead, the reference-design look, and collapses back to `bleed`'s stacked layout
6
- * below `sm` — CSS only for the sparkline's own box, `.metricsRow` below for the row it sits in
7
- * (`47.99375em` is Mantine's own complement of `min-width: 48em`, same value
8
- * `content/prose.module.css` derives it from).
2
+ * StatCard's sparkline placement (docs/CONTROLS-SPEC.md §2.2). `bleed` (default) keeps the full-width
3
+ * row beneath the hero value, bled past the card's inset padding. `right` sits the sparkline beside
4
+ * the BREAKDOWN row and collapses back to `bleed`'s stacked layout when the card itself is narrower
5
+ * than 480px (`container: basalt-card`, set on the Card root in `stat-card.tsx`).
9
6
  */
10
7
 
11
8
  .body {
@@ -131,7 +128,7 @@
131
128
  }
132
129
 
133
130
  /* Asks for `StatCard`'s `SPARKLINE_RIGHT_WIDTH`/`_HEIGHT` (handed down as custom properties, so this
134
- * rule and the `< sm` reset below can both reach them). `align-self: flex-end` is the one alignment
131
+ * rule and the narrow-card reset below can both reach them). `align-self: flex-end` is the one alignment
135
132
  * this restructure keeps at the SPARKLINE's own level rather than the row's: `.metricsRow` does not
136
133
  * set `align-items: flex-end` itself, because a card with no breakdown would then need nothing to
137
134
  * anchor against — only the sparkline opts into sitting at the row's bottom edge, which matters once
@@ -146,7 +143,7 @@
146
143
  overflow: hidden;
147
144
  }
148
145
 
149
- @media (max-width: 47.99375em) {
146
+ @container basalt-card (max-width: 479.9px) {
150
147
  .metricsRow {
151
148
  flex-direction: column;
152
149
  align-items: stretch;
@@ -2,8 +2,8 @@
2
2
  * StatGroup's column law and its optional rail, in CSS (law C9).
3
3
  *
4
4
  * **The law keys on the CONTAINER, not the viewport.** A viewport breakpoint answers the wrong
5
- * question — the same one `resolveChartTier` refuses to ask (`charts/primitives/chart-frame-layout.
6
- * ts`): the shell has regions that change the AVAILABLE width with the viewport held still (a
5
+ * question — the same one `resolveContainerClass` refuses to ask (`tokens/size-classes.ts`): the
6
+ * shell has regions that change the AVAILABLE width with the viewport held still (a
7
7
  * `PageAside` claiming its 300px, the sidebar collapsing 256px → its 48px rail, a consumer's own
8
8
  * split layout), and `@media` cannot see any of them. Measured defect: a `PageAside` mounted on a
9
9
  * 1512px desktop left the KPI row ~956px wide, `@media` still resolved `lg`, and four cells of
@@ -15,25 +15,24 @@
15
15
  * one: a query with no container resolves to false, so a shell-only context would have silently
16
16
  * pinned every non-shell consumer to the base count.
17
17
  *
18
- * The `@supports not` block below it is the pre-2023 fallback and the ONLY place the old viewport
19
- * law survives. It is written as an exclusive alternative rather than as a base the container
20
- * queries override, because the rail's `:nth-child` suppressors are MORE specific than the rule
21
- * that draws the border: two overlapping laws would each suppress a different set of leading cells
22
- * and the rail would lose hairlines in the middle of a row. One law at a time, chosen by support.
18
+ * The literals are the container-class law (`CONTAINER_CLASSES`, `tokens/size-classes.ts`): the
19
+ * `sm` count opens at `wide` (800px), not at the viewport-era 768. Two are StatGroup's own and say
20
+ * so: 260px (one column, below) and 1200px, where the full `cols` count opens. The class table
21
+ * stops at 800, and 800 is too early for a full KPI row — four cells of ~190px clamp a value a real
22
+ * dashboard prints (`tests/layout/page-aside.layout.test.ts` measures ~195px against the 844px row
23
+ * a claimed aside leaves). Conditions are px, never `em`: `em` inside a `@container` condition
24
+ * resolves against the CONTAINER's font-size, so a consumer panel with smaller text would silently
25
+ * move the boundary. A condition cannot read a custom property, so the numbers are written; the
26
+ * COUNTS are custom properties the component sets per instance.
23
27
  *
24
- * The literals: `@container` conditions are stated in px, `@media` ones in Mantine's own `em`
25
- * (`--mantine-breakpoint-sm` 48em, `--mantine-breakpoint-lg` 75em). Both spellings name the same
26
- * boundary at the 16px initial font size — 768px and 1200px — but `em` inside a `@container`
27
- * condition resolves against the CONTAINER's font-size rather than the root's, so a consumer panel
28
- * with smaller text would silently move the breakpoint. px is the only spelling that cannot drift.
29
- * (`47.99375em` → `767.9px`, `74.99375em` → `1199.9px`; the same complements `stat-card.module.css`
30
- * uses.) A condition still cannot read a custom property either way, so the numbers are written;
31
- * the COUNTS are custom properties the component sets per instance.
28
+ * No viewport fallback: basalt's own CSS already requires `color-mix()` (Safari 16.2, Chrome 111,
29
+ * Firefox 113), and every one of those parses `@container` — a `@supports not (container-type)`
30
+ * block is unreachable in any browser that renders basalt at all.
32
31
  */
33
32
 
34
33
  .container {
35
34
  container-type: inline-size;
36
- container-name: basalt-stat-group;
35
+ container-name: basalt-grid;
37
36
  }
38
37
 
39
38
  .root {
@@ -44,13 +43,26 @@
44
43
  gap: var(--vx-space-stack-md);
45
44
  }
46
45
 
47
- @container basalt-stat-group (min-width: 768px) {
46
+ /* 260px is StatGroup's own literal (docs/DESIGN-CORE.md § Layout, elevation, shapes), not a container class: one column below it,
47
+ * so every cell leads a row and the rail draws no leading hairline at all. */
48
+ @container basalt-grid (max-width: 259.9px) {
49
+ .root {
50
+ grid-template-columns: minmax(0, 1fr);
51
+ }
52
+
53
+ .root[data-divided] > *:nth-child(n) {
54
+ border-inline-start: 0;
55
+ padding-inline-start: 0;
56
+ }
57
+ }
58
+
59
+ @container basalt-grid (min-width: 800px) {
48
60
  .root {
49
61
  grid-template-columns: repeat(var(--basalt-stat-group-cols-sm), minmax(0, 1fr));
50
62
  }
51
63
  }
52
64
 
53
- @container basalt-stat-group (min-width: 1200px) {
65
+ @container basalt-grid (min-width: 1200px) {
54
66
  .root {
55
67
  grid-template-columns: repeat(var(--basalt-stat-group-cols-lg), minmax(0, 1fr));
56
68
  }
@@ -71,14 +83,14 @@
71
83
  padding-inline-start: var(--vx-space-stack-md);
72
84
  }
73
85
 
74
- @container basalt-stat-group (max-width: 767.9px) {
86
+ @container basalt-grid (max-width: 799.9px) {
75
87
  .root[data-divided] > *:nth-child(2n + 1) {
76
88
  border-inline-start: 0;
77
89
  padding-inline-start: 0;
78
90
  }
79
91
  }
80
92
 
81
- @container basalt-stat-group (min-width: 768px) and (max-width: 1199.9px) {
93
+ @container basalt-grid (min-width: 800px) and (max-width: 1199.9px) {
82
94
  .root[data-divided][data-sm-cols='2'] > *:nth-child(2n + 1),
83
95
  .root[data-divided][data-sm-cols='3'] > *:nth-child(3n + 1) {
84
96
  border-inline-start: 0;
@@ -86,7 +98,7 @@
86
98
  }
87
99
  }
88
100
 
89
- @container basalt-stat-group (min-width: 1200px) {
101
+ @container basalt-grid (min-width: 1200px) {
90
102
  .root[data-divided][data-cols='2'] > *:nth-child(2n + 1),
91
103
  .root[data-divided][data-cols='3'] > *:nth-child(3n + 1),
92
104
  .root[data-divided][data-cols='4'] > *:nth-child(4n + 1),
@@ -95,48 +107,3 @@
95
107
  padding-inline-start: 0;
96
108
  }
97
109
  }
98
-
99
- /*
100
- * The pre-container-query fallback — Safari < 16, Chrome < 106, Firefox < 110. Verbatim the law
101
- * this file shipped before, keyed on the viewport, and reachable ONLY where `@container` is not.
102
- * A browser that cannot parse `container-type` also cannot parse the `@container` blocks above, so
103
- * the two sets are never live at once.
104
- */
105
- @supports not (container-type: inline-size) {
106
- @media (min-width: 48em) {
107
- .root {
108
- grid-template-columns: repeat(var(--basalt-stat-group-cols-sm), minmax(0, 1fr));
109
- }
110
- }
111
-
112
- @media (min-width: 75em) {
113
- .root {
114
- grid-template-columns: repeat(var(--basalt-stat-group-cols-lg), minmax(0, 1fr));
115
- }
116
- }
117
-
118
- @media (max-width: 47.99375em) {
119
- .root[data-divided] > *:nth-child(2n + 1) {
120
- border-inline-start: 0;
121
- padding-inline-start: 0;
122
- }
123
- }
124
-
125
- @media (min-width: 48em) and (max-width: 74.99375em) {
126
- .root[data-divided][data-sm-cols='2'] > *:nth-child(2n + 1),
127
- .root[data-divided][data-sm-cols='3'] > *:nth-child(3n + 1) {
128
- border-inline-start: 0;
129
- padding-inline-start: 0;
130
- }
131
- }
132
-
133
- @media (min-width: 75em) {
134
- .root[data-divided][data-cols='2'] > *:nth-child(2n + 1),
135
- .root[data-divided][data-cols='3'] > *:nth-child(3n + 1),
136
- .root[data-divided][data-cols='4'] > *:nth-child(4n + 1),
137
- .root[data-divided][data-cols='5'] > *:nth-child(5n + 1) {
138
- border-inline-start: 0;
139
- padding-inline-start: 0;
140
- }
141
- }
142
- }
@@ -1 +1 @@
1
- {"version":3,"file":"widget-grid.d.ts","sourceRoot":"","sources":["../../src/dashboard/widget-grid.tsx"],"names":[],"mappings":"AAoDA,OAAO,KAAK,EAAiB,SAAS,EAAE,MAAM,OAAO,CAAA;AAErD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAGlD,uGAAuG;AACvG,MAAM,MAAM,cAAc,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;AAgB1C,MAAM,MAAM,eAAe,GAAG,WAAW,GAAG;IAC1C;8FAC0F;IAC1F,IAAI,CAAC,EAAE,cAAc,CAAA;IACrB,8FAA8F;IAC9F,QAAQ,EAAE,SAAS,CAAA;CACpB,CAAA;AAED,wBAAgB,UAAU,CAAC,EAAE,IAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,eAAe,+BA8BnF;yBA9Be,UAAU;;;AAgC1B,MAAM,MAAM,mBAAmB,GAAG,WAAW,GAAG;IAC9C,oGAAoG;IACpG,IAAI,CAAC,EAAE,cAAc,CAAA;IACrB,sCAAsC;IACtC,QAAQ,EAAE,SAAS,CAAA;CACpB,CAAA;AAED;;GAEG;AACH,iBAAS,cAAc,CAAC,EAAE,IAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,mBAAmB,+BAkBpF"}
1
+ {"version":3,"file":"widget-grid.d.ts","sourceRoot":"","sources":["../../src/dashboard/widget-grid.tsx"],"names":[],"mappings":"AAqDA,OAAO,KAAK,EAAiB,SAAS,EAAE,MAAM,OAAO,CAAA;AAErD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAGlD,uGAAuG;AACvG,MAAM,MAAM,cAAc,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;AAgB1C,MAAM,MAAM,eAAe,GAAG,WAAW,GAAG;IAC1C;8FAC0F;IAC1F,IAAI,CAAC,EAAE,cAAc,CAAA;IACrB,8FAA8F;IAC9F,QAAQ,EAAE,SAAS,CAAA;CACpB,CAAA;AAED,wBAAgB,UAAU,CAAC,EAAE,IAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,eAAe,+BA8BnF;yBA9Be,UAAU;;;AAgC1B,MAAM,MAAM,mBAAmB,GAAG,WAAW,GAAG;IAC9C,oGAAoG;IACpG,IAAI,CAAC,EAAE,cAAc,CAAA;IACrB,sCAAsC;IACtC,QAAQ,EAAE,SAAS,CAAA;CACpB,CAAA;AAED;;GAEG;AACH,iBAAS,cAAc,CAAC,EAAE,IAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,mBAAmB,+BAkBpF"}
@@ -15,18 +15,19 @@
15
15
  * container. A span resolved against the viewport while the tracks follow the container is exactly
16
16
  * the phantom-track defect `WidgetGrid.Item`'s context clamp exists to prevent.
17
17
  *
18
- * The literals: px in `@container`, Mantine's own `em` in the `@supports not` fallback — same
19
- * boundary (768px / 1200px at the 16px initial font size), but `em` inside a `@container`
20
- * condition resolves against the CONTAINER's font-size, so px is the only spelling that cannot
21
- * drift. A condition cannot read a custom property either way, so the numbers are written; the
22
- * COUNTS are custom properties, set once per instance by the component — three hand-written
23
- * `repeat()` blocks would have to enumerate every `cols` value, and the whole point of this
24
- * primitive is that a consumer states one desktop number and basalt owns the rest.
18
+ * The literals are the container-class law, as in `stat-group.module.css`: the `sm` count opens
19
+ * at `wide` (800px); 1200px, where the full `cols` count opens, is the grid's own boundary above
20
+ * the class table's top step. px, never `em` (an `em` condition resolves against the container's
21
+ * font-size). A condition cannot read a custom property, so the numbers are written; the COUNTS
22
+ * are custom properties, set once per instance by the component — three hand-written `repeat()`
23
+ * blocks would have to enumerate every `cols` value, and the whole point of this primitive is that
24
+ * a consumer states one desktop number and basalt owns the rest. No viewport fallback, for the
25
+ * reason `stat-group.module.css` states: nothing that renders basalt lacks `@container`.
25
26
  */
26
27
 
27
28
  .container {
28
29
  container-type: inline-size;
29
- container-name: basalt-widget-grid;
30
+ container-name: basalt-grid;
30
31
  }
31
32
 
32
33
  .root {
@@ -47,7 +48,7 @@
47
48
  min-width: 0;
48
49
  }
49
50
 
50
- @container basalt-widget-grid (min-width: 768px) {
51
+ @container basalt-grid (min-width: 800px) {
51
52
  .root {
52
53
  grid-template-columns: repeat(var(--basalt-widget-grid-cols-sm), minmax(0, 1fr));
53
54
  }
@@ -57,7 +58,7 @@
57
58
  }
58
59
  }
59
60
 
60
- @container basalt-widget-grid (min-width: 1200px) {
61
+ @container basalt-grid (min-width: 1200px) {
61
62
  .root {
62
63
  grid-template-columns: repeat(var(--basalt-widget-grid-cols-lg), minmax(0, 1fr));
63
64
  }
@@ -66,31 +67,3 @@
66
67
  grid-column: span var(--basalt-widget-grid-span-lg);
67
68
  }
68
69
  }
69
-
70
- /*
71
- * The pre-container-query fallback — Safari < 16, Chrome < 106, Firefox < 110. Verbatim the law
72
- * this file shipped before, keyed on the viewport, and reachable ONLY where `@container` is not: a
73
- * browser that cannot parse `container-type` cannot parse the blocks above either, so the two sets
74
- * are never live at once.
75
- */
76
- @supports not (container-type: inline-size) {
77
- @media (min-width: 48em) {
78
- .root {
79
- grid-template-columns: repeat(var(--basalt-widget-grid-cols-sm), minmax(0, 1fr));
80
- }
81
-
82
- .item {
83
- grid-column: span var(--basalt-widget-grid-span-sm);
84
- }
85
- }
86
-
87
- @media (min-width: 75em) {
88
- .root {
89
- grid-template-columns: repeat(var(--basalt-widget-grid-cols-lg), minmax(0, 1fr));
90
- }
91
-
92
- .item {
93
- grid-column: span var(--basalt-widget-grid-span-lg);
94
- }
95
- }
96
- }
@@ -24,7 +24,9 @@ export type WidgetHeaderProps = BasaltProps & SlotStylesProps<WidgetHeaderSlot>
24
24
  title: string;
25
25
  /** Optional leading icon, rendered before the title. Decorative — hidden from assistive tech. */
26
26
  icon?: ReactNode;
27
- /** Optional muted line rendered below the title row. */
27
+ /** Optional muted line rendered below the title row. In a card narrower than 480px, or shorter
28
+ * than 280px regardless of width, it folds into the info glyph's bubble instead (CSS only —
29
+ * exactly one of the two shows). */
28
30
  subtitle?: string;
29
31
  /**
30
32
  * Renders an info glyph BESIDE the heading (never inside it — this text would otherwise become
@@ -34,8 +36,8 @@ export type WidgetHeaderProps = BasaltProps & SlotStylesProps<WidgetHeaderSlot>
34
36
  * click — so a keyboard user gets it too. Mantine-free: a plain state bubble, not a Tooltip.
35
37
  */
36
38
  info?: string;
37
- /** Pre-formatted metric value (mono, hero size). Renders on its own row with `delta`, directly
38
- * under the title row — never inline with the title. */
39
+ /** Pre-formatted metric value (mono, hero size, never truncated). Renders on its own row with
40
+ * `delta` under the title row, or on the title row in a card 480px or wider. */
39
41
  value?: string;
40
42
  /**
41
43
  * The value's unit, rendered immediately after it on the hero row: muted, mono, `--vx-text-sm`.
@@ -125,8 +127,16 @@ export type WidgetHeaderDeltaProps = Pick<WidgetHeaderProps, 'delta' | 'deltaPer
125
127
  * composes it so an inspector row's `hint` is the same glyph, bubble and keyboard behaviour a
126
128
  * `WidgetHeader`'s `info` is — not a second one that drifts.
127
129
  */
128
- export declare function InfoGlyph({ text }: {
130
+ export declare function InfoGlyph({ text, note, ariaLabel, className, }: {
129
131
  text: string;
132
+ /** A second paragraph in the bubble, shown only where `.foldNote` is (the folded subtitle). */
133
+ note?: string;
134
+ /** The GLYPH's own accessible name. Default `'More information'`; `WidgetHeader` overrides it to
135
+ * include the subtitle text for its fold-glyph mount (`info === undefined`), where this trigger
136
+ * IS the subtitle's only accessible surface — the bubble it opens is otherwise unreachable
137
+ * without first knowing there is something to open. */
138
+ ariaLabel?: string;
139
+ className?: string;
130
140
  }): import("react").JSX.Element;
131
141
  export declare function WidgetHeader({ tier, title, icon, subtitle, info, value, unit, delta, deltaPeriod, deltaPolarity, deltaFormat, deltaGlyph, sparkline, count, actions, className, style, classNames, }: WidgetHeaderProps): import("react").JSX.Element;
132
142
  //# sourceMappingURL=widget-header.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"widget-header.d.ts","sourceRoot":"","sources":["../../src/dashboard/widget-header.tsx"],"names":[],"mappings":"AA8BA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAEtC,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAGnE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA;AAGlD,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,QAAQ,GAAG,OAAO,CAAA;AAE7D;;;;;;;;;GASG;AACH,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAA;AAEnE,MAAM,MAAM,iBAAiB,GAAG,WAAW,GACzC,eAAe,CAAC,gBAAgB,CAAC,GAAG;IAClC;;;;gDAI4C;IAC5C,IAAI,EAAE,gBAAgB,CAAA;IACtB,iDAAiD;IACjD,KAAK,EAAE,MAAM,CAAA;IACb,iGAAiG;IACjG,IAAI,CAAC,EAAE,SAAS,CAAA;IAChB,wDAAwD;IACxD,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;;;;;;OAMG;IACH,IAAI,CAAC,EAAE,MAAM,CAAA;IACb;4DACwD;IACxD,KAAK,CAAC,EAAE,MAAM,CAAA;IACd;;;;;;;;;;;OAWG;IACH,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,sFAAsF;IACtF,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,mEAAmE;IACnE,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB;qEACiE;IACjE,aAAa,CAAC,EAAE,aAAa,CAAA;IAC7B;;;;;;;;;;;;OAYG;IACH,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAA;IACvC;4DACwD;IACxD,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB;yDACqD;IACrD,SAAS,CAAC,EAAE,SAAS,CAAA;IACrB;2EACuE;IACvE,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,4FAA4F;IAC5F,OAAO,CAAC,EAAE,SAAS,CAAA;CACpB,CAAA;AAEH;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,MAAM,sBAAsB,GAAG,IAAI,CAAC,iBAAiB,EAAE,OAAO,GAAG,MAAM,GAAG,UAAU,GAAG,MAAM,CAAC,CAAA;AAEpG;;;GAGG;AACH,MAAM,MAAM,uBAAuB,GAAG,IAAI,CAAC,iBAAiB,EAAE,OAAO,GAAG,MAAM,CAAC,CAAA;AAE/E;;;;GAIG;AACH,MAAM,MAAM,sBAAsB,GAAG,IAAI,CACvC,iBAAiB,EACjB,OAAO,GAAG,aAAa,GAAG,eAAe,GAAG,aAAa,GAAG,YAAY,CACzE,CAAA;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,SAAS,CAAC,EAAE,IAAI,EAAE,EAAE;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,+BA8CnD;AAED,wBAAgB,YAAY,CAAC,EAC3B,IAAI,EACJ,KAAK,EACL,IAAI,EACJ,QAAQ,EACR,IAAI,EACJ,KAAK,EACL,IAAI,EACJ,KAAK,EACL,WAAW,EACX,aAAa,EACb,WAAW,EACX,UAAU,EACV,SAAS,EACT,KAAK,EACL,OAAO,EACP,SAAS,EACT,KAAK,EACL,UAAU,GACX,EAAE,iBAAiB,+BAoDnB"}
1
+ {"version":3,"file":"widget-header.d.ts","sourceRoot":"","sources":["../../src/dashboard/widget-header.tsx"],"names":[],"mappings":"AAgCA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAEtC,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAGnE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA;AAGlD,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,QAAQ,GAAG,OAAO,CAAA;AAE7D;;;;;;;;;GASG;AACH,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAA;AAEnE,MAAM,MAAM,iBAAiB,GAAG,WAAW,GACzC,eAAe,CAAC,gBAAgB,CAAC,GAAG;IAClC;;;;gDAI4C;IAC5C,IAAI,EAAE,gBAAgB,CAAA;IACtB,iDAAiD;IACjD,KAAK,EAAE,MAAM,CAAA;IACb,iGAAiG;IACjG,IAAI,CAAC,EAAE,SAAS,CAAA;IAChB;;wCAEoC;IACpC,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;;;;;;OAMG;IACH,IAAI,CAAC,EAAE,MAAM,CAAA;IACb;oFACgF;IAChF,KAAK,CAAC,EAAE,MAAM,CAAA;IACd;;;;;;;;;;;OAWG;IACH,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,sFAAsF;IACtF,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,mEAAmE;IACnE,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB;qEACiE;IACjE,aAAa,CAAC,EAAE,aAAa,CAAA;IAC7B;;;;;;;;;;;;OAYG;IACH,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAA;IACvC;4DACwD;IACxD,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB;yDACqD;IACrD,SAAS,CAAC,EAAE,SAAS,CAAA;IACrB;2EACuE;IACvE,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,4FAA4F;IAC5F,OAAO,CAAC,EAAE,SAAS,CAAA;CACpB,CAAA;AAEH;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,MAAM,sBAAsB,GAAG,IAAI,CAAC,iBAAiB,EAAE,OAAO,GAAG,MAAM,GAAG,UAAU,GAAG,MAAM,CAAC,CAAA;AAEpG;;;GAGG;AACH,MAAM,MAAM,uBAAuB,GAAG,IAAI,CAAC,iBAAiB,EAAE,OAAO,GAAG,MAAM,CAAC,CAAA;AAE/E;;;;GAIG;AACH,MAAM,MAAM,sBAAsB,GAAG,IAAI,CACvC,iBAAiB,EACjB,OAAO,GAAG,aAAa,GAAG,eAAe,GAAG,aAAa,GAAG,YAAY,CACzE,CAAA;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,SAAS,CAAC,EACxB,IAAI,EACJ,IAAI,EACJ,SAA8B,EAC9B,SAAS,GACV,EAAE;IACD,IAAI,EAAE,MAAM,CAAA;IACZ,+FAA+F;IAC/F,IAAI,CAAC,EAAE,MAAM,CAAA;IACb;;;2DAGuD;IACvD,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,+BAgDA;AAED,wBAAgB,YAAY,CAAC,EAC3B,IAAI,EACJ,KAAK,EACL,IAAI,EACJ,QAAQ,EACR,IAAI,EACJ,KAAK,EACL,IAAI,EACJ,KAAK,EACL,WAAW,EACX,aAAa,EACb,WAAW,EACX,UAAU,EACV,SAAS,EACT,KAAK,EACL,OAAO,EACP,SAAS,EACT,KAAK,EACL,UAAU,GACX,EAAE,iBAAiB,+BAiEnB"}
@@ -4,7 +4,12 @@ import { cx } from "../common/props.js";
4
4
  import { IconSlot } from "../theme/icon-slot.js";
5
5
  import { DeltaBadge } from "./delta-badge.js";
6
6
  import classes from "./widget-header.module.css";
7
- function InfoGlyph({ text }) {
7
+ function InfoGlyph({
8
+ text,
9
+ note,
10
+ ariaLabel = "More information",
11
+ className
12
+ }) {
8
13
  const [open, setOpen] = useState(false);
9
14
  const tipId = useId();
10
15
  const triggerRef = useRef(null);
@@ -17,14 +22,15 @@ function InfoGlyph({ text }) {
17
22
  document.addEventListener("pointerdown", handlePointerDown);
18
23
  return () => document.removeEventListener("pointerdown", handlePointerDown);
19
24
  }, [open]);
20
- return /* @__PURE__ */ jsxs("span", { className: classes.info, children: [
25
+ return /* @__PURE__ */ jsxs("span", { className: cx(classes.info, className), children: [
21
26
  /* @__PURE__ */ jsx(
22
27
  "button",
23
28
  {
24
29
  ref: triggerRef,
25
30
  type: "button",
31
+ "data-basalt-hit": true,
26
32
  className: classes.infoTrigger,
27
- "aria-label": "More information",
33
+ "aria-label": ariaLabel,
28
34
  "aria-describedby": open ? tipId : void 0,
29
35
  "data-open": open,
30
36
  onMouseEnter: () => setOpen(true),
@@ -38,7 +44,10 @@ function InfoGlyph({ text }) {
38
44
  children: /* @__PURE__ */ jsx("svg", { width: 11, height: 11, viewBox: "0 0 24 24", fill: "currentColor", "aria-hidden": "true", children: /* @__PURE__ */ jsx("path", { d: "M12 0C5.373 0 0 5.373 0 12s5.373 12 12 12 12-5.373 12-12S18.627 0 12 0zm0 4a1.5 1.5 0 1 1 0 3 1.5 1.5 0 0 1 0-3zm0 5a1 1 0 0 1 1 1v7a1 1 0 1 1-2 0v-7a1 1 0 0 1 1-1z" }) })
39
45
  }
40
46
  ),
41
- open && /* @__PURE__ */ jsx("span", { id: tipId, role: "tooltip", className: classes.infoBubble, children: text })
47
+ open && /* @__PURE__ */ jsxs("span", { id: tipId, role: "tooltip", className: classes.infoBubble, children: [
48
+ text,
49
+ note !== void 0 && /* @__PURE__ */ jsx("span", { className: classes.foldNote, children: note })
50
+ ] })
42
51
  ] });
43
52
  }
44
53
  function WidgetHeader({
@@ -74,9 +83,17 @@ function WidgetHeader({
74
83
  icon !== void 0 && /* @__PURE__ */ jsx(IconSlot, { className: cx(classes.icon, classNames?.icon), children: icon }),
75
84
  /* @__PURE__ */ jsx("span", { className: classes.titleText, children: title })
76
85
  ] }),
77
- info !== void 0 && /* @__PURE__ */ jsx(InfoGlyph, { text: info }),
86
+ info !== void 0 && /* @__PURE__ */ jsx(InfoGlyph, { text: info, ...subtitle !== void 0 && { note: subtitle } }),
87
+ info === void 0 && subtitle !== void 0 && /* @__PURE__ */ jsx(
88
+ InfoGlyph,
89
+ {
90
+ text: subtitle,
91
+ className: classes.foldGlyph,
92
+ ariaLabel: `More information: ${subtitle}`
93
+ }
94
+ ),
78
95
  count !== void 0 && /* @__PURE__ */ jsx("span", { className: classes.count, children: count }),
79
- actions !== void 0 && /* @__PURE__ */ jsx("span", { className: classes.actions, children: actions })
96
+ actions !== void 0 && /* @__PURE__ */ jsx("span", { className: classes.actions, "data-basalt-hit-scope": true, children: actions })
80
97
  ] }),
81
98
  (value !== void 0 || delta !== void 0) && /* @__PURE__ */ jsxs("div", { className: cx(classes.metrics, classNames?.metric), children: [
82
99
  value !== void 0 && /* @__PURE__ */ jsx("span", { className: classes.value, children: value }),