@cueplusplus/ui 0.15.0 → 0.17.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 (508) hide show
  1. package/CHANGELOG.md +1083 -0
  2. package/README.md +26 -0
  3. package/dist/agent-runtime/tool-call-card.js +7 -3
  4. package/dist/brand/_chassis.d.ts +1 -1
  5. package/dist/brand/cue-mark.d.ts +1 -1
  6. package/dist/brand/cue-mark.js +1 -1
  7. package/dist/charts/ramps.js +1 -1
  8. package/dist/chat/agent-pile.js +2 -1
  9. package/dist/chat/ask-box.js +4 -3
  10. package/dist/chat/delegation-card.js +3 -2
  11. package/dist/chat/message-list.js +4 -2
  12. package/dist/chat/message.js +17 -7
  13. package/dist/chrome/_edge-scroller.js +2 -1
  14. package/dist/chrome/_status-bar.js +9 -3
  15. package/dist/chrome/_tabs-scroll.d.ts +17 -1
  16. package/dist/chrome/_tabs-scroll.js +20 -3
  17. package/dist/chrome/app-bar.js +10 -3
  18. package/dist/chrome/app-shell.js +2 -1
  19. package/dist/chrome/band.d.ts +18 -12
  20. package/dist/chrome/band.js +19 -31
  21. package/dist/chrome/eyebrow.d.ts +13 -5
  22. package/dist/chrome/eyebrow.js +18 -7
  23. package/dist/chrome/footer.d.ts +5 -0
  24. package/dist/chrome/footer.js +14 -3
  25. package/dist/chrome/navigation-menu.js +4 -2
  26. package/dist/chrome/page-shell.js +8 -5
  27. package/dist/chrome/panel.d.ts +5 -2
  28. package/dist/chrome/panel.js +9 -4
  29. package/dist/chrome/row.js +6 -3
  30. package/dist/chrome/scroll-area.js +2 -1
  31. package/dist/chrome/section-header.js +13 -4
  32. package/dist/chrome/segmented-control.js +12 -3
  33. package/dist/chrome/status-bar.js +2 -1
  34. package/dist/chrome/tabs.js +11 -3
  35. package/dist/chrome/toolbar.js +2 -1
  36. package/dist/chrome/tree.js +3 -2
  37. package/dist/color/_thumb.js +9 -3
  38. package/dist/color/color-area.js +1 -1
  39. package/dist/color/color-field.d.ts +2 -1
  40. package/dist/color/color-picker.d.ts +2 -1
  41. package/dist/color/color-swatch.js +1 -1
  42. package/dist/configurator/_overrides.js +13 -4
  43. package/dist/configurator/configurator.js +4 -1
  44. package/dist/configurator/export-dialog.js +5 -2
  45. package/dist/configurator/panel-sections.js +6 -2
  46. package/dist/configurator/token-editor.js +4 -1
  47. package/dist/date/calendar.js +12 -8
  48. package/dist/date/date-field.d.ts +2 -1
  49. package/dist/date/date-picker.d.ts +2 -1
  50. package/dist/date/date-range-picker.d.ts +2 -1
  51. package/dist/date/time-field.d.ts +2 -1
  52. package/dist/dmx/channel-matrix.js +3 -2
  53. package/dist/dmx/dmx-bar.js +1 -1
  54. package/dist/dmx/dmx-strip.js +1 -1
  55. package/dist/dmx/universe-grid.js +3 -2
  56. package/dist/elements/activity-graph.js +3 -3
  57. package/dist/elements/agent-card.js +3 -3
  58. package/dist/elements/approval-card.js +3 -3
  59. package/dist/elements/artifact-card.js +2 -2
  60. package/dist/elements/background-inbox.js +2 -2
  61. package/dist/elements/canvas-split.js +2 -2
  62. package/dist/elements/chart.js +1 -1
  63. package/dist/elements/chat-panel.js +2 -2
  64. package/dist/elements/checkpoint-history.js +2 -2
  65. package/dist/elements/clamp.js +2 -1
  66. package/dist/elements/code-diff.js +1 -1
  67. package/dist/elements/code-runner.js +1 -1
  68. package/dist/elements/command-palette.js +6 -5
  69. package/dist/elements/comparison-card.js +2 -2
  70. package/dist/elements/composer.js +9 -8
  71. package/dist/elements/computer-use.js +1 -1
  72. package/dist/elements/confidence-marker.js +2 -1
  73. package/dist/elements/connection-state.js +1 -1
  74. package/dist/elements/context-breakdown.js +1 -1
  75. package/dist/elements/context-usage.js +1 -1
  76. package/dist/elements/conversation-search.js +4 -3
  77. package/dist/elements/cost-meter.js +1 -1
  78. package/dist/elements/data-table.js +2 -2
  79. package/dist/elements/day-separator.js +1 -1
  80. package/dist/elements/diagram.js +1 -1
  81. package/dist/elements/document-reference.js +3 -3
  82. package/dist/elements/draft-restore.js +1 -1
  83. package/dist/elements/edit-message.js +4 -3
  84. package/dist/elements/elements.css +26 -5
  85. package/dist/elements/elicitation-form.js +3 -3
  86. package/dist/elements/empty-state.js +2 -1
  87. package/dist/elements/error-state.js +1 -1
  88. package/dist/elements/feedback-dialog.js +4 -3
  89. package/dist/elements/file-tree.js +2 -2
  90. package/dist/elements/flow-graph.js +2 -2
  91. package/dist/elements/guardrail-notice.js +3 -3
  92. package/dist/elements/image-generation.js +1 -1
  93. package/dist/elements/inline-citation.js +3 -3
  94. package/dist/elements/job-progress.js +3 -3
  95. package/dist/elements/launcher-bubble.js +2 -2
  96. package/dist/elements/loading-state.js +1 -1
  97. package/dist/elements/map-answer.js +3 -2
  98. package/dist/elements/markdown.js +5 -4
  99. package/dist/elements/math-block.js +1 -1
  100. package/dist/elements/mcp-server-panel.js +3 -3
  101. package/dist/elements/message-attachment.js +4 -4
  102. package/dist/elements/message-pair.js +1 -1
  103. package/dist/elements/message-queue.js +2 -2
  104. package/dist/elements/mobile-composer.js +4 -3
  105. package/dist/elements/model-picker.js +3 -3
  106. package/dist/elements/onboarding.js +2 -2
  107. package/dist/elements/permission-grant.js +2 -2
  108. package/dist/elements/permission-scopes.js +5 -4
  109. package/dist/elements/prompt-library.js +7 -6
  110. package/dist/elements/queue-dock.js +4 -3
  111. package/dist/elements/quota-banner.js +1 -1
  112. package/dist/elements/quote-reply.js +1 -1
  113. package/dist/elements/read-aloud.js +2 -2
  114. package/dist/elements/reasoning-panel.js +2 -1
  115. package/dist/elements/recommendation-card.d.ts +1 -1
  116. package/dist/elements/recommendation-card.js +2 -2
  117. package/dist/elements/regenerate-menu.js +2 -2
  118. package/dist/elements/research-report.js +1 -1
  119. package/dist/elements/retrieval-chunks.js +1 -1
  120. package/dist/elements/revert-dock.js +5 -4
  121. package/dist/elements/reviewable-diff.js +1 -1
  122. package/dist/elements/schedule-card.js +3 -3
  123. package/dist/elements/score-breakdown.js +1 -1
  124. package/dist/elements/scroll-anchor.js +2 -2
  125. package/dist/elements/settings-panel.js +3 -2
  126. package/dist/elements/shared-conversation.js +2 -2
  127. package/dist/elements/sources.js +4 -3
  128. package/dist/elements/speaker-identity.js +1 -1
  129. package/dist/elements/spec-sheet.js +1 -1
  130. package/dist/elements/streaming-text.js +1 -1
  131. package/dist/elements/subagent-list.js +2 -2
  132. package/dist/elements/suggestions.js +1 -1
  133. package/dist/elements/surfaces.d.ts +1 -1
  134. package/dist/elements/surfaces.js +2 -1
  135. package/dist/elements/tail-status.js +1 -1
  136. package/dist/elements/terminal-block.js +1 -1
  137. package/dist/elements/thread-list.js +1 -1
  138. package/dist/elements/thread-search.js +5 -4
  139. package/dist/elements/timeline.js +1 -1
  140. package/dist/elements/todo-list.js +2 -2
  141. package/dist/elements/tool-call.js +4 -3
  142. package/dist/elements/tool-error.js +2 -2
  143. package/dist/elements/tool-group.js +1 -1
  144. package/dist/elements/tool-timeline.js +4 -3
  145. package/dist/elements/trace-waterfall.js +1 -1
  146. package/dist/elements/verdict-row.js +2 -2
  147. package/dist/elements/voice-conversation.js +3 -2
  148. package/dist/elements/web-preview.js +1 -1
  149. package/dist/elements/web-search.js +2 -2
  150. package/dist/elements/work-collapse.js +2 -1
  151. package/dist/flow/node-card.js +3 -2
  152. package/dist/flow/use-flow-theme.js +2 -1
  153. package/dist/forms/_chassis-size.d.ts +22 -0
  154. package/dist/forms/_chassis.d.ts +28 -15
  155. package/dist/forms/_chassis.js +34 -8
  156. package/dist/forms/_listbox.js +8 -5
  157. package/dist/forms/autocomplete.d.ts +2 -1
  158. package/dist/forms/checkbox.js +8 -2
  159. package/dist/forms/combobox.d.ts +2 -1
  160. package/dist/forms/env-var-input.d.ts +2 -1
  161. package/dist/forms/env-var-input.js +3 -2
  162. package/dist/forms/field.d.ts +2 -1
  163. package/dist/forms/field.js +15 -4
  164. package/dist/forms/file-upload.js +3 -2
  165. package/dist/forms/index.d.ts +2 -1
  166. package/dist/forms/input-group.d.ts +2 -1
  167. package/dist/forms/input.d.ts +2 -1
  168. package/dist/forms/multi-select.d.ts +2 -1
  169. package/dist/forms/number-field.js +2 -1
  170. package/dist/forms/otp-field.d.ts +2 -1
  171. package/dist/forms/password-input.d.ts +2 -1
  172. package/dist/forms/password-input.js +4 -2
  173. package/dist/forms/radio-group.js +6 -2
  174. package/dist/forms/rating.js +2 -1
  175. package/dist/forms/scrub-input.d.ts +2 -1
  176. package/dist/forms/scrub-input.js +2 -1
  177. package/dist/forms/search-input.d.ts +2 -1
  178. package/dist/forms/search-input.js +2 -1
  179. package/dist/forms/select.d.ts +2 -1
  180. package/dist/forms/select.js +6 -2
  181. package/dist/forms/slider.js +6 -2
  182. package/dist/forms/switch.js +6 -2
  183. package/dist/forms/tags-input.d.ts +2 -1
  184. package/dist/forms/textarea.js +2 -1
  185. package/dist/forms/toggle-group.d.ts +1 -1
  186. package/dist/forms/toggle.d.ts +1 -1
  187. package/dist/forms/toggle.js +3 -1
  188. package/dist/index.d.ts +4 -3
  189. package/dist/index.js +2 -2
  190. package/dist/instruments/_data-row.js +2 -1
  191. package/dist/instruments/app-window-frame.js +1 -1
  192. package/dist/instruments/code-block.js +8 -2
  193. package/dist/instruments/group-bar.js +1 -1
  194. package/dist/instruments/ledger.js +6 -2
  195. package/dist/instruments/log-viewer.js +5 -3
  196. package/dist/instruments/progress.js +5 -2
  197. package/dist/instruments/seam-grid.js +5 -3
  198. package/dist/instruments/stat.js +10 -3
  199. package/dist/instruments/table.js +28 -10
  200. package/dist/instruments/terminal-frame.js +4 -2
  201. package/dist/instruments/usage-chart.js +1 -1
  202. package/dist/layout/_collapse.js +6 -1
  203. package/dist/layout/bento.js +7 -4
  204. package/dist/layout/breadcrumb.js +7 -3
  205. package/dist/layout/card.js +14 -6
  206. package/dist/layout/carousel.js +3 -2
  207. package/dist/layout/collapsible.js +5 -1
  208. package/dist/layout/container.js +2 -1
  209. package/dist/layout/description-list.js +4 -1
  210. package/dist/layout/frames.js +11 -5
  211. package/dist/layout/item.js +3 -2
  212. package/dist/layout/link.d.ts +16 -0
  213. package/dist/layout/link.js +22 -3
  214. package/dist/layout/pagination.js +2 -1
  215. package/dist/layout/preview.d.ts +32 -12
  216. package/dist/layout/preview.js +149 -40
  217. package/dist/layout/resizable.js +2 -1
  218. package/dist/layout/sidebar.js +11 -3
  219. package/dist/layout/stepper.js +6 -2
  220. package/dist/lib/cn.js +29 -2
  221. package/dist/midi/musical-time-input.d.ts +2 -1
  222. package/dist/midi/piano-keyboard.js +3 -2
  223. package/dist/midi/spectrum-visualizer.js +1 -1
  224. package/dist/midi/threshold-rail.js +2 -1
  225. package/dist/midi/timeline-ruler.js +1 -1
  226. package/dist/overlays/_surface.d.ts +72 -12
  227. package/dist/overlays/_surface.js +86 -12
  228. package/dist/overlays/command-palette.js +9 -5
  229. package/dist/overlays/dialog.d.ts +5 -0
  230. package/dist/overlays/dialog.js +6 -1
  231. package/dist/overlays/info-tip.js +2 -1
  232. package/dist/overlays/menubar.js +3 -1
  233. package/dist/overlays/popover.js +2 -1
  234. package/dist/overlays/toast.js +6 -2
  235. package/dist/overlays/tooltip.js +4 -1
  236. package/dist/primitives/button.d.ts +15 -0
  237. package/dist/primitives/button.js +40 -10
  238. package/dist/primitives/chip.d.ts +20 -2
  239. package/dist/primitives/chip.js +39 -17
  240. package/dist/primitives/kbd.d.ts +6 -0
  241. package/dist/primitives/kbd.js +10 -1
  242. package/dist/primitives/skeleton.js +1 -1
  243. package/dist/system/_focus-ring-field.js +29 -0
  244. package/dist/system/_focus-ring.js +125 -0
  245. package/dist/system/_paint-elevation.js +9 -0
  246. package/dist/system/_paint-glass.js +46 -0
  247. package/dist/system/_paint-glow.js +51 -0
  248. package/dist/system/_paint-ground-pattern.js +30 -0
  249. package/dist/system/_paint-rest-shade.js +32 -0
  250. package/dist/system/_paint-rim.js +59 -0
  251. package/dist/system/_paint-stroke-sunken.js +19 -0
  252. package/dist/system/_paint-stroke-surface-1.js +19 -0
  253. package/dist/system/_paint-stroke-surface-2.js +40 -0
  254. package/dist/system/_paint-texture.js +56 -0
  255. package/dist/system/_style-app-bar.js +65 -0
  256. package/dist/system/_style-band.js +57 -0
  257. package/dist/system/_style-body-leading.js +21 -0
  258. package/dist/system/_style-body-size.js +30 -0
  259. package/dist/system/_style-body-weight.js +24 -0
  260. package/dist/system/_style-body.js +27 -0
  261. package/dist/system/_style-caption.js +19 -0
  262. package/dist/system/_style-card-pad.js +43 -0
  263. package/dist/system/_style-check.js +33 -0
  264. package/dist/system/_style-chip.js +103 -0
  265. package/dist/system/_style-code.js +13 -0
  266. package/dist/system/_style-collapse.js +14 -0
  267. package/dist/system/_style-control-face.js +29 -0
  268. package/dist/system/_style-control-label.js +22 -0
  269. package/dist/system/_style-control-step.js +22 -0
  270. package/dist/system/_style-control.js +76 -0
  271. package/dist/system/_style-data-face.js +28 -0
  272. package/dist/system/_style-description.js +23 -0
  273. package/dist/system/_style-eyebrow.js +43 -0
  274. package/dist/system/_style-footer-rule.js +47 -0
  275. package/dist/system/_style-gutter.js +17 -0
  276. package/dist/system/_style-help-ink.js +14 -0
  277. package/dist/system/_style-help.js +29 -0
  278. package/dist/system/_style-input-face.js +34 -0
  279. package/dist/system/_style-kbd.js +46 -0
  280. package/dist/system/_style-label-case.js +36 -0
  281. package/dist/system/_style-label-face.js +32 -0
  282. package/dist/system/_style-label-ink.js +29 -0
  283. package/dist/system/_style-label-leading.js +14 -0
  284. package/dist/system/_style-label-size.js +36 -0
  285. package/dist/system/_style-label-tracking.js +45 -0
  286. package/dist/system/_style-label-weight.js +40 -0
  287. package/dist/system/_style-lede.js +49 -0
  288. package/dist/system/_style-link.js +46 -0
  289. package/dist/system/_style-menu.js +30 -0
  290. package/dist/system/_style-nav-item.js +41 -0
  291. package/dist/system/_style-nav-voice.js +43 -0
  292. package/dist/system/_style-option.js +42 -0
  293. package/dist/system/_style-overlay-title.js +35 -0
  294. package/dist/system/_style-page-title.js +48 -0
  295. package/dist/system/_style-popover-pad.js +13 -0
  296. package/dist/system/_style-quiet-ink.js +13 -0
  297. package/dist/system/_style-row-pad.js +13 -0
  298. package/dist/system/_style-seam.js +43 -0
  299. package/dist/system/_style-section-rule.js +26 -0
  300. package/dist/system/_style-segment.js +30 -0
  301. package/dist/system/_style-segmented-control.js +86 -0
  302. package/dist/system/_style-selected.js +36 -0
  303. package/dist/system/_style-stage-marks.js +26 -0
  304. package/dist/system/_style-tab.js +71 -0
  305. package/dist/system/_style-textarea.js +21 -0
  306. package/dist/system/_style-title.js +37 -0
  307. package/dist/system/_style-tooltip.js +17 -0
  308. package/dist/system/density.d.ts +15 -5
  309. package/dist/system/density.js +188 -25
  310. package/dist/system/index.d.ts +2 -2
  311. package/dist/system/index.js +2 -2
  312. package/dist/system/overrides.d.ts +1 -0
  313. package/dist/system/overrides.js +151 -3
  314. package/dist/system/portal.d.ts +3 -2
  315. package/dist/system/portal.js +22 -10
  316. package/dist/system/prepaint.d.ts +21 -5
  317. package/dist/system/prepaint.js +3 -1
  318. package/dist/system/published.d.ts +1 -0
  319. package/dist/system/published.js +131 -0
  320. package/dist/system/theme-provider.d.ts +168 -60
  321. package/dist/system/theme-provider.js +375 -79
  322. package/dist/system/theme-registry.d.ts +2 -1
  323. package/dist/system/theme-registry.js +27 -10
  324. package/dist/system/use-density.js +4 -3
  325. package/dist/system/use-theme.d.ts +5 -2
  326. package/dist/system/use-theme.js +7 -4
  327. package/dist/system/vocabulary.js +2 -2
  328. package/dist/theming/create-theme.js +12 -6
  329. package/dist/theming/serialize.d.ts +34 -2
  330. package/dist/theming/serialize.js +86 -4
  331. package/manifest/components/accordion.json +7 -1
  332. package/manifest/components/agent-pile.json +3 -0
  333. package/manifest/components/alert-dialog.json +38 -1
  334. package/manifest/components/app-bar.json +23 -2
  335. package/manifest/components/app-shell.json +5 -0
  336. package/manifest/components/ask-box.json +3 -1
  337. package/manifest/components/autocomplete.json +49 -1
  338. package/manifest/components/band.json +14 -3
  339. package/manifest/components/bento.json +12 -1
  340. package/manifest/components/breadcrumb.json +8 -1
  341. package/manifest/components/button.json +31 -3
  342. package/manifest/components/calendar.json +7 -0
  343. package/manifest/components/card.json +28 -1
  344. package/manifest/components/carousel.json +4 -1
  345. package/manifest/components/channel-matrix.json +40 -1
  346. package/manifest/components/chart-tooltip-content.json +38 -1
  347. package/manifest/components/chat-empty-state.json +3 -1
  348. package/manifest/components/checkbox-group.json +14 -0
  349. package/manifest/components/checkbox.json +14 -0
  350. package/manifest/components/chip.json +16 -1
  351. package/manifest/components/clamp.json +3 -1
  352. package/manifest/components/code-block.json +10 -1
  353. package/manifest/components/collapsible.json +13 -2
  354. package/manifest/components/color-area.json +4 -2
  355. package/manifest/components/color-field.json +14 -0
  356. package/manifest/components/color-picker.json +14 -0
  357. package/manifest/components/color-slider.json +3 -1
  358. package/manifest/components/colors-section.json +9 -1
  359. package/manifest/components/combobox.json +49 -1
  360. package/manifest/components/command-palette.json +37 -1
  361. package/manifest/components/composer-actions.json +3 -0
  362. package/manifest/components/composer-attach-button.json +3 -0
  363. package/manifest/components/composer-attachment-chip.json +3 -0
  364. package/manifest/components/composer-attachments.json +3 -0
  365. package/manifest/components/composer-bar.json +3 -0
  366. package/manifest/components/composer-command-item.json +3 -0
  367. package/manifest/components/composer-context.json +3 -0
  368. package/manifest/components/composer-input.json +3 -0
  369. package/manifest/components/composer-menu-item.json +3 -0
  370. package/manifest/components/composer-menu.json +3 -0
  371. package/manifest/components/composer-model-item.json +3 -0
  372. package/manifest/components/composer-model-trigger.json +3 -0
  373. package/manifest/components/composer-person-item.json +3 -0
  374. package/manifest/components/composer-send.json +3 -0
  375. package/manifest/components/composer-toolbar.json +3 -0
  376. package/manifest/components/composer-voice-button.json +3 -0
  377. package/manifest/components/composer-voice.json +3 -0
  378. package/manifest/components/composer.json +14 -0
  379. package/manifest/components/confidence-marker.json +3 -1
  380. package/manifest/components/container.json +2 -1
  381. package/manifest/components/context-menu.json +38 -1
  382. package/manifest/components/conversation-search.json +3 -1
  383. package/manifest/components/cue-mark.json +2 -2
  384. package/manifest/components/cue-portal-frame.json +1 -1
  385. package/manifest/components/data-row.json +3 -1
  386. package/manifest/components/data-tree.json +3 -1
  387. package/manifest/components/date-field.json +14 -0
  388. package/manifest/components/date-picker.json +14 -0
  389. package/manifest/components/date-range-picker.json +14 -0
  390. package/manifest/components/delegation-card.json +3 -1
  391. package/manifest/components/density.json +21 -7
  392. package/manifest/components/description-list.json +6 -1
  393. package/manifest/components/dialog.json +39 -1
  394. package/manifest/components/disclosure.json +13 -2
  395. package/manifest/components/dmx-bar.json +37 -1
  396. package/manifest/components/dmx-strip.json +37 -1
  397. package/manifest/components/drawer.json +38 -1
  398. package/manifest/components/dropdown-menu.json +38 -1
  399. package/manifest/components/edit-message.json +3 -1
  400. package/manifest/components/elements-command-palette.json +3 -1
  401. package/manifest/components/elements-composer.json +3 -0
  402. package/manifest/components/empty-state-composer.json +3 -1
  403. package/manifest/components/empty-state-greeting.json +3 -1
  404. package/manifest/components/empty-state-suggestion.json +3 -1
  405. package/manifest/components/empty-state-suggestions.json +3 -1
  406. package/manifest/components/env-var-input.json +14 -1
  407. package/manifest/components/export-dialog.json +6 -1
  408. package/manifest/components/eyebrow.json +13 -2
  409. package/manifest/components/feedback-dialog.json +3 -0
  410. package/manifest/components/field-description.json +14 -0
  411. package/manifest/components/field-error.json +14 -0
  412. package/manifest/components/field-label.json +15 -1
  413. package/manifest/components/field.json +14 -0
  414. package/manifest/components/file-upload.json +3 -0
  415. package/manifest/components/footer.json +14 -1
  416. package/manifest/components/frames.json +14 -1
  417. package/manifest/components/hover-card.json +38 -1
  418. package/manifest/components/info-tip.json +3 -0
  419. package/manifest/components/input-group.json +14 -0
  420. package/manifest/components/input.json +14 -0
  421. package/manifest/components/item.json +3 -1
  422. package/manifest/components/kbd.json +10 -1
  423. package/manifest/components/ledger.json +9 -2
  424. package/manifest/components/link.json +10 -0
  425. package/manifest/components/log-viewer.json +10 -0
  426. package/manifest/components/map-answer.json +3 -1
  427. package/manifest/components/markdown-text.json +3 -0
  428. package/manifest/components/menubar.json +41 -2
  429. package/manifest/components/message-list.json +10 -0
  430. package/manifest/components/message.json +6 -1
  431. package/manifest/components/mobile-composer.json +3 -1
  432. package/manifest/components/multi-select.json +49 -1
  433. package/manifest/components/musical-time-input.json +14 -0
  434. package/manifest/components/navigation-menu.json +41 -1
  435. package/manifest/components/node-card.json +3 -0
  436. package/manifest/components/number-field.json +14 -1
  437. package/manifest/components/otp-field.json +13 -0
  438. package/manifest/components/page-shell.json +14 -0
  439. package/manifest/components/pagination.json +3 -0
  440. package/manifest/components/panel-header.json +12 -0
  441. package/manifest/components/panel.json +13 -1
  442. package/manifest/components/password-input.json +14 -1
  443. package/manifest/components/permission-scopes.json +3 -1
  444. package/manifest/components/piano-keyboard.json +3 -0
  445. package/manifest/components/popover.json +39 -1
  446. package/manifest/components/preset-section.json +9 -1
  447. package/manifest/components/preview.json +30 -10
  448. package/manifest/components/progress.json +6 -1
  449. package/manifest/components/prompt-library.json +3 -1
  450. package/manifest/components/queue-dock.json +3 -1
  451. package/manifest/components/radio-group.json +8 -0
  452. package/manifest/components/radio.json +8 -0
  453. package/manifest/components/rating.json +4 -1
  454. package/manifest/components/reasoning-panel.json +3 -1
  455. package/manifest/components/recommendation-card.json +1 -1
  456. package/manifest/components/resizable.json +4 -1
  457. package/manifest/components/revert-dock.json +3 -1
  458. package/manifest/components/row.json +5 -1
  459. package/manifest/components/scroll-area.json +4 -2
  460. package/manifest/components/scrollable-tabs-list.json +19 -0
  461. package/manifest/components/scrub-input.json +14 -1
  462. package/manifest/components/seam-cell.json +1 -0
  463. package/manifest/components/seam-grid.json +1 -0
  464. package/manifest/components/seam-list.json +5 -1
  465. package/manifest/components/search-input.json +14 -1
  466. package/manifest/components/section-header.json +15 -2
  467. package/manifest/components/segmented-control.json +17 -0
  468. package/manifest/components/select.json +28 -0
  469. package/manifest/components/settings-panel.json +3 -0
  470. package/manifest/components/shape-section.json +9 -1
  471. package/manifest/components/sheet.json +38 -1
  472. package/manifest/components/shimmer-label.json +3 -0
  473. package/manifest/components/sidebar.json +19 -2
  474. package/manifest/components/slider.json +8 -0
  475. package/manifest/components/sources.json +3 -1
  476. package/manifest/components/stat.json +9 -0
  477. package/manifest/components/status-bar.json +4 -0
  478. package/manifest/components/stepper.json +8 -0
  479. package/manifest/components/swap-label.json +3 -0
  480. package/manifest/components/switch.json +8 -0
  481. package/manifest/components/table-scroll-region.json +20 -2
  482. package/manifest/components/table.json +20 -2
  483. package/manifest/components/tabs.json +20 -1
  484. package/manifest/components/tags-input.json +49 -1
  485. package/manifest/components/terminal-frame.json +3 -0
  486. package/manifest/components/textarea.json +16 -0
  487. package/manifest/components/theme-configurator.json +38 -1
  488. package/manifest/components/theme-provider.json +37 -19
  489. package/manifest/components/thread-search.json +3 -1
  490. package/manifest/components/threshold-rail.json +3 -0
  491. package/manifest/components/time-field.json +14 -0
  492. package/manifest/components/toast.json +39 -0
  493. package/manifest/components/toggle-group.json +1 -19
  494. package/manifest/components/toggle.json +3 -5
  495. package/manifest/components/token-editor.json +6 -1
  496. package/manifest/components/tool-call-card.json +9 -2
  497. package/manifest/components/tool-call.json +3 -1
  498. package/manifest/components/tool-timeline.json +3 -1
  499. package/manifest/components/toolbar.json +4 -1
  500. package/manifest/components/tooltip.json +40 -1
  501. package/manifest/components/tree-visibility-toggle.json +3 -0
  502. package/manifest/components/tree.json +3 -0
  503. package/manifest/components/universe-grid.json +3 -0
  504. package/manifest/components/voice-conversation.json +3 -0
  505. package/manifest/components/work-collapse.json +3 -1
  506. package/manifest/manifest.json +205 -185
  507. package/manifest/tokens.json +260 -4
  508. package/package.json +6 -6
package/README.md CHANGED
@@ -53,6 +53,32 @@ To stop the defaults flashing on first paint, add `prepaintScript()` beside the
53
53
  both the same array — [§4 of `CONSUMING.md`](https://github.com/cueplusplus/cue-ui/blob/main/docs/CONSUMING.md#4-the-provider)
54
54
  is the whole layout.
55
55
 
56
+ Beside `theme` and `mode`, the provider takes four axes, and each one changes a single thing:
57
+ `density` the geometry, `font` the typeface pairing, `styleSet` the page composition, and `paint`
58
+ the finish — rims, strokes, elevation, glow, glass, texture and edge fades. `paint` is off unless
59
+ you ask for it: the provider stamps no `data-paint`, so a page looks exactly as it did until you
60
+ pass one of `none`, `halo`, `hatch`, `lift`, `frost`, `bevel` or `grain`. Any subtree can take its
61
+ own with `<Density paint="frost">` — the same island that re-scopes `density` and `styleSet`. The
62
+ font pairing is the one axis a subtree cannot change: it lives on `<html>`, so it is the root's.
63
+
64
+ ```tsx
65
+ import cue from "@cueplusplus/theme-cue";
66
+ import { ThemeProvider } from "@cueplusplus/ui/system";
67
+
68
+ export function App({ children }: { children: React.ReactNode }) {
69
+ return (
70
+ <ThemeProvider themes={[cue]} theme="cue" density="compact" mode="system" paint="halo">
71
+ {children}
72
+ </ThemeProvider>
73
+ );
74
+ }
75
+ ```
76
+
77
+ The ten packs, where each was measured from and what each refuses:
78
+ <https://ui.cueplusplus.com/docs/paint>. Serving a nonce-based Content-Security-Policy? Read
79
+ [§4.5 of `CONSUMING.md`](https://github.com/cueplusplus/cue-ui/blob/main/docs/CONSUMING.md#45-content-security-policy-the-nonce-prop-and-what-it-does-not-reach)
80
+ before you ship it — `paint="grain"` alone needs `img-src data:`.
81
+
56
82
  ## What it ships
57
83
 
58
84
  Common components come from the root entry. Groups that need an optional peer have a subpath of
@@ -2,8 +2,12 @@
2
2
  import { cn } from "../lib/cn.js";
3
3
  import { AGENT_ROOT_COLOR, agentColor } from "../chat/agent-color.js";
4
4
  import { CheckGlyph } from "../chat/_glyphs.js";
5
+ import { FOCUS_RING_OFFSET_2 } from "../system/_focus-ring.js";
6
+ import { LABEL_FACE } from "../system/_style-label-face.js";
5
7
  import { Chip } from "../primitives/chip.js";
6
8
  import { Spinner } from "../primitives/spinner.js";
9
+ import { LABEL_CASE } from "../system/_style-label-case.js";
10
+ import { LABEL_TRACKING } from "../system/_style-label-tracking.js";
7
11
  import * as React from "react";
8
12
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
9
13
  //#region src/agent-runtime/tool-call-card.tsx
@@ -23,9 +27,9 @@ const DANGER_TONES = {
23
27
  * card with nothing to disclose draws instead — the two must sit at exactly the
24
28
  * same height and ink, or a list of calls ripples as some of them gain detail.
25
29
  */
26
- const HEADER = "flex min-w-0 items-center gap-(--cue-space-2) border-0 bg-transparent p-0 text-start font-mono text-(length:--cue-text-ui) text-fg-muted outline-none focus-visible:outline-2 focus-visible:outline-solid focus-visible:outline-offset-2 focus-visible:outline-accent";
30
+ const HEADER = `flex min-w-0 items-center gap-(--cue-space-2) border-0 bg-transparent p-0 text-start font-mono text-(length:--cue-text-ui) text-fg-muted outline-none ${FOCUS_RING_OFFSET_2}`;
27
31
  /** The label over a block in the body, in the same eyebrow as a message header. */
28
- const EYEBROW = "font-mono text-(length:--cue-text-micro) tracking-(--cue-tracking-caps) uppercase text-fg-subtle";
32
+ const EYEBROW = `${LABEL_FACE} text-(length:--cue-text-micro) ${LABEL_TRACKING} ${LABEL_CASE} text-fg-subtle`;
29
33
  /**
30
34
  * An LLM's own tool call, shown while it runs and after.
31
35
  *
@@ -96,7 +100,7 @@ const ToolCallCard = React.forwardRef(function ToolCallCard({ className, tool, a
96
100
  "data-status": status,
97
101
  "data-state": hasDetail ? open ? "open" : "closed" : void 0,
98
102
  "data-danger": danger,
99
- className: cn("flex min-w-0 flex-col gap-(--cue-space-2) rounded-(--radius-control) border border-border px-(--cue-space-3) py-(--cue-space-2)", className),
103
+ className: cn("flex min-w-0 flex-col gap-(--cue-space-2) rounded-control border border-border px-(--cue-space-3) py-(--cue-space-2)", className),
100
104
  style: {
101
105
  "--agent-color": color,
102
106
  ...style
@@ -22,7 +22,7 @@ type BrandSize = "sm" | "md" | "lg";
22
22
  *
23
23
  * Not a light/dark pair. The source artwork ships two files that hard-code
24
24
  * `white`, `black` and `#1E1E1E`; this library ships one component that reads
25
- * the token layer, so a single element is correct in all ten presets and both
25
+ * the token layer, so a single element is correct in every preset and both
26
26
  * modes without anybody choosing a file.
27
27
  */
28
28
  type BrandTone = "inherit" | "fg" | "accent";
@@ -8,7 +8,7 @@ interface CueMarkProps extends BrandAssetProps {}
8
8
  * Square at every size, drawn from the artwork's own path data, and painted
9
9
  * entirely from tokens — the disc takes the tone's ink and the two "+" glyphs
10
10
  * take the ground, which is exactly the relationship the two shipped SVGs
11
- * encode by hand. One element is therefore correct in all ten presets and
11
+ * encode by hand. One element is therefore correct in every preset and
12
12
  * both modes, and there is no light/dark variant to pick.
13
13
  *
14
14
  * The two glyphs are {@link Plussie}'s eyes; both components read one geometry
@@ -10,7 +10,7 @@ import { jsx, jsxs } from "react/jsx-runtime";
10
10
  * Square at every size, drawn from the artwork's own path data, and painted
11
11
  * entirely from tokens — the disc takes the tone's ink and the two "+" glyphs
12
12
  * take the ground, which is exactly the relationship the two shipped SVGs
13
- * encode by hand. One element is therefore correct in all ten presets and
13
+ * encode by hand. One element is therefore correct in every preset and
14
14
  * both modes, and there is no light/dark variant to pick.
15
15
  *
16
16
  * The two glyphs are {@link Plussie}'s eyes; both components read one geometry
@@ -600,7 +600,7 @@ const ChartRamp = React.forwardRef(function ChartRamp({ className, colors, label
600
600
  role: "img",
601
601
  "aria-label": label,
602
602
  "data-slot": "chart-ramp",
603
- className: cn("flex w-full overflow-hidden rounded-(--radius-control)", className),
603
+ className: cn("flex w-full overflow-hidden rounded-control", className),
604
604
  style: { height: toRem(height) },
605
605
  ...elementProps,
606
606
  children: colors.map((color, index) => /* @__PURE__ */ jsx("span", {
@@ -2,6 +2,7 @@
2
2
  import { cn } from "../lib/cn.js";
3
3
  import { agentColor } from "./agent-color.js";
4
4
  import { CrownGlyph } from "./_glyphs.js";
5
+ import { FOCUS_RING_OFFSET_2 } from "../system/_focus-ring.js";
5
6
  import * as React from "react";
6
7
  import { jsx, jsxs } from "react/jsx-runtime";
7
8
  //#region src/chat/agent-pile.tsx
@@ -62,7 +63,7 @@ const AgentPile = React.forwardRef(function AgentPile({ className, agents, root,
62
63
  agent.working === true ? "working" : null,
63
64
  agent.asking === true ? "asking a question" : null
64
65
  ].filter(Boolean).join(" · ");
65
- const avatarClasses = cn("relative flex shrink-0 items-center justify-center rounded-full border border-(--agent-color) bg-surface-2 font-mono leading-none text-(--agent-color) uppercase outline-none", AVATAR_SIZES[size], selected === agent.slug ? "ring-2 ring-(--agent-color)" : null, onSelect === void 0 ? null : "cursor-pointer transition-colors hover:bg-surface-3 focus-visible:outline-2 focus-visible:outline-solid focus-visible:outline-offset-2 focus-visible:outline-accent");
66
+ const avatarClasses = cn("relative flex shrink-0 items-center justify-center rounded-full border border-(--agent-color) bg-surface-2 font-mono leading-none text-(--agent-color) uppercase outline-none", AVATAR_SIZES[size], selected === agent.slug ? "ring-2 ring-(--agent-color)" : null, onSelect === void 0 ? null : `cursor-pointer transition-colors hover:bg-surface-3 ${FOCUS_RING_OFFSET_2}`);
66
67
  const initial = name.slice(0, 1).toUpperCase();
67
68
  return /* @__PURE__ */ jsxs("span", {
68
69
  "data-slot": "agent-pile-item",
@@ -2,6 +2,7 @@
2
2
  import { cn } from "../lib/cn.js";
3
3
  import { AGENT_ROOT_COLOR, agentColor } from "./agent-color.js";
4
4
  import { CheckGlyph } from "./_glyphs.js";
5
+ import { FOCUS_RING_OFFSET_2 } from "../system/_focus-ring.js";
5
6
  import { Checkbox } from "../forms/checkbox.js";
6
7
  import { Input } from "../forms/input.js";
7
8
  import { NumberField } from "../forms/number-field.js";
@@ -114,14 +115,14 @@ const AskBox = React.forwardRef(function AskBox({ className, question, kind = "t
114
115
  "data-slot": "ask-box",
115
116
  "data-answered": "true",
116
117
  "data-kind": kind,
117
- className: cn("flex min-w-0 flex-col rounded-(--radius-surface) border border-border bg-surface-1 px-(--cue-space-4) py-(--cue-space-3)", className),
118
+ className: cn("flex min-w-0 flex-col rounded-surface border border-border bg-surface-1 px-(--cue-space-4) py-(--cue-space-3)", className),
118
119
  style: boxStyle,
119
120
  ...elementProps,
120
121
  children: [/* @__PURE__ */ jsxs("button", {
121
122
  type: "button",
122
123
  "data-slot": "ask-box-summary",
123
124
  "aria-expanded": open,
124
- className: "relative flex min-w-0 cursor-pointer items-center gap-(--cue-space-2) border-0 bg-transparent p-0 text-start font-mono text-(length:--cue-text-ui) outline-none focus-visible:outline-2 focus-visible:outline-solid focus-visible:outline-offset-2 focus-visible:outline-accent",
125
+ className: `relative flex min-w-0 cursor-pointer items-center gap-(--cue-space-2) border-0 bg-transparent p-0 text-start font-mono text-(length:--cue-text-ui) outline-none ${FOCUS_RING_OFFSET_2}`,
125
126
  onClick: () => setOpen((current) => !current),
126
127
  children: [
127
128
  /* @__PURE__ */ jsx("span", {
@@ -304,7 +305,7 @@ const AskBox = React.forwardRef(function AskBox({ className, question, kind = "t
304
305
  "data-slot": "ask-box",
305
306
  "data-answered": "false",
306
307
  "data-kind": kind,
307
- className: cn("flex min-w-0 flex-col gap-(--cue-space-3) rounded-(--radius-surface) border border-(--agent-color) bg-surface-1 px-(--cue-space-4) py-(--cue-space-3)", className),
308
+ className: cn("flex min-w-0 flex-col gap-(--cue-space-3) rounded-surface border border-(--agent-color) bg-surface-1 px-(--cue-space-4) py-(--cue-space-3)", className),
308
309
  style: boxStyle,
309
310
  ...elementProps,
310
311
  children: [
@@ -2,6 +2,7 @@
2
2
  import { cn } from "../lib/cn.js";
3
3
  import { agentColor } from "./agent-color.js";
4
4
  import { CheckGlyph } from "./_glyphs.js";
5
+ import { FOCUS_RING_OFFSET_2 } from "../system/_focus-ring.js";
5
6
  import { Spinner } from "../primitives/spinner.js";
6
7
  import * as React from "react";
7
8
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
@@ -52,7 +53,7 @@ const DelegationCard = React.forwardRef(function DelegationCard({ className, age
52
53
  "data-direction": direction,
53
54
  "data-state": open ? "open" : "closed",
54
55
  "data-status": status,
55
- className: cn("flex min-w-0 flex-col gap-(--cue-space-2) rounded-(--radius-control) border border-border px-(--cue-space-3) py-(--cue-space-2)", className),
56
+ className: cn("flex min-w-0 flex-col gap-(--cue-space-2) rounded-control border border-border px-(--cue-space-3) py-(--cue-space-2)", className),
56
57
  style: {
57
58
  "--agent-color": color,
58
59
  ...style
@@ -64,7 +65,7 @@ const DelegationCard = React.forwardRef(function DelegationCard({ className, age
64
65
  "data-slot": "delegation-card-trigger",
65
66
  "aria-expanded": open,
66
67
  "aria-controls": open ? bodyId : void 0,
67
- className: "flex min-w-0 cursor-pointer items-center gap-(--cue-space-2) border-0 bg-transparent p-0 text-start font-mono text-(length:--cue-text-ui) text-fg-muted outline-none focus-visible:outline-2 focus-visible:outline-solid focus-visible:outline-offset-2 focus-visible:outline-accent",
68
+ className: `flex min-w-0 cursor-pointer items-center gap-(--cue-space-2) border-0 bg-transparent p-0 text-start font-mono text-(length:--cue-text-ui) text-fg-muted outline-none ${FOCUS_RING_OFFSET_2}`,
68
69
  onClick: toggle,
69
70
  children: [
70
71
  /* @__PURE__ */ jsx("span", {
@@ -1,7 +1,9 @@
1
1
  "use client";
2
2
  import { cn } from "../lib/cn.js";
3
3
  import { ChevronDownGlyph } from "./_glyphs.js";
4
+ import { FOCUS_RING, FOCUS_RING_INSET_2 } from "../system/_focus-ring.js";
4
5
  import { useIsomorphicLayoutEffect } from "../system/use-isomorphic-layout-effect.js";
6
+ import { ELEVATION_2 } from "../system/_paint-elevation.js";
5
7
  import * as React from "react";
6
8
  import { jsx, jsxs } from "react/jsx-runtime";
7
9
  //#region src/chat/message-list.tsx
@@ -116,7 +118,7 @@ const MessageList = React.forwardRef(function MessageList({ className, children,
116
118
  "aria-label": ariaLabel,
117
119
  tabIndex: 0,
118
120
  "data-slot": "message-list-scroller",
119
- className: "min-h-0 flex-1 overflow-y-auto outline-none focus-visible:outline-2 focus-visible:outline-solid focus-visible:-outline-offset-2 focus-visible:outline-accent",
121
+ className: `min-h-0 flex-1 overflow-y-auto outline-none ${FOCUS_RING_INSET_2}`,
120
122
  onScroll,
121
123
  children: count === 0 ? /* @__PURE__ */ jsx("div", {
122
124
  "data-slot": "message-list-empty",
@@ -131,7 +133,7 @@ const MessageList = React.forwardRef(function MessageList({ className, children,
131
133
  }), behind ? /* @__PURE__ */ jsxs("button", {
132
134
  type: "button",
133
135
  "data-slot": "message-list-jump",
134
- className: "absolute bottom-(--cue-space-4) left-1/2 flex -translate-x-1/2 cursor-pointer items-center gap-(--cue-space-2) rounded-(--radius-control) border border-border-overlay bg-surface-2 px-(--cue-space-4) py-(--cue-space-2) font-mono text-(length:--cue-text-label) text-fg shadow-[0_8px_24px_rgba(0,0,0,0.4)] outline-none hover:border-accent hover:text-accent focus-visible:outline-2 focus-visible:outline-solid focus-visible:outline-offset-1 focus-visible:outline-accent",
136
+ className: `absolute bottom-(--cue-space-4) left-1/2 flex -translate-x-1/2 cursor-pointer items-center gap-(--cue-space-2) rounded-control border border-border-overlay bg-surface-2 px-(--cue-space-4) py-(--cue-space-2) font-mono text-(length:--cue-text-label) text-fg ${ELEVATION_2} outline-none hover:border-accent hover:text-accent ${FOCUS_RING}`,
135
137
  onClick: jumpToLatest,
136
138
  children: [/* @__PURE__ */ jsx(ChevronDownGlyph, { className: "size-icon-sm" }), jumpLabel]
137
139
  }) : null]
@@ -1,5 +1,8 @@
1
1
  import { cn } from "../lib/cn.js";
2
2
  import { AGENT_ROOT_COLOR, agentColor } from "./agent-color.js";
3
+ import { LABEL_FACE } from "../system/_style-label-face.js";
4
+ import { LABEL_CASE } from "../system/_style-label-case.js";
5
+ import { LABEL_TRACKING } from "../system/_style-label-tracking.js";
3
6
  import * as React from "react";
4
7
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
5
8
  //#region src/chat/message.tsx
@@ -9,14 +12,21 @@ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
9
12
  *
10
13
  * The tight corner is the tail, and it points at whoever is speaking: bottom
11
14
  * right for the right-aligned user turn, bottom left for the agent's. Written
12
- * against the radius tokens rather than literal pixels, so the whole family
13
- * tightens with `--cue-radius-scale` at ultra-compact density instead of
14
- * staying a fixed 10px blob next to 2px controls.
15
+ * as the overlay rung with one corner overridden to the control rung, rather
16
+ * than a `[border-radius:…]` arbitrary value reading `var(--radius-*)`
17
+ * directly — a `--radius-*` reader bypasses the compiled bridge utilities
18
+ * `rounded-control`/`rounded-overlay` resolve to, so it neither shows up in
19
+ * the class-token scan that guards this bridge nor tightens with
20
+ * `--cue-radius-scale` through the same path every other radius in this
21
+ * system does. `rounded-br-control`/`rounded-bl-control` are ordinary
22
+ * per-corner bridge utilities (`packages/tokens/build.mjs`'s `SIDES` table
23
+ * covers every corner, not just the four edges), so the four-value shorthand
24
+ * upstream Tailwind has no plain form for is two ordinary utility classes.
15
25
  */
16
26
  const ROLE_RADII = {
17
- user: "[border-radius:var(--radius-overlay)_var(--radius-overlay)_var(--radius-control)_var(--radius-overlay)]",
18
- agent: "[border-radius:var(--radius-overlay)_var(--radius-overlay)_var(--radius-overlay)_var(--radius-control)]",
19
- system: "rounded-(--radius-control)"
27
+ user: "rounded-overlay rounded-br-control",
28
+ agent: "rounded-overlay rounded-bl-control",
29
+ system: "rounded-control"
20
30
  };
21
31
  /**
22
32
  * Fill per role.
@@ -72,7 +82,7 @@ const Message = React.forwardRef(function Message({ className, role = "agent", a
72
82
  children: [
73
83
  hasHeader ? /* @__PURE__ */ jsxs("div", {
74
84
  "data-slot": "message-header",
75
- className: "flex min-w-0 items-baseline justify-between gap-(--cue-space-3) font-mono text-(length:--cue-text-micro) tracking-(--cue-tracking-caps) uppercase",
85
+ className: cn("flex min-w-0 items-baseline justify-between gap-(--cue-space-3) text-(length:--cue-text-micro)", LABEL_FACE, LABEL_TRACKING, LABEL_CASE),
76
86
  children: [name === void 0 ? null : /* @__PURE__ */ jsx("span", {
77
87
  "data-slot": "message-author",
78
88
  className: cn("min-w-0 truncate", role === "user" ? "text-accent-fg opacity-70" : "text-(--agent-color)"),
@@ -1,5 +1,6 @@
1
1
  "use client";
2
2
  import { cn } from "../lib/cn.js";
3
+ import { FOCUS_RING_INSET_2 } from "../system/_focus-ring.js";
3
4
  import { computeScrollEdges, edgeFadeMask } from "./_tabs-scroll.js";
4
5
  import { useComposedRefs } from "../lib/compose.js";
5
6
  import { ChevronLeftGlyph, ChevronRightGlyph } from "./_glyphs.js";
@@ -95,7 +96,7 @@ function useEdgeScroll(enabled = true) {
95
96
  * `relative` frame.
96
97
  */
97
98
  function EdgeChevrons({ edges, onNudge, previousLabel, nextLabel, className }) {
98
- const base = "absolute inset-y-0 z-10 flex w-(--cue-space-5) cursor-pointer items-center justify-center text-fg-muted outline-none hover:text-fg focus-visible:outline-2 focus-visible:outline-solid focus-visible:-outline-offset-2 focus-visible:outline-accent";
99
+ const base = `absolute inset-y-0 z-10 flex w-(--cue-space-5) cursor-pointer items-center justify-center text-fg-muted outline-none hover:text-fg ${FOCUS_RING_INSET_2}`;
99
100
  return /* @__PURE__ */ jsxs(Fragment, { children: [edges.start ? /* @__PURE__ */ jsx("button", {
100
101
  type: "button",
101
102
  "data-slot": "edge-scroll-previous",
@@ -1,4 +1,6 @@
1
1
  import { cn } from "../lib/cn.js";
2
+ import { FOCUS_RING_INSET } from "../system/_focus-ring.js";
3
+ import { LABEL_FACE } from "../system/_style-label-face.js";
2
4
  //#region src/chrome/_status-bar.ts
3
5
  /**
4
6
  * The class half of `StatusBar` (see `./status-bar.tsx`).
@@ -42,8 +44,12 @@ const ITEM_BASE = "inline-flex min-w-0 shrink-0 items-center gap-(--cue-space-2)
42
44
  *
43
45
  * The reset first: a `<button>` arrives with a border, a ground, a gutter and a
44
46
  * font of the user agent's choosing, and none of them belong in a 24px strip.
45
- * `text-(length:--cue-text-label)` and `font-mono` are re-declared rather than
46
- * inherited for the same reason — form controls do not inherit type.
47
+ * `text-(length:--cue-text-label)` and the face are re-declared rather than
48
+ * inherited for the same reason — form controls do not inherit type. The face
49
+ * is the bar's own, {@link LABEL_FACE}, and not a fixed `font-mono`: the bar
50
+ * reads `--cue-style-label-face`, and a restatement that did not read it too
51
+ * left every control mono while the readings beside it went sans under a
52
+ * sans-voiced Look (tender, kiln, porcelain) — one bar in two faces.
47
53
  *
48
54
  * `h-full` is the VS Code reading of a status item and the one that makes hover
49
55
  * legible: the fill is the height of the bar, not the height of the words, so a
@@ -58,7 +64,7 @@ const ITEM_BASE = "inline-flex min-w-0 shrink-0 items-center gap-(--cue-space-2)
58
64
  * never match `:disabled` — the pseudo-class is defined on form controls — so
59
65
  * without the data twin a disabled link would read as perfectly live.
60
66
  */
61
- const INTERACTIVE_CHASSIS = "h-full cursor-pointer border-0 bg-transparent py-0 font-mono text-(length:--cue-text-label) outline-none transition-colors duration-150 focus-visible:outline-2 focus-visible:outline-solid focus-visible:-outline-offset-1 focus-visible:outline-accent disabled:pointer-events-none disabled:opacity-40 data-[disabled]:pointer-events-none data-[disabled]:opacity-40 motion-reduce:transition-none";
67
+ const INTERACTIVE_CHASSIS = `h-full cursor-pointer border-0 bg-transparent py-0 ${LABEL_FACE} text-(length:--cue-text-label) outline-none transition-colors duration-150 ${FOCUS_RING_INSET} disabled:pointer-events-none disabled:opacity-40 data-[disabled]:pointer-events-none data-[disabled]:opacity-40 motion-reduce:transition-none`;
62
68
  /**
63
69
  * A quiet control's gutter, and the negative margin that pays for it.
64
70
  *
@@ -56,8 +56,24 @@ declare function computeScrollEdges(scrollLeft: number, scrollWidth: number, cli
56
56
  * overflowing edge is often the gap between two tabs, and fading empty space is
57
57
  * invisible — hence the chevron buttons in the component.
58
58
  *
59
+ * **The default reach is a custom property, not a number**, so a paint pack can
60
+ * lengthen or shorten every edge fade in the library at once. It is written as
61
+ * `var(--cue-paint-fade-length,24px)` with the fallback spelled out, because an
62
+ * ink or a paint name is declared with a `:root` default here but the mask is
63
+ * also built by this function in isolation — a test calling it with no DOM
64
+ * would otherwise produce a gradient with an unresolvable stop.
65
+ *
66
+ * `--cue-paint-fade-length` is `24px` at `:root` and {@link TAB_FADE_PX} is 24,
67
+ * so the swap renders identically: measured pixel for pixel in Chromium and
68
+ * WebKit, with a 64px pack changing 15,360 channels to prove the probe could
69
+ * see a difference.
70
+ *
71
+ * An explicit `fadePx` still wins, and stays a plain number: a caller that has
72
+ * measured its own reach is not asking for the axis's.
73
+ *
59
74
  * @param edges Which edges overflow, from {@link computeScrollEdges}.
60
- * @param fadePx How far the fade reaches in. Defaults to {@link TAB_FADE_PX}.
75
+ * @param fadePx How far the fade reaches in. Omitted, it follows
76
+ * `--cue-paint-fade-length`, whose own default is {@link TAB_FADE_PX}.
61
77
  * @returns A `linear-gradient(...)` value, or `undefined` when nothing
62
78
  * overflows — no mask property at all, rather than a fully opaque one, so the
63
79
  * common case creates no compositing layer.
@@ -59,15 +59,32 @@ function computeScrollEdges(scrollLeft, scrollWidth, clientWidth) {
59
59
  * overflowing edge is often the gap between two tabs, and fading empty space is
60
60
  * invisible — hence the chevron buttons in the component.
61
61
  *
62
+ * **The default reach is a custom property, not a number**, so a paint pack can
63
+ * lengthen or shorten every edge fade in the library at once. It is written as
64
+ * `var(--cue-paint-fade-length,24px)` with the fallback spelled out, because an
65
+ * ink or a paint name is declared with a `:root` default here but the mask is
66
+ * also built by this function in isolation — a test calling it with no DOM
67
+ * would otherwise produce a gradient with an unresolvable stop.
68
+ *
69
+ * `--cue-paint-fade-length` is `24px` at `:root` and {@link TAB_FADE_PX} is 24,
70
+ * so the swap renders identically: measured pixel for pixel in Chromium and
71
+ * WebKit, with a 64px pack changing 15,360 channels to prove the probe could
72
+ * see a difference.
73
+ *
74
+ * An explicit `fadePx` still wins, and stays a plain number: a caller that has
75
+ * measured its own reach is not asking for the axis's.
76
+ *
62
77
  * @param edges Which edges overflow, from {@link computeScrollEdges}.
63
- * @param fadePx How far the fade reaches in. Defaults to {@link TAB_FADE_PX}.
78
+ * @param fadePx How far the fade reaches in. Omitted, it follows
79
+ * `--cue-paint-fade-length`, whose own default is {@link TAB_FADE_PX}.
64
80
  * @returns A `linear-gradient(...)` value, or `undefined` when nothing
65
81
  * overflows — no mask property at all, rather than a fully opaque one, so the
66
82
  * common case creates no compositing layer.
67
83
  */
68
- function edgeFadeMask(edges, fadePx = 24) {
84
+ function edgeFadeMask(edges, fadePx) {
69
85
  if (!edges.start && !edges.end) return void 0;
70
- return `linear-gradient(to right, ${edges.start ? `transparent 0px, black ${fadePx}px` : "black 0px"}, ${edges.end ? `black calc(100% - ${fadePx}px), transparent 100%` : "black 100%"})`;
86
+ const reach = fadePx === void 0 ? `var(--cue-paint-fade-length,24px)` : `${fadePx}px`;
87
+ return `linear-gradient(to right, ${edges.start ? `transparent 0px, black ${reach}` : "black 0px"}, ${edges.end ? `black calc(100% - ${reach}), transparent 100%` : "black 100%"})`;
71
88
  }
72
89
  //#endregion
73
90
  export { TAB_FADE_PX, computeScrollEdges, edgeFadeMask };
@@ -2,6 +2,9 @@ import { cn } from "../lib/cn.js";
2
2
  import { Link } from "../layout/link.js";
3
3
  import { Separator } from "../primitives/separator.js";
4
4
  import { EdgeScrollNav } from "./_edge-scroller.js";
5
+ import { GLASS_CLASSES } from "../system/_paint-glass.js";
6
+ import { APP_BAR_CHROME, APP_BAR_LINK, APP_BAR_QUIET_INK } from "../system/_style-app-bar.js";
7
+ import { NAV_VOICE } from "../system/_style-nav-voice.js";
5
8
  import * as React from "react";
6
9
  import { jsx } from "react/jsx-runtime";
7
10
  //#region src/chrome/app-bar.tsx
@@ -11,6 +14,10 @@ import { jsx } from "react/jsx-runtime";
11
14
  * One rung of the chrome ladder tall, from `--cue-chrome-toolbar` — the same
12
15
  * token `Toolbar` and the docs site's hand-rolled header use, so a page that
13
16
  * stacks a bar on a toolbar gets two equal strips rather than two guesses.
17
+ * A style set may make it taller, lighten, drop or dash its rule and widen its
18
+ * inline inset (`style-appbar-height`, `style-chrome-rule`,
19
+ * `style-chrome-rule-style`, `style-appbar-inset`); under a set that names
20
+ * none of them it is exactly this.
14
21
  *
15
22
  * Sticky by default, and translucent because of it: a bar pinned over scrolling
16
23
  * content needs a ground, and `bg-surface-1/95` plus `backdrop-blur` says
@@ -53,7 +60,7 @@ const AppBarRoot = React.forwardRef(function AppBarRoot({ className, sticky = tr
53
60
  return /* @__PURE__ */ jsx("header", {
54
61
  ref,
55
62
  "data-slot": "app-bar",
56
- className: cn("flex h-(--cue-chrome-toolbar) w-full shrink-0 items-center gap-(--cue-space-4) border-b border-border bg-surface-1/95 px-(--cue-space-5) backdrop-blur", sticky ? "sticky top-0 z-40" : null, className),
63
+ className: cn(`flex w-full shrink-0 items-center gap-(--cue-space-4) border-b ${APP_BAR_CHROME} ${GLASS_CLASSES}`, sticky ? "sticky top-0 z-40" : null, className),
57
64
  ...elementProps
58
65
  });
59
66
  });
@@ -108,7 +115,7 @@ const AppBarNav = React.forwardRef(function AppBarNav({ className, frameClassNam
108
115
  });
109
116
  });
110
117
  const REGISTERS = {
111
- muted: "text-fg-muted",
118
+ muted: APP_BAR_QUIET_INK,
112
119
  strong: "text-fg"
113
120
  };
114
121
  /**
@@ -150,7 +157,7 @@ const AppBar = {
150
157
  ref,
151
158
  "data-active": active ? "" : void 0,
152
159
  "aria-current": active ? "page" : void 0,
153
- className: cn("shrink-0 font-mono text-(length:--cue-text-ui)", active ? "text-accent" : REGISTERS[register], className),
160
+ className: cn(`shrink-0 rounded-control ${NAV_VOICE} ${APP_BAR_LINK}`, active ? "text-accent" : REGISTERS[register], className),
154
161
  ...linkProps
155
162
  });
156
163
  }),
@@ -5,6 +5,7 @@ import { Sidebar } from "../layout/sidebar.js";
5
5
  import { CrossGlyph } from "../overlays/_glyphs.js";
6
6
  import { Drawer } from "../overlays/drawer.js";
7
7
  import { IconButton } from "../primitives/icon-button.js";
8
+ import { TEXTURE_CLASSES } from "../system/_paint-texture.js";
8
9
  import { DRAG_CLASSES, NO_DRAG_CLASSES } from "./_drag.js";
9
10
  import * as React from "react";
10
11
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
@@ -113,7 +114,7 @@ const AppShell = {
113
114
  ref,
114
115
  "data-slot": "app-shell",
115
116
  "data-rail": rail ? "" : void 0,
116
- className: cn("group/app-shell relative flex h-dvh flex-col overflow-clip bg-bg text-fg", className),
117
+ className: cn("group/app-shell relative flex h-dvh flex-col overflow-clip bg-bg text-fg", TEXTURE_CLASSES, className),
117
118
  style: {
118
119
  [NAV_WIDTH_PROPERTY]: rail ? railWidth : navWidth,
119
120
  ...style
@@ -9,7 +9,7 @@ type BandSeparation = "rule" | "ground" | "bleed" | "none";
9
9
  *
10
10
  * `"prose"` is the default and is the only one of the five that moves with
11
11
  * `[data-style]`: 68ch with no set and under `console`, 74ch under `editorial`,
12
- * 60ch under `marketing`. The four rungs are fixed aliases and a band that
12
+ * 60ch under `marketing` and `graphite`. The four rungs are fixed aliases and a band that
13
13
  * names one has opted out of the axis for its measure — which is the right
14
14
  * answer for a band holding a `Bento` or a device frame, and the wrong one for
15
15
  * a band holding a paragraph.
@@ -39,13 +39,15 @@ interface BandProps extends React.ComponentPropsWithoutRef<"section"> {
39
39
  *
40
40
  * | set | `"rule"` draws | `"ground"` paints |
41
41
  * |---|---|---|
42
- * | *(no set)* and `console` | 1px | nothing — the ground is `transparent` |
42
+ * | *(no set)*, `console`, `tender`, `zine` and `porcelain` | 1px | nothing — the ground is `transparent` |
43
43
  * | `editorial` | a 0.5px hairline, **which Chromium paints at 1px at every DPR**; only retina WebKit draws it thinner | nothing — `transparent` |
44
44
  * | `marketing` | **nothing — the rule is `0px`** | `--cue-surface-1` |
45
+ * | `kiln` | **nothing — the rule is `0px`**; `Footer` keeps its own, through `--cue-style-footer-rule` | `--cue-sunken`, the recessed ground |
46
+ * | `graphite` | 1px, in `--cue-border` | nothing — `transparent` |
45
47
  *
46
- * Read the diagonal: `"ground"` is the marketing separation and `"rule"` is
47
- * everyone else's. A band that wants to separate under *every* set separates
48
- * by rhythm, which every set has.
48
+ * Read the diagonal: `"ground"` is the marketing and kiln separation and
49
+ * `"rule"` is everyone else's. A band that wants to separate under *every* set
50
+ * separates by rhythm, which every set has.
49
51
  */
50
52
  separation?: BandSeparation;
51
53
  /** Which measure the band's centred column takes. Defaults to `"prose"`. */
@@ -67,23 +69,27 @@ interface BandProps extends React.ComponentPropsWithoutRef<"section"> {
67
69
  * Every dimension it spends belongs to the style axis, so the same markup
68
70
  * composes differently under `[data-style]` without a prop changing: the
69
71
  * vertical rhythm is `--cue-band-y` (one `--cue-space-7` with no set, doubled
70
- * under `editorial`, trebled under `marketing`), the column is
72
+ * under `editorial`, trebled under `marketing` and `graphite`), the column is
71
73
  * `--cue-measure-prose` unless `width` names a fixed rung, and the rule and the
72
74
  * ground are `--cue-band-rule` and `--cue-band-ground`. Read `separation`'s own
73
75
  * documentation before choosing one, because two of the four can come out to
74
76
  * nothing and they do not vanish symmetrically: `--cue-band-ground` is
75
- * `transparent` on `:root` and on two of the three sets, so a `"ground"` paints
76
- * nothing in three of the four states a page can be in, while `--cue-band-rule`
77
- * is `0px` under `marketing` alone. Both are deliberate and nothing warns.
77
+ * `transparent` on `:root` and on every set but `marketing` and `kiln`, so a
78
+ * `"ground"` paints nothing on most pages, while `--cue-band-rule` is `0px`
79
+ * under those two alone. Both are deliberate and nothing warns.
78
80
  *
79
81
  * **Two substitution boundaries, because `--cue-band-y` is a `calc()` resolved
80
82
  * at the element that declares it.** A `<Density>` island nested inside a
81
83
  * styled page moves every `--cue-space-*` and the band rhythm does **not**
82
84
  * follow it — the island inherits the rhythm already resolved above. Restate
83
85
  * the set on the island (`<Density density="compact" styleSet="editorial">`) to
84
- * re-resolve it against that island's rung. Likewise a nested `[data-theme]`
85
- * under a marketing band paints the **outer** theme's `--cue-surface-1` through
86
- * an already-resolved `--cue-band-ground`.
86
+ * re-resolve it against that island's rung. Likewise a hand-stamped
87
+ * `[data-theme]` element under a marketing page paints the **outer** theme's
88
+ * `--cue-surface-1` through an already-resolved `--cue-band-ground`, and its
89
+ * rule in the outer theme's border. The library's own theme islands do not: a
90
+ * nested `ThemeProvider` that names a theme or a mode, and a `Preview` stage
91
+ * with a theme, a mode or a pairing, restate the set in force beside it, so a
92
+ * band inside one paints that island's ground and rule.
87
93
  *
88
94
  * It renders a `<section>`, which is not a landmark until it has an accessible
89
95
  * name — so a band with a heading should carry `aria-labelledby` pointing at
@@ -1,34 +1,15 @@
1
1
  import { cn } from "../lib/cn.js";
2
+ import { TEXTURE_CLASSES } from "../system/_paint-texture.js";
2
3
  import { Container } from "../layout/container.js";
3
4
  import { bandClasses } from "./_band.js";
5
+ import { BAND_BROAD_WIDTH, BAND_Y_HALVES } from "../system/_style-band.js";
6
+ import { GROUND_PATTERN_CLASSES } from "../system/_paint-ground-pattern.js";
4
7
  import * as React from "react";
5
8
  import { jsx } from "react/jsx-runtime";
6
9
  //#region src/chrome/band.tsx
7
- /**
8
- * What each separation adds to the frame `bandClasses` draws, and the two
9
- * `--cue-*` names that live in this file rather than in the chassis beside it.
10
- *
11
- * `_band.ts` holds only what `Footer` can also render — the rhythm and the
12
- * rule — because docgen's token scanner reads a chassis file whole and cannot
13
- * see that `Footer` calls `bandClasses` with the literal `"rule"`. The ground
14
- * is reachable only from `<Band separation="ground">`, so it is written here,
15
- * next to the prop whose value selects it. `_band.ts`'s own docblock carries
16
- * the argument.
17
- *
18
- * `rule`'s entry is the colour and not the width: the width is
19
- * `--cue-band-rule` and belongs to the chassis, and both elements name the ink
20
- * in their own class list rather than inheriting it from the other.
21
- *
22
- * That ink is now a token. It was the literal `border-border`, spelled here and
23
- * again in `Footer`, which meant a style set could say how THICK the line
24
- * between two bands is and had no way to say what colour it was — and every
25
- * site measured in the 2026-09-22 corpus that separates bands by a line picks
26
- * one lighter than its box edge. `--cue-band-rule-color` defaults to
27
- * `var(--cue-border)` on `:root`, which is byte-for-byte what this drew before.
28
- */
29
10
  const SEPARATION_PAINT = {
30
11
  rule: "border-(--cue-band-rule-color)",
31
- ground: "bg-(--cue-band-ground)",
12
+ ground: `bg-(--cue-band-ground) ${GROUND_PATTERN_CLASSES} ${TEXTURE_CLASSES} before:[mask-image:linear-gradient(var(--cue-band-ground),var(--cue-band-ground)),var(--cue-paint-fade)] before:[-webkit-mask-image:linear-gradient(var(--cue-band-ground),var(--cue-band-ground)),var(--cue-paint-fade)]`,
32
13
  bleed: null,
33
14
  none: null
34
15
  };
@@ -44,23 +25,27 @@ const SEPARATION_PAINT = {
44
25
  * Every dimension it spends belongs to the style axis, so the same markup
45
26
  * composes differently under `[data-style]` without a prop changing: the
46
27
  * vertical rhythm is `--cue-band-y` (one `--cue-space-7` with no set, doubled
47
- * under `editorial`, trebled under `marketing`), the column is
28
+ * under `editorial`, trebled under `marketing` and `graphite`), the column is
48
29
  * `--cue-measure-prose` unless `width` names a fixed rung, and the rule and the
49
30
  * ground are `--cue-band-rule` and `--cue-band-ground`. Read `separation`'s own
50
31
  * documentation before choosing one, because two of the four can come out to
51
32
  * nothing and they do not vanish symmetrically: `--cue-band-ground` is
52
- * `transparent` on `:root` and on two of the three sets, so a `"ground"` paints
53
- * nothing in three of the four states a page can be in, while `--cue-band-rule`
54
- * is `0px` under `marketing` alone. Both are deliberate and nothing warns.
33
+ * `transparent` on `:root` and on every set but `marketing` and `kiln`, so a
34
+ * `"ground"` paints nothing on most pages, while `--cue-band-rule` is `0px`
35
+ * under those two alone. Both are deliberate and nothing warns.
55
36
  *
56
37
  * **Two substitution boundaries, because `--cue-band-y` is a `calc()` resolved
57
38
  * at the element that declares it.** A `<Density>` island nested inside a
58
39
  * styled page moves every `--cue-space-*` and the band rhythm does **not**
59
40
  * follow it — the island inherits the rhythm already resolved above. Restate
60
41
  * the set on the island (`<Density density="compact" styleSet="editorial">`) to
61
- * re-resolve it against that island's rung. Likewise a nested `[data-theme]`
62
- * under a marketing band paints the **outer** theme's `--cue-surface-1` through
63
- * an already-resolved `--cue-band-ground`.
42
+ * re-resolve it against that island's rung. Likewise a hand-stamped
43
+ * `[data-theme]` element under a marketing page paints the **outer** theme's
44
+ * `--cue-surface-1` through an already-resolved `--cue-band-ground`, and its
45
+ * rule in the outer theme's border. The library's own theme islands do not: a
46
+ * nested `ThemeProvider` that names a theme or a mode, and a `Preview` stage
47
+ * with a theme, a mode or a pairing, restate the set in force beside it, so a
48
+ * band inside one paints that island's ground and rule.
64
49
  *
65
50
  * It renders a `<section>`, which is not a landmark until it has an accessible
66
51
  * name — so a band with a heading should carry `aria-labelledby` pointing at
@@ -82,6 +67,9 @@ const Band = React.forwardRef(function Band({ className, columnClassName, separa
82
67
  const column = width === "prose" ? {
83
68
  width: "full",
84
69
  className: "max-w-(--cue-measure-prose)"
70
+ } : width === "broad" ? {
71
+ width: "full",
72
+ className: BAND_BROAD_WIDTH
85
73
  } : {
86
74
  width,
87
75
  className: null
@@ -90,7 +78,7 @@ const Band = React.forwardRef(function Band({ className, columnClassName, separa
90
78
  ref,
91
79
  "data-slot": "band",
92
80
  "data-separation": separation,
93
- className: cn(bandClasses(separation), SEPARATION_PAINT[separation], className),
81
+ className: cn(bandClasses(separation), BAND_Y_HALVES, SEPARATION_PAINT[separation], className),
94
82
  ...elementProps,
95
83
  children: separation === "bleed" ? children : /* @__PURE__ */ jsx(Container, {
96
84
  width: column.width,