@cueplusplus/ui 0.12.0 → 0.14.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 (196) hide show
  1. package/CHANGELOG.md +305 -0
  2. package/LICENSE +21 -0
  3. package/NOTICE.md +34 -0
  4. package/README.md +2 -19
  5. package/dist/agent-runtime/tool-call-card.js +2 -2
  6. package/dist/chat/ask-box.js +2 -2
  7. package/dist/chat/composer.js +1 -1
  8. package/dist/chat/message.js +1 -1
  9. package/dist/chrome/_band.js +54 -0
  10. package/dist/chrome/band.d.ts +106 -0
  11. package/dist/chrome/band.js +97 -0
  12. package/dist/chrome/empty-state.js +1 -1
  13. package/dist/chrome/footer.d.ts +13 -0
  14. package/dist/chrome/footer.js +17 -2
  15. package/dist/chrome/index.d.ts +2 -1
  16. package/dist/chrome/index.js +2 -1
  17. package/dist/chrome/navigation-menu.js +1 -1
  18. package/dist/chrome/page-shell.js +4 -4
  19. package/dist/configurator/export-dialog.js +1 -1
  20. package/dist/configurator/panel-sections.js +1 -1
  21. package/dist/elements/agent-card.js +1 -1
  22. package/dist/elements/agent-handoff.js +2 -2
  23. package/dist/elements/canvas-split.js +2 -2
  24. package/dist/elements/chat-panel.js +1 -1
  25. package/dist/elements/code-diff.js +1 -1
  26. package/dist/elements/code-runner.js +2 -2
  27. package/dist/elements/comparison-card.js +1 -1
  28. package/dist/elements/confidence-marker.js +1 -1
  29. package/dist/elements/conversation-search.js +1 -1
  30. package/dist/elements/day-separator.js +1 -1
  31. package/dist/elements/document-reference.js +1 -1
  32. package/dist/elements/edit-message.js +1 -1
  33. package/dist/elements/elicitation-form.js +1 -1
  34. package/dist/elements/guardrail-notice.js +1 -1
  35. package/dist/elements/image-generation.js +1 -1
  36. package/dist/elements/inline-citation.js +2 -2
  37. package/dist/elements/markdown.js +1 -1
  38. package/dist/elements/math-block.js +1 -1
  39. package/dist/elements/message-branches.js +1 -1
  40. package/dist/elements/message-pair.js +1 -1
  41. package/dist/elements/onboarding.js +2 -2
  42. package/dist/elements/prompt-library.js +1 -1
  43. package/dist/elements/quote-reply.js +2 -2
  44. package/dist/elements/read-aloud.js +1 -1
  45. package/dist/elements/reasoning-panel.js +1 -1
  46. package/dist/elements/recommendation-card.js +1 -1
  47. package/dist/elements/research-report.js +1 -1
  48. package/dist/elements/retrieval-chunks.js +1 -1
  49. package/dist/elements/reviewable-diff.js +1 -1
  50. package/dist/elements/score-breakdown.js +1 -1
  51. package/dist/elements/scroll-anchor.js +1 -1
  52. package/dist/elements/settings-panel.js +1 -1
  53. package/dist/elements/shared-conversation.js +1 -1
  54. package/dist/elements/speaker-identity.js +1 -1
  55. package/dist/elements/stopped-run.js +1 -1
  56. package/dist/elements/streaming-text.js +1 -1
  57. package/dist/elements/timeline.js +1 -1
  58. package/dist/elements/tool-error.js +1 -1
  59. package/dist/elements/voice-conversation.js +1 -1
  60. package/dist/forms/textarea.js +1 -1
  61. package/dist/index.d.ts +5 -4
  62. package/dist/index.js +4 -2
  63. package/dist/instruments/code-block.js +1 -1
  64. package/dist/instruments/progress.d.ts +19 -3
  65. package/dist/instruments/progress.js +19 -1
  66. package/dist/instruments/terminal-frame.js +1 -1
  67. package/dist/layout/_collapse.js +1 -1
  68. package/dist/layout/card.js +1 -1
  69. package/dist/layout/container.js +3 -3
  70. package/dist/layout/frames.d.ts +19 -1
  71. package/dist/layout/frames.js +21 -7
  72. package/dist/layout/index.d.ts +2 -2
  73. package/dist/layout/preview.d.ts +29 -9
  74. package/dist/layout/preview.js +38 -17
  75. package/dist/overlays/_surface.d.ts +1 -1
  76. package/dist/overlays/_surface.js +1 -1
  77. package/dist/overlays/toast.js +1 -1
  78. package/dist/overlays/tooltip.js +1 -1
  79. package/dist/primitives/chip.d.ts +1 -1
  80. package/dist/system/density.d.ts +34 -6
  81. package/dist/system/density.js +41 -10
  82. package/dist/system/index.d.ts +2 -1
  83. package/dist/system/index.js +2 -1
  84. package/dist/system/portal.d.ts +8 -7
  85. package/dist/system/portal.js +16 -9
  86. package/dist/system/prepaint.d.ts +25 -5
  87. package/dist/system/prepaint.js +10 -2
  88. package/dist/system/theme-provider.d.ts +86 -7
  89. package/dist/system/theme-provider.js +62 -20
  90. package/dist/system/use-theme.d.ts +9 -2
  91. package/dist/system/use-theme.js +9 -2
  92. package/dist/system/vocabulary.d.ts +2 -1
  93. package/dist/system/vocabulary.js +16 -2
  94. package/manifest/components/accordion.json +1 -0
  95. package/manifest/components/agent-card.json +1 -0
  96. package/manifest/components/agent-handoff.json +1 -0
  97. package/manifest/components/alert-dialog.json +1 -0
  98. package/manifest/components/ask-box.json +1 -0
  99. package/manifest/components/autocomplete.json +1 -0
  100. package/manifest/components/band.json +104 -0
  101. package/manifest/components/canvas-split-body.json +1 -0
  102. package/manifest/components/canvas-split-document.json +1 -0
  103. package/manifest/components/canvas-split-header.json +1 -0
  104. package/manifest/components/canvas-split-line.json +1 -0
  105. package/manifest/components/canvas-split-message.json +1 -0
  106. package/manifest/components/canvas-split-thread.json +1 -0
  107. package/manifest/components/canvas-split.json +1 -0
  108. package/manifest/components/card.json +1 -0
  109. package/manifest/components/channel-matrix.json +1 -0
  110. package/manifest/components/chart-tooltip-content.json +1 -0
  111. package/manifest/components/chat-panel-assistant-message.json +1 -0
  112. package/manifest/components/chat-panel-composer.json +1 -0
  113. package/manifest/components/chat-panel-messages.json +1 -0
  114. package/manifest/components/chat-panel-typing.json +1 -0
  115. package/manifest/components/chat-panel-user-message.json +1 -0
  116. package/manifest/components/chat-panel.json +1 -0
  117. package/manifest/components/code-block.json +1 -0
  118. package/manifest/components/code-diff.json +1 -0
  119. package/manifest/components/code-runner.json +1 -0
  120. package/manifest/components/collapsible.json +1 -0
  121. package/manifest/components/colors-section.json +1 -0
  122. package/manifest/components/combobox.json +1 -0
  123. package/manifest/components/command-palette.json +1 -0
  124. package/manifest/components/comparison-card.json +1 -0
  125. package/manifest/components/composer.json +1 -0
  126. package/manifest/components/confidence-marker.json +1 -0
  127. package/manifest/components/container.json +3 -0
  128. package/manifest/components/context-menu.json +1 -0
  129. package/manifest/components/conversation-search.json +1 -0
  130. package/manifest/components/cue-portal-frame.json +1 -1
  131. package/manifest/components/day-separator.json +1 -0
  132. package/manifest/components/density.json +16 -1
  133. package/manifest/components/dialog.json +1 -0
  134. package/manifest/components/disclosure.json +1 -0
  135. package/manifest/components/dmx-bar.json +1 -0
  136. package/manifest/components/dmx-strip.json +1 -0
  137. package/manifest/components/document-reference.json +1 -0
  138. package/manifest/components/drawer.json +1 -0
  139. package/manifest/components/dropdown-menu.json +1 -0
  140. package/manifest/components/edit-message.json +1 -0
  141. package/manifest/components/elements-timeline.json +1 -0
  142. package/manifest/components/elicitation-form.json +1 -0
  143. package/manifest/components/empty-state.json +1 -0
  144. package/manifest/components/export-dialog.json +1 -0
  145. package/manifest/components/footer.json +3 -2
  146. package/manifest/components/frac.json +1 -0
  147. package/manifest/components/frames.json +14 -0
  148. package/manifest/components/guardrail-notice.json +1 -0
  149. package/manifest/components/hover-card.json +1 -0
  150. package/manifest/components/inline-citation.json +1 -0
  151. package/manifest/components/markdown-text.json +1 -0
  152. package/manifest/components/math-block.json +1 -0
  153. package/manifest/components/menubar.json +1 -0
  154. package/manifest/components/message-branches.json +1 -0
  155. package/manifest/components/message-pair.json +1 -0
  156. package/manifest/components/message.json +1 -0
  157. package/manifest/components/multi-select.json +1 -0
  158. package/manifest/components/navigation-menu.json +1 -0
  159. package/manifest/components/onboarding.json +1 -0
  160. package/manifest/components/page-shell.json +4 -0
  161. package/manifest/components/popover.json +1 -0
  162. package/manifest/components/preset-section.json +1 -0
  163. package/manifest/components/preview.json +17 -2
  164. package/manifest/components/progress.json +2 -2
  165. package/manifest/components/prompt-library.json +1 -0
  166. package/manifest/components/quote-reply.json +1 -0
  167. package/manifest/components/read-aloud.json +1 -0
  168. package/manifest/components/reasoning-panel.json +1 -0
  169. package/manifest/components/recommendation-card.json +1 -0
  170. package/manifest/components/research-report.json +1 -0
  171. package/manifest/components/retrieval-chunks.json +1 -0
  172. package/manifest/components/reviewable-diff.json +1 -0
  173. package/manifest/components/score-breakdown.json +1 -0
  174. package/manifest/components/scroll-anchor.json +1 -0
  175. package/manifest/components/settings-panel.json +1 -0
  176. package/manifest/components/shape-section.json +1 -0
  177. package/manifest/components/shared-conversation.json +1 -0
  178. package/manifest/components/sheet.json +1 -0
  179. package/manifest/components/speaker-identity.json +1 -0
  180. package/manifest/components/stopped-run.json +1 -0
  181. package/manifest/components/streaming-text.json +1 -0
  182. package/manifest/components/sub.json +1 -0
  183. package/manifest/components/sup.json +1 -0
  184. package/manifest/components/tags-input.json +1 -0
  185. package/manifest/components/terminal-frame.json +1 -0
  186. package/manifest/components/textarea.json +1 -0
  187. package/manifest/components/theme-configurator.json +1 -0
  188. package/manifest/components/theme-provider.json +26 -1
  189. package/manifest/components/toast.json +1 -0
  190. package/manifest/components/tool-call-card.json +1 -0
  191. package/manifest/components/tool-error.json +1 -0
  192. package/manifest/components/tooltip.json +1 -0
  193. package/manifest/components/voice-conversation.json +1 -0
  194. package/manifest/manifest.json +133 -105
  195. package/manifest/tokens.json +20 -1
  196. package/package.json +11 -9
package/CHANGELOG.md CHANGED
@@ -1,5 +1,310 @@
1
1
  # @cueplusplus/ui
2
2
 
3
+ ## 0.14.0
4
+
5
+ ### Minor Changes
6
+
7
+ - f9bb2ff: **`Frames` takes a `layout`.** The default, `"board"`, is what it has always
8
+ drawn: a picker across the top and one frame on the stage at a time. The new
9
+ `"column"` runs every frame down a single scroller instead — each with its own
10
+ caption and count, all of them on one ground — so a reader comparing eight
11
+ states of a component reads them rather than clicking through them.
12
+
13
+ ```tsx
14
+ <Frames layout="column" …/>
15
+ ```
16
+
17
+ Nothing changes for markup that does not pass it: `layout` defaults to
18
+ `"board"`, and a `Frames` with no `layout` prop renders byte-for-byte what it
19
+ rendered before.
20
+
21
+ - f9bb2ff: **`ThemeProvider` takes a CSP `nonce`.**
22
+
23
+ When `overrides.densities` is set, the provider emits one `<style>` element for
24
+ the density layer. An application serving `style-src-elem 'self'
25
+ 'nonce-<per-request>'` had that element refused on every page load: React
26
+ renders it on the client, and a client-rendered element cannot pick up a server
27
+ nonce by itself.
28
+
29
+ ```tsx
30
+ // app/layout.tsx — the nonce your middleware already mints
31
+ <ThemeProvider nonce={nonce} overrides={{ densities: … }}>
32
+ ```
33
+
34
+ The attribute is set only when you pass one. It is absent otherwise rather than
35
+ present and empty, because `nonce=""` matches no `'nonce-…'` source and would
36
+ talk a policy out of admitting the element some other way.
37
+
38
+ Nothing else in this library emits a `<style>` element, and `prepaintScript()`
39
+ returns a string your application renders in a `<script>` of its own — so your
40
+ application already owns that element's nonce, and this prop is the whole of
41
+ what a strict `style-src-elem` needs from here.
42
+
43
+ **One thing a nonce cannot fix.** The provider always sets a style _attribute_
44
+ on its root — `color-scheme` and `--cue-font-scale`, plus the font families and
45
+ overrides where given. CSP has no nonce form for `style-src-attr`: it is
46
+ `'unsafe-inline'` or `'none'`. Under `'none'` the browser drops those
47
+ declarations, and no prop here can change that.
48
+
49
+ ### Patch Changes
50
+
51
+ - 331501f: ## The scope goes public
52
+
53
+ Every package in `@cueplusplus` was private on npm. npm authenticates _every_
54
+ read of a private package, so each consumer needed a granular read-only token,
55
+ and it could not live in a committed `.npmrc` — pnpm 10 and later ignore an
56
+ env-expanded `_authToken` there by design. The failure mode was the expensive
57
+ part: npm answers a private package the same way to a reader it will not admit
58
+ exists, so a missing credential surfaced as `404 Not Found` rather than `401`,
59
+ and read as "this was never published".
60
+
61
+ That was a fair trade while the design system had no consumer outside the org.
62
+ It stopped being one the moment a public project depended on it, because a
63
+ public project cannot ask its readers for a token before they can install it.
64
+
65
+ So `access` is `public`, in the Changesets config and in all sixteen manifests.
66
+ Consumers now run `pnpm add @cueplusplus/ui` and nothing else: no token, no
67
+ `.npmrc`, nothing to rotate, and no extra step in CI or on a hosting provider.
68
+
69
+ Nothing else moves. Same registry, same names, same versions — so no consumer
70
+ needs to regenerate a lockfile, and a machine that keeps its npm token for
71
+ another private scope can keep it.
72
+
73
+ The guard tests are turned around rather than removed. `changeset-config` still
74
+ asserts the access level and `publishable-packages` still asserts the registry;
75
+ both now assert the public contract. `publishable-packages` additionally asserts
76
+ `access: "public"` per manifest, which it never did before: the Changesets config
77
+ decides what a release does, but npm defaults a scoped package to restricted, so
78
+ a manifest that forgets is the one that quietly stays private while its siblings
79
+ go public.
80
+
81
+ - 52094a9: **The `@cueplusplus` scope is served by npm now, not GitHub Packages.** Every package is
82
+ **private** there, so installs still authenticate — but the credential and the configuration both
83
+ change, and the old ones stop working.
84
+
85
+ **What to remove.** The scope routing you were asked to commit:
86
+
87
+ ```ini
88
+ # .npmrc — delete this line
89
+ @cueplusplus:registry=https://npm.pkg.github.com
90
+ ```
91
+
92
+ Nothing replaces it. npm's own registry is where the scope resolves by default, so there is no
93
+ routing to commit at all — which also means a project that consumed this scope through a committed
94
+ `.npmrc` can usually delete the file.
95
+
96
+ **What to replace.** The classic GitHub PAT with `read:packages` is no longer used. In its place,
97
+ an npm **granular access token** with **read-only** permission on the `@cueplusplus` scope,
98
+ written once at the user level:
99
+
100
+ ```sh
101
+ pnpm config set //registry.npmjs.org/:_authToken npm_…
102
+ ```
103
+
104
+ It goes at the user level for the same reason as before: pnpm 10 and later ignore an env-expanded
105
+ `_authToken` in a project `.npmrc`, and the install then fails with a `404` — not a `401` — and a
106
+ warning nobody reads. npm answers a private package the same way to a reader it will not admit
107
+ exists, so the failure reads as "never published".
108
+
109
+ **One token, every scope.** npm authenticates per registry rather than per scope, so a machine
110
+ that installs other private scopes from npm needs one line, not one per scope — select them all on
111
+ the same token. Two different tokens for `registry.npmjs.org` cannot coexist in one config.
112
+
113
+ **CI changes too, and this one is easy to miss.** Under GitHub Packages a workflow's own
114
+ `GITHUB_TOKEN` could read the scope, so many workflows carried no secret. npm does not know about
115
+ that token. Every repository that installs these packages now needs the read-only npm token as a
116
+ secret, and `setup-node` pointed at `registry.npmjs.org`. The same applies to Vercel, Trigger.dev
117
+ and any Docker build that installs — `docs/CONSUMING.md` §1 has each of them.
118
+
119
+ Nothing about the packages themselves changed: same exports, same versions, same contents. What
120
+ moved is where they are served from and what proves you may read them.
121
+
122
+ - Updated dependencies [331501f]
123
+ - Updated dependencies [52094a9]
124
+ - @cueplusplus/theme-base@1.0.3
125
+ - @cueplusplus/tokens@0.14.0
126
+
127
+ ## 0.13.0
128
+
129
+ ### Minor Changes
130
+
131
+ - f87c822: `Band`, the page's horizontal section — and `Footer` now spends its recipe
132
+ instead of carrying a second copy of it.
133
+
134
+ **What `Band` is.** A full-bleed element, a rule or a ground running edge to
135
+ edge, and a centred column at the measure — which is what a footer has always
136
+ been, minus the footer. Every dimension it spends belongs to the fourth axis,
137
+ so the same markup composes three ways under `data-style` with no prop
138
+ changing: `--cue-band-y` for the rhythm, `--cue-measure-prose` for the column
139
+ unless `width` names one of `Container`'s four fixed rungs, and
140
+ `--cue-band-rule` / `--cue-band-ground` for the separation. `separation` takes
141
+ `"rule"`, `"ground"`, `"bleed"` (no column — the children run the full width)
142
+ and `"none"` (rhythm alone). Two of those can come out to nothing, by design
143
+ and with nothing to warn you, and they do not vanish symmetrically: a ground is
144
+ `transparent` on `:root` and on two of the three sets, so it paints only under
145
+ `marketing`, while a rule is `0px` under `marketing` alone. The prop's
146
+ documentation carries the table, and a test holds the table to the stylesheet
147
+ so it cannot stop being true.
148
+
149
+ **What changed for existing callers.** `Footer` is built on `Band`'s recipe
150
+ now — `separation="rule"`, spent through two internal helpers rather than
151
+ through `<Band>` itself, because `Band` renders a `<section>` and `Footer` has
152
+ to keep rendering the `<footer>` that makes it the `contentinfo` landmark.
153
+ Under no style set it renders exactly what it rendered before: `--cue-band-y`
154
+ resolves to `var(--cue-space-7)`, the same rung the column always spelled, and
155
+ `--cue-band-rule` resolves to `var(--cue-border-width)`, the same 1px
156
+ `border-t` always painted. Inside a `[data-style]` subtree it now follows the
157
+ axis like any other band: a hairline and doubled rhythm under `editorial`, no
158
+ rule at all and trebled rhythm under `marketing`. **This is the first shipped
159
+ component to follow `data-style`.** An app that wants the old, fixed behaviour
160
+ inside a styled region wraps the footer in `<Density styleSet="console">`.
161
+
162
+ **What did not change.** `FooterProps` is the same four props —
163
+ `width`, `meta`, `columnClassName`, `children` — byte for byte; this is a
164
+ change of implementation, not of contract. The fine-print rule above the
165
+ meta row is still a literal `border-t border-border` and does not follow the
166
+ axis: it separates content inside the footer, not the footer from the page.
167
+
168
+ **What the published manifest says now.** The helper `Footer` spends `Band`'s
169
+ recipe through first landed in `band.tsx`, a public component file — and
170
+ `packages/docgen`'s token scanner only follows a component's imports into an
171
+ underscore-prefixed chassis file, the same convention `chrome/_drag.ts` already
172
+ uses. It never opened `band.tsx`, so `footer.json`'s `tokensUsed` — and the
173
+ token chips on `/docs/components/footer` — silently lost `--cue-space-7` and
174
+ gained neither of the two names that replaced it. The recipe now lives in
175
+ `chrome/_band.ts`, and `footer.json` publishes ten names: the nine it shipped
176
+ before this branch, less the `--cue-space-7` that `--cue-band-y` replaced, plus
177
+ `--cue-band-y` and `--cue-band-rule`. Those two
178
+ are the whole of what a `<footer>` takes from the recipe, so they are the whole
179
+ of what that file holds — the scanner reads a chassis file whole and cannot see
180
+ which branch a call takes, and `Footer` fixes `separation` at the literal
181
+ `"rule"` and types `width` as `ContainerWidth`. `Band`'s other two style-owned
182
+ spends, `--cue-band-ground` and `--cue-measure-prose`, are unreachable from a
183
+ footer and are written in `band.tsx` beside the prop values that select them,
184
+ so `band.json` publishes all five and `footer.json` claims neither. Nothing
185
+ else in either component's manifest entry moved.
186
+
187
+ **What it costs.** Nothing at runtime; the manifest grows one component.
188
+
189
+ **Correction, no behaviour change.** `layout/preview.tsx`'s docblock cited the
190
+ group pages' tooled `Preview` count as 325; `Band` landing raised the
191
+ library's component count and the tooled figure to 326. Comment-only, caught
192
+ by the branch's own review sweep, and folded in here because it is the last
193
+ commit that touches this package's authored tree before the note.
194
+
195
+ - 5b40f07: **A fourth composable axis: `data-style`, for page composition.**
196
+
197
+ Theme, density and font already answer "what colour", "how tight" and "which
198
+ typeface". `data-style` answers the question none of them could: how a _page_ is
199
+ composed — reading measure, prose line height, and the rhythm of a band. Three
200
+ sets ship. `console` is the current look made explicit and provably unchanged,
201
+ `editorial` widens the measure and opens the leading for long-form reading, and
202
+ `marketing` narrows the measure and spends the vertical space a landing page
203
+ wants.
204
+
205
+ Each set declares `--cue-measure-prose`, `--cue-leading-prose`, `--cue-band-y`,
206
+ `--cue-band-rule` and `--cue-band-ground`; `editorial` and `marketing` add
207
+ `--cue-style-display` for a display type scale. Only the display rung composes
208
+ with `--cue-font-scale`, and a name added to the set vocabulary without an
209
+ answer is a build error rather than a silent guess.
210
+
211
+ **Driving it.** `<ThemeProvider styleSet="editorial">` stamps the attribute on
212
+ its own element and on `<html>`, `useTheme().styleSet` and `setStyleSet()` read
213
+ and drive it, and it persists beside theme, density, font and mode under a
214
+ `style` key — written only when there is a set. A pre-paint script applies a
215
+ stored set before the first paint, so turning one on _or off_ lands on the first
216
+ frame rather than the first commit. The set is carried into overlay portals,
217
+ `<Density styleSet>` islands and `<Preview styleSet>` stages, so an overlay
218
+ follows the subtree it was opened from and three sets can be shown side by side
219
+ on one page.
220
+
221
+ `useTheme().styleSet` is **the set in force, not the set named here**. A
222
+ provider that names no set of its own reports the one stamped around it —
223
+ including a `<Density styleSet>` island sitting between it and an outer provider
224
+ — exactly as the DOM resolves it. That is deliberate: it makes the context value
225
+ and the set a portal or a stage carries out of that DOM one value rather than
226
+ two that can disagree. `null` means nothing anywhere has chosen a set, which is
227
+ not the same fact as `console`.
228
+
229
+ `setStyleSet(null)` is the same distinction from the writing side: it clears the
230
+ set this provider **names**, not the set that applies to it. A nested provider
231
+ that clears its own goes back to inheriting whatever is stamped around it, and
232
+ `styleSet` reports that inherited set, because it is what the cascade resolves
233
+ to. At the root the two coincide, which is why only a nested provider shows the
234
+ difference. To positively leave an inherited set, pass `DEFAULT_STYLE_SET`: it
235
+ stamps an attribute whose block restates the `:root` defaults token for token,
236
+ and an attribute is the only thing that out-specifies an ancestor's.
237
+
238
+ Restating a set on a `<Density>` island is what re-resolves its band rhythm at
239
+ that island's rung: `--cue-band-y` is built from `--cue-space-7`, and a custom
240
+ property's `var()` references are substituted where they are declared, so an
241
+ island that only changes density inherits the rhythm already resolved above it.
242
+
243
+ `STYLE_SETS`, `DEFAULT_STYLE_SET`, `STYLE_CONTRACT`, `STYLE_SET_CONTRACT` and
244
+ the `StyleSet` type are exported from `@cueplusplus/tokens`, so an application
245
+ can type a prop and validate a stored preference against the same closed list
246
+ the stylesheet was built from.
247
+
248
+ **What it costs.**
249
+
250
+ - **Every consumer carries 144 more bytes of blocking inline pre-paint script**,
251
+ whether or not the application uses the axis — a typical script grows from 995
252
+ bytes to 1139. It has to read the stored set and stamp or clear the attribute
253
+ before the first paint, and an application that never touches the axis cannot
254
+ opt out of the branch that decides there is nothing to stamp.
255
+ - **The attribute is the generic `data-style`, not `data-cue-style`.** An
256
+ application already using `data-style` on `<html>` for its own purposes will
257
+ have it overwritten while a `<ThemeProvider>` is mounted, and cleared when the
258
+ provider holds no set; the original value is restored on unmount. The generic
259
+ name was chosen for readability, and this collision is the price. If you use
260
+ `data-style` on `<html>` yourself, move it before upgrading.
261
+
262
+ **What is unchanged.** A page that names no set is untouched: no attribute is
263
+ stamped anywhere, no stored preference gains a key, and a stored `"style": null`
264
+ is refused and scrubbed on the next load like every other value nothing
265
+ declares. `console`'s declarations are asserted at build time to be exactly the
266
+ `:root` defaults, and a browser test compares every `--cue-*` on two identical
267
+ subtrees — one bare, one under `console` — and requires them to compute
268
+ identically. Switching to the default set changes nothing, as a checked fact
269
+ rather than a promise.
270
+
271
+ One note on `editorial`'s hairline: its 0.5px `--cue-band-rule` paints a
272
+ measured 1px on Chromium at either device pixel ratio and 0.5px only on retina
273
+ WebKit, so the separation it actually ships is the doubled `--cue-space-7`
274
+ rhythm with a hairline under it.
275
+
276
+ ### Patch Changes
277
+
278
+ - b1c2f25: **Every package now ships the licence it declares.** All sixteen have said `"license": "MIT"` in
279
+ their manifest since they were first published, and none of them carried the text. Installing one
280
+ gave you a licence field and nothing to read; anyone auditing their dependency tree found a package
281
+ that claimed a licence it did not include. Each package root now holds the MIT notice, and npm packs
282
+ a root `LICENSE` whether or not `files` lists it, so it is in the tarball you install.
283
+
284
+ `@cueplusplus/ui` additionally ships `NOTICE.md`, the third-party notice for the assistant-ui code
285
+ vendored into its elements. That one is not automatic — `files` had to name it — and it is byte-for-byte
286
+ the notice that already sat beside the source it covers, because a notice that travels without the
287
+ bytes it describes is not a notice.
288
+
289
+ Nothing else about these packages changed: same exports, same versions of every dependency, same
290
+ registry. If you are upgrading only for this, the diff you receive is licence text.
291
+
292
+ - 0b30ba6: `ImageGeneration` now clears its blur with `blur-none`. It used to ask for `blur-0`, which is a Tailwind v3 class that v4 has no rule for, so the class did nothing at all. You will not see a difference — the image already came out of its blur when generation finished, because a filter transition runs to no filter just as it runs to zero blur — but the class now says what it does, and the elements sync renames it, so a re-sync from assistant-ui will not put it back.
293
+ - 6f791a8: Two families of hard-coded values become tokens, with nothing rendering differently.
294
+
295
+ `PageShell` and `Container` spell their three capped measures as `max-w-(--cue-measure-narrow)` / `-wide` / `-broad` rather than as `max-w-[42rem]` / `[54rem]` / `[84rem]`. Nothing about the props changes — `PageWidth` and `ContainerWidth` still offer `narrow` / `wide` / `broad` / `full`, still default to `narrow`, and `full` still caps nothing.
296
+
297
+ And the 63 `leading-relaxed` utilities across 55 of this library's modules — dialogs, menus, settings panels, chat rows, tooltips, cards, the two shared class strings behind every collapsible and every popup surface — now spend `--cue-leading-ui`, which `@cueplusplus/tokens` pins at 1.625, Tailwind's own value for that utility. Ninety-one components pick the token up in their `tokensUsed`. `leading-none` is untouched: line-height 1 on an icon or a numeral is a shape decision, not a reading one, so a reading axis has nothing to say about it.
298
+
299
+ Both are exact no-ops today. What they buy you is a knob: one declaration of `--cue-leading-ui` or `--cue-measure-wide`, anywhere in your own CSS, and every component that spends it follows — with no fork and no `className` at the call site.
300
+
301
+ - f813329: `Progress` now names its bar in the HTML your server sends. A screen-reader user on a server-rendered page heard "progress bar, 40%" and never the caption beside it: the words were on the page, but the `role="progressbar"` only pointed at them once the browser had hydrated — and on a page that never hydrates, never. Base UI makes that connection from a layout effect; this layer now hands the caption and the bar the same `useId` while it renders, so the name is in the markup from the first byte and the same reader hears "Rendering, progress bar, 40%" whether or not the JavaScript has arrived. Nothing moves on screen, and a bar you named yourself with `aria-label` or `aria-labelledby` keeps the name you gave it — in the served markup and after hydration alike, which is asserted in both renders rather than in the one the change was written in.
302
+ - Updated dependencies [b1c2f25]
303
+ - Updated dependencies [31a7567]
304
+ - Updated dependencies [5b40f07]
305
+ - @cueplusplus/theme-base@1.0.2
306
+ - @cueplusplus/tokens@0.13.0
307
+
3
308
  ## 0.12.0
4
309
 
5
310
  ### Minor Changes
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 CUE++ contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/NOTICE.md ADDED
@@ -0,0 +1,34 @@
1
+ # Third-party notice — assistant-ui Elements
2
+
3
+ The files in this directory are vendored from [assistant-ui/assistant-ui](https://github.com/assistant-ui/assistant-ui)
4
+ at commit `31a049fcfa846a76da7c8e2c0bcd62960825dbd4` (2026-08-22), from `packages/ui/src/components/elements/`.
5
+ They are rewritten onto CUE++ tokens by `scripts/elements-sync/`, which also records every
6
+ byte it fetched in `scripts/elements-sync/elements-sync.lock.json`.
7
+
8
+ Elements are distributed only as copy-in source through a shadcn registry — there is no npm
9
+ package to depend on — so vendoring is the intended use, and the licence below is the whole
10
+ obligation it carries.
11
+
12
+ ```
13
+ MIT License
14
+
15
+ Copyright (c) 2025 AgentbaseAI Inc.
16
+
17
+ Permission is hereby granted, free of charge, to any person obtaining a copy
18
+ of this software and associated documentation files (the "Software"), to deal
19
+ in the Software without restriction, including without limitation the rights
20
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
21
+ copies of the Software, and to permit persons to whom the Software is
22
+ furnished to do so, subject to the following conditions:
23
+
24
+ The above copyright notice and this permission notice shall be included in all
25
+ copies or substantial portions of the Software.
26
+
27
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
28
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
29
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
30
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
31
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
32
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
33
+ SOFTWARE.
34
+ ```
package/README.md CHANGED
@@ -5,25 +5,8 @@ Base UI underneath for behaviour and accessibility, Tailwind v4 on top for the p
5
5
 
6
6
  ## Install
7
7
 
8
- The `@cueplusplus` scope is served by **GitHub Packages**, not npmjs.com, and GitHub Packages
9
- authenticates *every* install. That is two settings, in two places, and the split is not
10
- cosmetic — pnpm ignores an env-expanded credential in a project `.npmrc` and the install fails
11
- with `401`.
12
-
13
- Commit the scope routing, and nothing else, at the root of your project:
14
-
15
- ```ini
16
- # .npmrc
17
- @cueplusplus:registry=https://npm.pkg.github.com
18
- ```
19
-
20
- Then write the credential once, at the **user** level, where pnpm reads it from. It is a
21
- **classic** personal access token with `read:packages` — GitHub Packages accepts neither
22
- fine-grained PATs nor OIDC:
23
-
24
- ```sh
25
- pnpm config set //npm.pkg.github.com/:_authToken ghp_…
26
- ```
8
+ The `@cueplusplus` scope is **public on npm** and resolves there by default, so there is nothing
9
+ to configure and no credential to supply — it installs like any other package.
27
10
 
28
11
  ```sh
29
12
  pnpm add @cueplusplus/ui @cueplusplus/tokens @cueplusplus/theme-cue @base-ui/react
@@ -165,7 +165,7 @@ const ToolCallCard = React.forwardRef(function ToolCallCard({ className, tool, a
165
165
  children: argsLabel
166
166
  }), /* @__PURE__ */ jsx("pre", {
167
167
  "data-slot": "tool-call-card-args",
168
- className: "m-0 min-w-0 overflow-x-auto font-mono text-(length:--cue-text-micro) leading-relaxed break-words whitespace-pre-wrap text-fg-muted",
168
+ className: "m-0 min-w-0 overflow-x-auto font-mono text-(length:--cue-text-micro) leading-(--cue-leading-ui) break-words whitespace-pre-wrap text-fg-muted",
169
169
  children: args
170
170
  })] }) : null,
171
171
  hasResult ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("span", {
@@ -174,7 +174,7 @@ const ToolCallCard = React.forwardRef(function ToolCallCard({ className, tool, a
174
174
  children: resultLabel
175
175
  }), /* @__PURE__ */ jsx("div", {
176
176
  "data-slot": "tool-call-card-result",
177
- className: "min-w-0 font-mono text-(length:--cue-text-micro) leading-relaxed break-words whitespace-pre-wrap text-fg",
177
+ className: "min-w-0 font-mono text-(length:--cue-text-micro) leading-(--cue-leading-ui) break-words whitespace-pre-wrap text-fg",
178
178
  children: result
179
179
  })] }) : null,
180
180
  children
@@ -154,7 +154,7 @@ const AskBox = React.forwardRef(function AskBox({ className, question, kind = "t
154
154
  className: "mt-(--cue-space-3) flex flex-col gap-(--cue-space-2) border-t border-border pt-(--cue-space-3)",
155
155
  children: [
156
156
  /* @__PURE__ */ jsx("p", {
157
- className: "text-(length:--cue-text-ui) leading-relaxed break-words whitespace-pre-wrap text-fg-muted",
157
+ className: "text-(length:--cue-text-ui) leading-(--cue-leading-ui) break-words whitespace-pre-wrap text-fg-muted",
158
158
  children: question
159
159
  }),
160
160
  /* @__PURE__ */ jsx("p", {
@@ -326,7 +326,7 @@ const AskBox = React.forwardRef(function AskBox({ className, question, kind = "t
326
326
  /* @__PURE__ */ jsx("p", {
327
327
  id: questionId,
328
328
  "data-slot": "ask-box-question",
329
- className: "min-w-0 text-(length:--cue-text-body) leading-relaxed break-words whitespace-pre-wrap text-fg",
329
+ className: "min-w-0 text-(length:--cue-text-body) leading-(--cue-leading-ui) break-words whitespace-pre-wrap text-fg",
330
330
  children: question
331
331
  }),
332
332
  /* @__PURE__ */ jsx("div", {
@@ -104,7 +104,7 @@ const Composer = React.forwardRef(function Composer({ className, onSend, value:
104
104
  placeholder,
105
105
  disabled,
106
106
  value,
107
- className: cn(bareControlClasses, "min-h-control-lg resize-none self-stretch py-(--cue-space-2) text-(length:--cue-text-body) leading-relaxed"),
107
+ className: cn(bareControlClasses, "min-h-control-lg resize-none self-stretch py-(--cue-space-2) text-(length:--cue-text-body) leading-(--cue-leading-ui)"),
108
108
  onChange: (event) => setValue(event.target.value),
109
109
  onKeyDown
110
110
  }),
@@ -85,7 +85,7 @@ const Message = React.forwardRef(function Message({ className, role = "agent", a
85
85
  }) : null,
86
86
  /* @__PURE__ */ jsxs("div", {
87
87
  "data-slot": "message-body",
88
- className: "relative min-w-0 text-(length:--cue-text-body) leading-relaxed break-words whitespace-pre-wrap",
88
+ className: "relative min-w-0 text-(length:--cue-text-body) leading-(--cue-leading-ui) break-words whitespace-pre-wrap",
89
89
  children: [children, pending ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("span", {
90
90
  "data-slot": "message-caret",
91
91
  "aria-hidden": "true",
@@ -0,0 +1,54 @@
1
+ import { cn } from "../lib/cn.js";
2
+ //#region src/chrome/_band.ts
3
+ /**
4
+ * The rule a band draws at its top edge.
5
+ *
6
+ * Spelt as `border-t-(length:--cue-band-rule)` and not as
7
+ * `border-t-(--cue-band-rule)`. Both compile. The second sets
8
+ * `border-top-color`, which would give every band a 1px rule in the token's own
9
+ * text as a colour — a rule that is always drawn and never right. The `length:`
10
+ * hint is what makes Tailwind emit `border-top-width`. It does not carry
11
+ * `border-border` — the element that spends this adds that itself, so both
12
+ * `Band` and `Footer` say in their own class list what colours their rule,
13
+ * rather than one of the two inheriting it silently from the other.
14
+ */
15
+ const RULE = "border-t-(length:--cue-band-rule)";
16
+ /**
17
+ * The band recipe as class strings, for the one other element in this library
18
+ * that is a band and cannot be a `<section>`.
19
+ *
20
+ * `Footer` is the `contentinfo` landmark: it has to render a `<footer>`, and
21
+ * this library has exactly one polymorphic escape hatch (`ThemeProvider`'s
22
+ * `asChild`) whose own documentation calls it the one place. So rather than
23
+ * give `Band` a second one, or let `Footer` keep a second copy of the recipe
24
+ * — which is the thing spec Decision 4 refuses by name — the strings live here
25
+ * and both elements spend them.
26
+ *
27
+ * It lives in an underscore-prefixed chassis file rather than in `band.tsx` on
28
+ * purpose: `packages/docgen`'s token scanner only follows a component's imports
29
+ * into files whose basename starts with `_`, and `Footer` spends this recipe
30
+ * without rendering `<Band>` itself. Keeping the strings on `band.tsx` left
31
+ * `footer.json`'s published `tokensUsed` silently missing the two tokens this
32
+ * function spends — the rhythm and the rule — because the scanner had no reason
33
+ * to open a public component file it was not asked to document. This file is
34
+ * that reason.
35
+ *
36
+ * **Exactly those two names live here, and that is the second half of the same
37
+ * mechanism.** The scanner reads a chassis file whole; it does not know which
38
+ * branch a call takes, so every `--cue-*` written in this file is published as
39
+ * a token *both* elements render with. `Footer` calls this with the literal
40
+ * `"rule"` and types its own `width` as `ContainerWidth`, so `Band`'s other two
41
+ * spends — `bg-(--cue-band-ground)` for `separation="ground"` and
42
+ * `max-w-(--cue-measure-prose)` for `width="prose"` — are unreachable from a
43
+ * `<footer>` and are written in `band.tsx`, beside the prop that selects them.
44
+ * Moving them here would make `footer.json` claim two tokens the component
45
+ * cannot paint, which is the same defect as the omission this file was written
46
+ * to fix, pointing the other way.
47
+ *
48
+ * It is not exported from the package. A caller who wants a band uses `Band`.
49
+ */
50
+ function bandClasses(separation) {
51
+ return cn("w-full py-(--cue-band-y)", separation === "rule" ? RULE : null);
52
+ }
53
+ //#endregion
54
+ export { bandClasses };
@@ -0,0 +1,106 @@
1
+ import { ContainerWidth } from "../layout/container.js";
2
+ import * as React from "react";
3
+ //#region src/chrome/band.d.ts
4
+ /** How a band separates itself from the section above it. */
5
+ type BandSeparation = "rule" | "ground" | "bleed" | "none";
6
+ /**
7
+ * Which measure a band's column takes: `Container`'s four fixed rungs, plus
8
+ * `"prose"` — the reading measure a style set owns.
9
+ *
10
+ * `"prose"` is the default and is the only one of the five that moves with
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
13
+ * names one has opted out of the axis for its measure — which is the right
14
+ * answer for a band holding a `Bento` or a device frame, and the wrong one for
15
+ * a band holding a paragraph.
16
+ */
17
+ type BandWidth = ContainerWidth | "prose";
18
+ interface BandProps extends React.ComponentPropsWithoutRef<"section"> {
19
+ /**
20
+ * How this band separates itself from the one above it. Defaults to `"rule"`.
21
+ *
22
+ * - **`"rule"`** — a line at the top edge, `--cue-band-rule` wide, in
23
+ * `border-border`. What `Footer` has always drawn.
24
+ * - **`"ground"`** — a ground, `--cue-band-ground`, edge to edge. The one
25
+ * value that touches colour, and it resolves through the single carve-out
26
+ * the token layer allows a style set.
27
+ * - **`"bleed"`** — neither, and **no column**: the children run the band's
28
+ * full width with no measure and no gutters. The separation is the change
29
+ * of scale, which is what a full-width image or strip does. `width` has
30
+ * nothing to apply to and is ignored.
31
+ * - **`"none"`** — neither, column kept. Sections separate by rhythm alone,
32
+ * which is `--cue-band-y` and is what `editorial` leads with.
33
+ *
34
+ * **What a style set makes each of these do, because two of them can come out
35
+ * to nothing and there is no way for this component to warn you.** The values
36
+ * are the token layer's; `packages/ui/test/chrome/band.test.tsx` holds this
37
+ * table to `packages/tokens/dist/axes.css`, so it cannot quietly stop being
38
+ * true.
39
+ *
40
+ * | set | `"rule"` draws | `"ground"` paints |
41
+ * |---|---|---|
42
+ * | *(no set)* and `console` | 1px | nothing — the ground is `transparent` |
43
+ * | `editorial` | a 0.5px hairline, **which Chromium paints at 1px at every DPR**; only retina WebKit draws it thinner | nothing — `transparent` |
44
+ * | `marketing` | **nothing — the rule is `0px`** | `--cue-surface-1` |
45
+ *
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.
49
+ */
50
+ separation?: BandSeparation;
51
+ /** Which measure the band's centred column takes. Defaults to `"prose"`. */
52
+ width?: BandWidth;
53
+ /** Extra classes for the centred column. Ignored when `separation` is `"bleed"`. */
54
+ columnClassName?: string;
55
+ /** The band's contents. */
56
+ children?: React.ReactNode;
57
+ }
58
+ /**
59
+ * A full-bleed horizontal section: the page's rhythm, its separation, and a
60
+ * column at the measure.
61
+ *
62
+ * This is `Footer`'s recipe with the footer taken out of it — a `w-full`
63
+ * element, a rule running edge to edge, and a centred `Container` inside so the
64
+ * line reaches the window while the words stop at the measure. `Footer` is
65
+ * built on this rather than beside it; the recipe exists once.
66
+ *
67
+ * Every dimension it spends belongs to the style axis, so the same markup
68
+ * composes differently under `[data-style]` without a prop changing: the
69
+ * vertical rhythm is `--cue-band-y` (one `--cue-space-7` with no set, doubled
70
+ * under `editorial`, trebled under `marketing`), the column is
71
+ * `--cue-measure-prose` unless `width` names a fixed rung, and the rule and the
72
+ * ground are `--cue-band-rule` and `--cue-band-ground`. Read `separation`'s own
73
+ * documentation before choosing one, because two of the four can come out to
74
+ * 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.
78
+ *
79
+ * **Two substitution boundaries, because `--cue-band-y` is a `calc()` resolved
80
+ * at the element that declares it.** A `<Density>` island nested inside a
81
+ * styled page moves every `--cue-space-*` and the band rhythm does **not**
82
+ * follow it — the island inherits the rhythm already resolved above. Restate
83
+ * 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`.
87
+ *
88
+ * It renders a `<section>`, which is not a landmark until it has an accessible
89
+ * name — so a band with a heading should carry `aria-labelledby` pointing at
90
+ * it, and a band without one costs the document nothing.
91
+ *
92
+ * Static markup — no `"use client"`.
93
+ *
94
+ * @example
95
+ * <Band aria-labelledby="pitch">
96
+ * <h2 id="pitch">One import</h2>
97
+ * <p>Everything on one token layer.</p>
98
+ * </Band>
99
+ * @example
100
+ * <Band separation="ground" width="broad">
101
+ * <Bento.Root cols={3}>{tiles}</Bento.Root>
102
+ * </Band>
103
+ */
104
+ declare const Band: React.ForwardRefExoticComponent<BandProps & React.RefAttributes<HTMLElement>>;
105
+ //#endregion
106
+ export { Band, BandProps, BandSeparation, BandWidth };