@cueplusplus/ui 0.18.2 → 0.19.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 (136) hide show
  1. package/CHANGELOG.md +61 -0
  2. package/dist/brand/_motif-seed.js +20 -0
  3. package/dist/brand/gloss-object.d.ts +23 -0
  4. package/dist/brand/gloss-object.js +108 -0
  5. package/dist/brand/halftone.d.ts +23 -0
  6. package/dist/brand/halftone.js +54 -0
  7. package/dist/brand/index.d.ts +6 -1
  8. package/dist/brand/motif.d.ts +32 -0
  9. package/dist/brand/motif.js +71 -0
  10. package/dist/brand/particle-mark.d.ts +29 -0
  11. package/dist/brand/particle-mark.js +137 -0
  12. package/dist/brand/ribbon.d.ts +20 -0
  13. package/dist/brand/ribbon.js +54 -0
  14. package/dist/chrome/announcement-bar.d.ts +30 -0
  15. package/dist/chrome/announcement-bar.js +38 -0
  16. package/dist/chrome/app-bar.d.ts +4 -1
  17. package/dist/chrome/app-bar.js +7 -2
  18. package/dist/chrome/app-shell.js +8 -1
  19. package/dist/chrome/band.d.ts +3 -1
  20. package/dist/chrome/band.js +4 -3
  21. package/dist/chrome/hero.d.ts +61 -0
  22. package/dist/chrome/hero.js +108 -0
  23. package/dist/chrome/index.d.ts +6 -1
  24. package/dist/chrome/index.js +6 -1
  25. package/dist/chrome/keyword.d.ts +22 -0
  26. package/dist/chrome/keyword.js +28 -0
  27. package/dist/chrome/logo-strip.d.ts +23 -0
  28. package/dist/chrome/logo-strip.js +43 -0
  29. package/dist/chrome/page-shell.js +13 -1
  30. package/dist/chrome/stat-band.d.ts +32 -0
  31. package/dist/chrome/stat-band.js +39 -0
  32. package/dist/dmx/channel-matrix.js +5 -3
  33. package/dist/dmx/dmx-strip.js +5 -3
  34. package/dist/elements/animated-number.js +4 -1
  35. package/dist/elements/replay.d.ts +1 -1
  36. package/dist/elements/replay.js +5 -2
  37. package/dist/elements/scroll-anchor.js +4 -1
  38. package/dist/index.d.ts +13 -1
  39. package/dist/index.js +14 -2
  40. package/dist/instruments/index.js +1 -1
  41. package/dist/instruments/stat.js +1 -1
  42. package/dist/instruments/terminal-frame.js +5 -2
  43. package/dist/layout/grid.js +4 -2
  44. package/dist/layout/preview.js +4 -188
  45. package/dist/layout/sidebar.js +88 -52
  46. package/dist/overlays/_surface.d.ts +2 -2
  47. package/dist/primitives/button.js +22 -3
  48. package/dist/primitives/chip.js +62 -6
  49. package/dist/styles.css +26 -0
  50. package/dist/system/_scoped-pairing.js +18 -0
  51. package/dist/system/_stage-scope.js +199 -0
  52. package/dist/system/_style-check.js +1 -1
  53. package/dist/system/_style-chip.js +1 -1
  54. package/dist/system/_style-group-label.js +7 -3
  55. package/dist/system/_style-hero-title.js +41 -0
  56. package/dist/system/_style-kbd.js +1 -1
  57. package/dist/system/_style-label-ink.js +12 -5
  58. package/dist/system/_style-menu.js +1 -1
  59. package/dist/system/_style-page-title.js +1 -1
  60. package/dist/system/_style-segmented-control.js +1 -1
  61. package/dist/system/_style-skeleton.js +1 -1
  62. package/dist/system/_style-tab.js +1 -1
  63. package/dist/system/font-scope.d.ts +38 -0
  64. package/dist/system/font-scope.js +69 -0
  65. package/dist/system/index.d.ts +3 -1
  66. package/dist/system/index.js +3 -1
  67. package/dist/system/portal.js +7 -1
  68. package/dist/system/still.d.ts +32 -0
  69. package/dist/system/still.js +47 -0
  70. package/manifest/components/alert-dialog.json +1 -1
  71. package/manifest/components/announcement-bar.json +82 -0
  72. package/manifest/components/app-bar.json +3 -2
  73. package/manifest/components/app-shell.json +3 -0
  74. package/manifest/components/autocomplete.json +1 -0
  75. package/manifest/components/band.json +2 -1
  76. package/manifest/components/bento.json +12 -12
  77. package/manifest/components/button.json +1 -0
  78. package/manifest/components/channel-matrix.json +1 -0
  79. package/manifest/components/chart-tooltip-content.json +1 -0
  80. package/manifest/components/checkbox-group.json +1 -1
  81. package/manifest/components/checkbox.json +1 -1
  82. package/manifest/components/chip.json +1 -0
  83. package/manifest/components/combobox.json +1 -0
  84. package/manifest/components/command-palette.json +1 -0
  85. package/manifest/components/context-menu.json +1 -1
  86. package/manifest/components/density.json +6 -2
  87. package/manifest/components/dialog.json +1 -1
  88. package/manifest/components/dmx-bar.json +1 -1
  89. package/manifest/components/dmx-strip.json +1 -1
  90. package/manifest/components/drawer.json +1 -1
  91. package/manifest/components/dropdown-menu.json +1 -0
  92. package/manifest/components/font-scope.json +81 -0
  93. package/manifest/components/footer.json +0 -1
  94. package/manifest/components/gloss-object.json +81 -0
  95. package/manifest/components/grid.json +6 -6
  96. package/manifest/components/halftone.json +79 -0
  97. package/manifest/components/hero.json +204 -0
  98. package/manifest/components/hover-card.json +1 -1
  99. package/manifest/components/kbd.json +1 -0
  100. package/manifest/components/keyword.json +67 -0
  101. package/manifest/components/ledger.json +4 -4
  102. package/manifest/components/logo-strip.json +93 -0
  103. package/manifest/components/markdown-text.json +2 -2
  104. package/manifest/components/menubar.json +1 -1
  105. package/manifest/components/motif.json +90 -0
  106. package/manifest/components/multi-select.json +1 -0
  107. package/manifest/components/navigation-menu.json +1 -0
  108. package/manifest/components/page-shell.json +5 -0
  109. package/manifest/components/particle-mark.json +75 -0
  110. package/manifest/components/popover.json +1 -1
  111. package/manifest/components/preview.json +9 -4
  112. package/manifest/components/radio-group.json +0 -1
  113. package/manifest/components/radio.json +0 -1
  114. package/manifest/components/ribbon.json +65 -0
  115. package/manifest/components/scrollable-tabs-list.json +1 -0
  116. package/manifest/components/segmented-control.json +1 -0
  117. package/manifest/components/sheet.json +1 -1
  118. package/manifest/components/sidebar.json +1 -0
  119. package/manifest/components/skeleton.json +1 -0
  120. package/manifest/components/stack.json +4 -4
  121. package/manifest/components/stat-band.json +68 -0
  122. package/manifest/components/stat.json +1 -1
  123. package/manifest/components/still-provider.json +60 -0
  124. package/manifest/components/switch.json +0 -1
  125. package/manifest/components/table.json +1 -1
  126. package/manifest/components/tabs.json +1 -0
  127. package/manifest/components/tags-input.json +1 -0
  128. package/manifest/components/theme-configurator.json +1 -0
  129. package/manifest/components/theme-provider.json +9 -4
  130. package/manifest/components/toast.json +1 -0
  131. package/manifest/components/tooltip.json +1 -1
  132. package/manifest/fixtures.json +18 -0
  133. package/manifest/manifest.json +267 -55
  134. package/manifest/tokens.json +91 -3
  135. package/package.json +4 -4
  136. package/dist/system/_paint-ground-pattern.js +0 -30
@@ -134,6 +134,7 @@
134
134
  "--cue-style-chip-radius",
135
135
  "--cue-style-chip-size",
136
136
  "--cue-style-chip-tracking",
137
+ "--cue-style-control-radius",
137
138
  "--cue-style-focus-width",
138
139
  "--cue-style-label-case",
139
140
  "--cue-style-label-face",
@@ -271,6 +271,7 @@
271
271
  "--cue-style-chip-size",
272
272
  "--cue-style-chip-tracking",
273
273
  "--cue-style-control-face",
274
+ "--cue-style-control-radius",
274
275
  "--cue-style-control-step-size",
275
276
  "--cue-style-disabled-edge",
276
277
  "--cue-style-disabled-fill",
@@ -187,6 +187,7 @@
187
187
  "--cue-style-body-size",
188
188
  "--cue-style-body-weight",
189
189
  "--cue-style-control-face",
190
+ "--cue-style-control-radius",
190
191
  "--cue-style-control-step-size",
191
192
  "--cue-style-dialog-radius",
192
193
  "--cue-style-display-variation",
@@ -92,7 +92,6 @@
92
92
  "--cue-control-sm",
93
93
  "--cue-fg",
94
94
  "--cue-fg-muted",
95
- "--cue-fg-subtle",
96
95
  "--cue-font-mono",
97
96
  "--cue-leading-ui",
98
97
  "--cue-paint-rim-width",
@@ -119,6 +118,7 @@
119
118
  "--cue-style-body-size",
120
119
  "--cue-style-body-weight",
121
120
  "--cue-style-control-face",
121
+ "--cue-style-control-radius",
122
122
  "--cue-style-display-variation",
123
123
  "--cue-style-group-label-ink",
124
124
  "--cue-style-group-label-pad",
@@ -48,13 +48,14 @@
48
48
  },
49
49
  {
50
50
  "name": "styleSet",
51
- "type": "\"console\" | \"editorial\" | \"marketing\" | \"graphite\" | \"tender\" | \"zine\" | \"kiln\" | \"porcelain\"",
51
+ "type": "\"command\" | \"console\" | \"editorial\" | \"marketing\" | \"graphite\" | \"tender\" | \"zine\" | \"kiln\" | \"porcelain\" | \"ledger\" | \"monolith\" | \"prism\"",
52
52
  "required": false,
53
53
  "defaultValue": null,
54
54
  "description": "A style set for this subtree: `console`, `editorial`, `marketing` or\n`graphite`.\n\nOptional, and **absent means inherit** — an island that names none stamps no\n`data-style` and passes the ambient set straight through, exactly as a bare\n`<Density>` does today. Naming one is what makes this the library's island\nform of the fourth axis, and there are two reasons to reach for it:\n\n- `console` inside a page that is not console. That is the whole job of the\n default set: it restates the `:root` defaults, so a subtree stamped with\n it renders the ordinary look inside a page under any other set.\n- Moving the band rhythm with the rung. `--cue-band-y` is\n `calc(var(--cue-space-7) * 2)` declared on the `[data-style]` element, and\n a custom property's `var()` references are substituted where they are\n declared — so a nested density island moves `--cue-space-*` but inherits\n the rhythm already resolved above it. Restating the set here re-resolves\n it against this island's rung, which is how a denser island gets a\n proportionally tighter band instead of the outer one's.\n\nThe library restates the set for you where an island changes what a set's\nvalues read besides the rung — the theme's inks, the pairing's faces: a\nnested `ThemeProvider` that names a theme or a mode, and a `Preview` stage\nwith a theme, a mode or a pairing, stamp the set and the pack in force\nbeside it. This island changes only the rung, so it does not, and the\nrhythm above stays the opt-in the second bullet describes.",
55
55
  "control": {
56
56
  "kind": "enum",
57
57
  "members": [
58
+ "command",
58
59
  "console",
59
60
  "editorial",
60
61
  "marketing",
@@ -62,7 +63,10 @@
62
63
  "tender",
63
64
  "zine",
64
65
  "kiln",
65
- "porcelain"
66
+ "porcelain",
67
+ "ledger",
68
+ "monolith",
69
+ "prism"
66
70
  ]
67
71
  }
68
72
  },
@@ -166,7 +166,6 @@
166
166
  "--cue-control-sm",
167
167
  "--cue-fg",
168
168
  "--cue-fg-muted",
169
- "--cue-fg-subtle",
170
169
  "--cue-font-mono",
171
170
  "--cue-leading-ui",
172
171
  "--cue-paint-rim-width",
@@ -195,6 +194,7 @@
195
194
  "--cue-style-body-size",
196
195
  "--cue-style-body-weight",
197
196
  "--cue-style-control-face",
197
+ "--cue-style-control-radius",
198
198
  "--cue-style-dialog-pad",
199
199
  "--cue-style-dialog-radius",
200
200
  "--cue-style-display-variation",
@@ -64,7 +64,6 @@
64
64
  "--cue-data-ground",
65
65
  "--cue-fg",
66
66
  "--cue-fg-muted",
67
- "--cue-fg-subtle",
68
67
  "--cue-font-mono",
69
68
  "--cue-leading-ui",
70
69
  "--cue-paint-rim-width",
@@ -91,6 +90,7 @@
91
90
  "--cue-style-body-size",
92
91
  "--cue-style-body-weight",
93
92
  "--cue-style-control-face",
93
+ "--cue-style-control-radius",
94
94
  "--cue-style-display-variation",
95
95
  "--cue-style-group-label-ink",
96
96
  "--cue-style-group-label-pad",
@@ -74,7 +74,6 @@
74
74
  "--cue-data-ground",
75
75
  "--cue-fg",
76
76
  "--cue-fg-muted",
77
- "--cue-fg-subtle",
78
77
  "--cue-font-mono",
79
78
  "--cue-leading-ui",
80
79
  "--cue-paint-rim-width",
@@ -101,6 +100,7 @@
101
100
  "--cue-style-body-size",
102
101
  "--cue-style-body-weight",
103
102
  "--cue-style-control-face",
103
+ "--cue-style-control-radius",
104
104
  "--cue-style-display-variation",
105
105
  "--cue-style-group-label-ink",
106
106
  "--cue-style-group-label-pad",
@@ -160,7 +160,6 @@
160
160
  "--cue-control-sm",
161
161
  "--cue-fg",
162
162
  "--cue-fg-muted",
163
- "--cue-fg-subtle",
164
163
  "--cue-font-mono",
165
164
  "--cue-leading-ui",
166
165
  "--cue-paint-rim-width",
@@ -189,6 +188,7 @@
189
188
  "--cue-style-body-size",
190
189
  "--cue-style-body-weight",
191
190
  "--cue-style-control-face",
191
+ "--cue-style-control-radius",
192
192
  "--cue-style-dialog-radius",
193
193
  "--cue-style-display-variation",
194
194
  "--cue-style-group-label-ink",
@@ -248,6 +248,7 @@
248
248
  "--cue-style-body-size",
249
249
  "--cue-style-body-weight",
250
250
  "--cue-style-control-face",
251
+ "--cue-style-control-radius",
251
252
  "--cue-style-display-variation",
252
253
  "--cue-style-group-label-ink",
253
254
  "--cue-style-group-label-pad",
@@ -0,0 +1,81 @@
1
+ {
2
+ "name": "FontScope",
3
+ "slug": "font-scope",
4
+ "group": "system",
5
+ "importPath": "@cueplusplus/ui",
6
+ "peerDependencies": [],
7
+ "clientOnly": true,
8
+ "description": "A subtree set in another type pairing — and everything it opens with it.\n\n`ThemeProvider`'s `font` is root-level only: the pairing has no island, and a\nnested provider forwards it to the root. `data-font` on a `<div>` is enough\nfor the subtree's own tokens, and nothing more: a dialog or menu opened inside\nit mounts on `<body>`, stamped from the root's pairing, and unclassed text\nkeeps the family `<body>` computed, because a computed family does not follow\na token. `FontScope` does all three: it stamps `data-font`, asks for the\nfamily again on its own element, and republishes the pairing so every portal\nopened inside it is stamped with it and asks for the family too. It is what\n`Preview` does for a stage that names a pairing, as a component of its own.\n\nIt never calls `setFont`, so the root's pairing — and the visitor's stored\none — never moves. A gallery frame that draws a page in a Look of its own is\nthe case it exists for (structural Looks, spec 2026-10-02 §6.2).\n\nThe set and pack in force around it are restated beside `data-font`, once it\nmay restate, because their names read the pairing and a custom property's\n`var()`s are substituted where it is declared.",
9
+ "props": [
10
+ {
11
+ "name": "font",
12
+ "type": "\"source\" | \"system\" | \"geist\" | \"geist-mono\" | \"inter\" | \"plex\" | \"roboto\" | \"apple\" | \"office\" | \"inter-source\" | \"dm\" | \"calsans\" | \"fraunces-mono\"",
13
+ "required": true,
14
+ "defaultValue": null,
15
+ "description": "The pairing this subtree is set in.",
16
+ "control": {
17
+ "kind": "enum",
18
+ "members": [
19
+ "source",
20
+ "system",
21
+ "geist",
22
+ "geist-mono",
23
+ "inter",
24
+ "plex",
25
+ "roboto",
26
+ "apple",
27
+ "office",
28
+ "inter-source",
29
+ "dm",
30
+ "calsans",
31
+ "fraunces-mono"
32
+ ]
33
+ }
34
+ },
35
+ {
36
+ "name": "children",
37
+ "type": "ReactNode",
38
+ "required": true,
39
+ "defaultValue": null,
40
+ "description": "What is set in it. Every overlay opened inside it is set in it too.",
41
+ "control": {
42
+ "kind": "node",
43
+ "fixture": "children.text"
44
+ }
45
+ }
46
+ ],
47
+ "typeReferences": [
48
+ "Omit<React.ComponentPropsWithoutRef<\"div\">, \"children\">"
49
+ ],
50
+ "subcomponents": [],
51
+ "parts": [],
52
+ "variants": {},
53
+ "defaultVariants": {},
54
+ "tokensUsed": [
55
+ "--cue-font-sans"
56
+ ],
57
+ "summary": "A subtree set in another type pairing, and every dialog or menu it opens with it, without moving the root's.",
58
+ "examples": [
59
+ {
60
+ "title": "Usage",
61
+ "code": "<FontScope font=\"inter-source\">\n <Dialog.Root>…</Dialog.Root>\n</FontScope>",
62
+ "language": "tsx"
63
+ }
64
+ ],
65
+ "status": "stable",
66
+ "url": "/docs/components/font-scope",
67
+ "mdUrl": "/docs/components/font-scope.md",
68
+ "jsonUrl": "/r/components/font-scope.json",
69
+ "whenToUse": [
70
+ "A frame or specimen that draws a page in a Look of its own, where the pairing has to reach its overlays too.",
71
+ "A picker row or a comparison that shows one pairing beside the page's."
72
+ ],
73
+ "whenNotToUse": [
74
+ "Changing the page's own pairing. That is `ThemeProvider`'s `font`, at the root, or its `setFont`.",
75
+ "A heading in another face. A class on the element is enough; a scope re-sets everything under it."
76
+ ],
77
+ "commonMistakes": [
78
+ "Stamping `data-font` on a `<div>` and expecting a dialog opened inside it to follow. The dialog mounts on `<body>`; only the scope carries the pairing to it.",
79
+ "Passing `font` to a nested `ThemeProvider`. The pairing is root-level there, and a nested provider forwards it to the root."
80
+ ]
81
+ }
@@ -69,7 +69,6 @@
69
69
  "--cue-band-y",
70
70
  "--cue-border",
71
71
  "--cue-fg-muted",
72
- "--cue-fg-subtle",
73
72
  "--cue-font-mono",
74
73
  "--cue-space-3",
75
74
  "--cue-space-5",
@@ -0,0 +1,81 @@
1
+ {
2
+ "name": "GlossObject",
3
+ "slug": "gloss-object",
4
+ "group": "brand",
5
+ "importPath": "@cueplusplus/ui",
6
+ "peerDependencies": [],
7
+ "clientOnly": false,
8
+ "description": "A glossy, iridescent object for a marketing hero — the chrome-ring and gloss\nlettermark look (spec 2026-10-02 §3.4). Drawn with layered radial and linear\ngradients of the theme's accent against the foreground's mix, plus a specular\nhighlight in the accent's own ink (`--cue-accent-fg`), so it is the Look's own colour and never a copied render.\nDecorative: hidden from assistive technology.\n\nStatic markup — no `\"use client\"`.",
9
+ "props": [
10
+ {
11
+ "name": "shape",
12
+ "type": "\"mark\" | \"torus\" | \"knot\"",
13
+ "required": false,
14
+ "defaultValue": "torus",
15
+ "description": "The object: a ring, a knot of two rings, or a rounded mark. Defaults to `\"torus\"`.",
16
+ "control": {
17
+ "kind": "enum",
18
+ "members": [
19
+ "mark",
20
+ "torus",
21
+ "knot"
22
+ ]
23
+ }
24
+ },
25
+ {
26
+ "name": "seed",
27
+ "type": "number",
28
+ "required": false,
29
+ "defaultValue": "1",
30
+ "description": "Tilts the highlight. Defaults to `1`.",
31
+ "control": {
32
+ "kind": "number"
33
+ }
34
+ }
35
+ ],
36
+ "typeReferences": [
37
+ "React.SVGProps<SVGSVGElement>"
38
+ ],
39
+ "subcomponents": [],
40
+ "parts": [],
41
+ "variants": {},
42
+ "defaultVariants": {},
43
+ "tokensUsed": [
44
+ "--cue-accent",
45
+ "--cue-accent-fg",
46
+ "--cue-fg"
47
+ ],
48
+ "summary": "A glossy, iridescent object — a ring, two rings or a rounded mark — in the theme's accent.",
49
+ "examples": [
50
+ {
51
+ "title": "Usage",
52
+ "code": "<GlossObject shape=\"knot\" className=\"h-48 w-48\" />",
53
+ "language": "tsx"
54
+ }
55
+ ],
56
+ "status": "stable",
57
+ "url": "/docs/components/gloss-object",
58
+ "mdUrl": "/docs/components/gloss-object.md",
59
+ "jsonUrl": "/r/components/gloss-object.json",
60
+ "whenToUse": [
61
+ "A marketing hero's centrepiece, or art between sections."
62
+ ],
63
+ "whenNotToUse": [
64
+ "Icons or small UI marks. It is a hero-scale decoration."
65
+ ],
66
+ "commonMistakes": [
67
+ "Expecting a 3D render. It is layered gradients, drawn in the Look's own colour."
68
+ ],
69
+ "specimens": [
70
+ {
71
+ "title": "GlossObject",
72
+ "group": "brand",
73
+ "components": [
74
+ "GlossObject"
75
+ ],
76
+ "code": "<Specimens>\n {([\"torus\", \"knot\", \"mark\"] as const).map((shape) => (\n <Specimen key={shape} label={shape}>\n <GlossObject shape={shape} className=\"size-40\" />\n </Specimen>\n ))}\n</Specimens>",
77
+ "note": "A glossy object of layered gradients over an authored outline, lit in the accent.",
78
+ "interaction": "none."
79
+ }
80
+ ]
81
+ }
@@ -9,17 +9,17 @@
9
9
  "props": [
10
10
  {
11
11
  "name": "cols",
12
- "type": "4 | 1 | 2 | 3 | 5 | 6",
12
+ "type": "1 | 4 | 2 | 3 | 5 | 6",
13
13
  "required": false,
14
14
  "defaultValue": "1",
15
15
  "description": "How many equal columns. Defaults to `1`. Ignored when `minItemWidth` is set.",
16
16
  "control": {
17
17
  "kind": "enum",
18
18
  "members": [
19
- 4,
20
19
  1,
21
20
  2,
22
21
  3,
22
+ 4,
23
23
  5,
24
24
  6
25
25
  ],
@@ -29,7 +29,7 @@
29
29
  },
30
30
  {
31
31
  "name": "gap",
32
- "type": "0 | 4 | 8 | 1 | 2 | 3 | 5 | 6 | 7",
32
+ "type": "0 | 1 | 4 | 8 | 2 | 3 | 5 | 6 | 7",
33
33
  "required": false,
34
34
  "defaultValue": "4",
35
35
  "description": "Which rung of the density space ladder to spend between cells. Defaults to `4`.",
@@ -37,14 +37,14 @@
37
37
  "kind": "enum",
38
38
  "members": [
39
39
  0,
40
- 4,
41
- 8,
42
40
  1,
43
41
  2,
44
42
  3,
43
+ 4,
45
44
  5,
46
45
  6,
47
- 7
46
+ 7,
47
+ 8
48
48
  ],
49
49
  "min": 0,
50
50
  "max": 8
@@ -0,0 +1,79 @@
1
+ {
2
+ "name": "Halftone",
3
+ "slug": "halftone",
4
+ "group": "brand",
5
+ "importPath": "@cueplusplus/ui",
6
+ "peerDependencies": [],
7
+ "clientOnly": false,
8
+ "description": "A halftone dot screen over a generated form — the engraved, printed look of a\ndeveloper-tool landing page (spec 2026-10-02 §3.4). Every dot's size is the\nform's density at that cell, so the picture is drawn by the screen itself\nrather than filtered from an image, and nothing is fetched. Dots are the\nforeground ink. Decorative: hidden from assistive technology.\n\nStatic markup — no `\"use client\"`.",
9
+ "props": [
10
+ {
11
+ "name": "shape",
12
+ "type": "\"wave\" | \"orb\" | \"ridge\"",
13
+ "required": false,
14
+ "defaultValue": "ridge",
15
+ "description": "The generated form the dots describe. Defaults to `\"ridge\"`.",
16
+ "control": {
17
+ "kind": "enum",
18
+ "members": [
19
+ "wave",
20
+ "orb",
21
+ "ridge"
22
+ ]
23
+ }
24
+ },
25
+ {
26
+ "name": "seed",
27
+ "type": "number",
28
+ "required": false,
29
+ "defaultValue": "1",
30
+ "description": "Which variant of the form. Defaults to `1`.",
31
+ "control": {
32
+ "kind": "number"
33
+ }
34
+ }
35
+ ],
36
+ "typeReferences": [
37
+ "React.SVGProps<SVGSVGElement>"
38
+ ],
39
+ "subcomponents": [],
40
+ "parts": [],
41
+ "variants": {},
42
+ "defaultVariants": {},
43
+ "tokensUsed": [
44
+ "--cue-fg"
45
+ ],
46
+ "summary": "A halftone dot screen over a generated form: the engraved, printed developer-tool motif.",
47
+ "examples": [
48
+ {
49
+ "title": "Usage",
50
+ "code": "<Halftone shape=\"orb\" className=\"h-72 w-72\" />",
51
+ "language": "tsx"
52
+ }
53
+ ],
54
+ "status": "stable",
55
+ "url": "/docs/components/halftone",
56
+ "mdUrl": "/docs/components/halftone.md",
57
+ "jsonUrl": "/r/components/halftone.json",
58
+ "whenToUse": [
59
+ "Hero art on a developer-tool or documentation landing page."
60
+ ],
61
+ "whenNotToUse": [
62
+ "Turning a photograph into halftone. It draws only its generated forms and fetches nothing."
63
+ ],
64
+ "commonMistakes": [
65
+ "Using it at a few pixels. The dot screen needs room; below ~120px the form is lost."
66
+ ],
67
+ "specimens": [
68
+ {
69
+ "title": "Halftone",
70
+ "group": "brand",
71
+ "components": [
72
+ "Halftone"
73
+ ],
74
+ "code": "<Specimens>\n {([\"ridge\", \"wave\", \"orb\"] as const).map((shape) => (\n <Specimen key={shape} label={shape}>\n <Halftone shape={shape} className=\"size-40\" />\n </Specimen>\n ))}\n</Specimens>",
75
+ "note": "A dot screen over a generated form, drawn by the screen itself rather than filtered from an image. Nothing is fetched.",
76
+ "interaction": "none."
77
+ }
78
+ ]
79
+ }
@@ -0,0 +1,204 @@
1
+ {
2
+ "name": "Hero",
3
+ "slug": "hero",
4
+ "group": "chrome",
5
+ "importPath": "@cueplusplus/ui",
6
+ "peerDependencies": [],
7
+ "clientOnly": false,
8
+ "description": "The opening of a page: a title, the line under it, what to do next, and art.\n\n**The Look decides the arrangement, not this component.** The grid reads the\nstyle set's hero recipe — `style-hero-columns`, `style-hero-align` and\n`style-hero-media-order` — so the same hero opens centred under one Look, with\nits art beside the words under another, and with the art first under a third,\nwith no prop changed. Unset, it is one column, start-aligned, art after the\nwords.\n\n**No media, one column**, whatever the recipe says: two columns with nothing in\nthe second is half a page of nothing.\n\n`surface=\"inverse\"` is a theme island in dark mode, so every ink inside it —\nthe title, the lede, a button's fill and its focus ring — is the dark palette's,\nand an overlay opened from it inherits that. The island carries\n`data-cue-rescope`, where the token build re-declares the active set's and\npack's inks, so the card is right in the first frame, before hydration.\n\nStatic markup — no `\"use client\"`.",
9
+ "props": [
10
+ {
11
+ "name": "eyebrow",
12
+ "type": "ReactNode",
13
+ "required": false,
14
+ "defaultValue": null,
15
+ "description": "A short line above the title, usually an `Eyebrow`.",
16
+ "control": {
17
+ "kind": "node",
18
+ "fixture": "children.text"
19
+ }
20
+ },
21
+ {
22
+ "name": "title",
23
+ "type": "ReactNode",
24
+ "required": true,
25
+ "defaultValue": null,
26
+ "description": "The title's first line. A hero without a title is a band; use `Band`.",
27
+ "control": {
28
+ "kind": "node",
29
+ "fixture": "children.text"
30
+ }
31
+ },
32
+ {
33
+ "name": "titleSecond",
34
+ "type": "ReactNode",
35
+ "required": false,
36
+ "defaultValue": null,
37
+ "description": "The title's second line, drawn in the style set's second ink: the accent, a\nmuted ink or the keyword gradient, by the Look. Omit it for a one-line title.",
38
+ "control": {
39
+ "kind": "node",
40
+ "fixture": "children.text"
41
+ }
42
+ },
43
+ {
44
+ "name": "level",
45
+ "type": "1 | 2 | 3",
46
+ "required": false,
47
+ "defaultValue": "1",
48
+ "description": "The title's heading level. `1`, the default, is a page's opening; `2` or `3`\nis a hero that opens a section under the page's own `<h1>`, or a preview of\none on a page about something else.",
49
+ "control": {
50
+ "kind": "enum",
51
+ "members": [
52
+ 1,
53
+ 2,
54
+ 3
55
+ ],
56
+ "min": 1,
57
+ "max": 3
58
+ }
59
+ },
60
+ {
61
+ "name": "lede",
62
+ "type": "ReactNode",
63
+ "required": false,
64
+ "defaultValue": null,
65
+ "description": "The sentence under the title.",
66
+ "control": {
67
+ "kind": "node",
68
+ "fixture": "children.text"
69
+ }
70
+ },
71
+ {
72
+ "name": "actions",
73
+ "type": "ReactNode",
74
+ "required": false,
75
+ "defaultValue": null,
76
+ "description": "The calls to action, usually a primary and a secondary `Button`.",
77
+ "control": {
78
+ "kind": "node",
79
+ "fixture": "children.text"
80
+ }
81
+ },
82
+ {
83
+ "name": "media",
84
+ "type": "ReactNode",
85
+ "required": false,
86
+ "defaultValue": null,
87
+ "description": "Art beside or behind the words: a `Motif`, an image, a product shot.",
88
+ "control": {
89
+ "kind": "node",
90
+ "fixture": "children.text"
91
+ }
92
+ },
93
+ {
94
+ "name": "stats",
95
+ "type": "ReactNode",
96
+ "required": false,
97
+ "defaultValue": null,
98
+ "description": "A row of figures under the lede, usually a `StatBand`.",
99
+ "control": {
100
+ "kind": "node",
101
+ "fixture": "children.text"
102
+ }
103
+ },
104
+ {
105
+ "name": "surface",
106
+ "type": "\"page\" | \"inverse\"",
107
+ "required": false,
108
+ "defaultValue": "page",
109
+ "description": "`page` draws the hero on the page's own ground. `inverse` draws it as a dark\ncard on any page — its whole colour scope flipped, controls and focus included —\nwhich is how a report opens on a light page. Defaults to `\"page\"`.",
110
+ "control": {
111
+ "kind": "enum",
112
+ "members": [
113
+ "page",
114
+ "inverse"
115
+ ]
116
+ }
117
+ }
118
+ ],
119
+ "typeReferences": [
120
+ "Omit<React.ComponentPropsWithoutRef<\"section\">, \"title\">"
121
+ ],
122
+ "subcomponents": [],
123
+ "parts": [],
124
+ "variants": {},
125
+ "defaultVariants": {},
126
+ "tokensUsed": [
127
+ "--cue-bg",
128
+ "--cue-fg",
129
+ "--cue-fg-muted",
130
+ "--cue-font-mono",
131
+ "--cue-leading-ui",
132
+ "--cue-radius-surface",
133
+ "--cue-space-3",
134
+ "--cue-space-5",
135
+ "--cue-space-7",
136
+ "--cue-style-body-face",
137
+ "--cue-style-body-weight",
138
+ "--cue-style-display",
139
+ "--cue-style-display-case",
140
+ "--cue-style-display-face",
141
+ "--cue-style-display-variation",
142
+ "--cue-style-display-weight",
143
+ "--cue-style-heading-ink",
144
+ "--cue-style-hero-align",
145
+ "--cue-style-hero-columns",
146
+ "--cue-style-hero-media-order",
147
+ "--cue-style-hero-title-clip-2",
148
+ "--cue-style-hero-title-fill-2",
149
+ "--cue-style-hero-title-ink-2",
150
+ "--cue-style-hero-title-size",
151
+ "--cue-style-hero-title-text-2",
152
+ "--cue-style-leading-display",
153
+ "--cue-style-lede-ink",
154
+ "--cue-style-lede-leading",
155
+ "--cue-style-lede-size",
156
+ "--cue-style-page-title-face",
157
+ "--cue-style-page-title-leading",
158
+ "--cue-style-page-title-size",
159
+ "--cue-style-page-title-tracking",
160
+ "--cue-style-page-title-weight",
161
+ "--cue-style-prose-ink",
162
+ "--cue-style-prose-tracking",
163
+ "--cue-style-tracking-display",
164
+ "--cue-text-title",
165
+ "--cue-text-ui"
166
+ ],
167
+ "summary": "The opening of a page: a title, its second line, what to do next, and art — arranged by the Look.",
168
+ "examples": [
169
+ {
170
+ "title": "Usage",
171
+ "code": "<Hero eyebrow={<Eyebrow>Category report</Eyebrow>} title=\"Snacks & nuts\" titleSecond=\"Range review\"\n lede=\"Every recommendation has a boundary.\" actions={<Button>Open the report</Button>} />",
172
+ "language": "tsx"
173
+ }
174
+ ],
175
+ "status": "stable",
176
+ "url": "/docs/components/hero",
177
+ "mdUrl": "/docs/components/hero.md",
178
+ "jsonUrl": "/r/components/hero.json",
179
+ "whenToUse": [
180
+ "The top of a landing, product or report page, where one statement and one action lead.",
181
+ "A report's opening card: `surface='inverse'` with `stats` draws the dark KPI hero on a light page."
182
+ ],
183
+ "whenNotToUse": [
184
+ "A section further down the page. Use `Band` with a `SectionHeader`; a page has one hero.",
185
+ "An app screen. Apps open on their work, not a statement; use `AppShell` and `PageShell`."
186
+ ],
187
+ "commonMistakes": [
188
+ "Passing layout props to make it centred or two-column. The Look decides that through its style set; a hero that hard-codes it cannot be re-skinned.",
189
+ "Two columns with no `media`: the hero falls back to one column, by design, so supply the art or let it be one column.",
190
+ "Leaving the default `level={1}` on a hero drawn inside a page that already has its own `<h1>` — a preview, a tile, an embedded page. Pass `level={2}`."
191
+ ],
192
+ "specimens": [
193
+ {
194
+ "title": "Hero",
195
+ "group": "chrome",
196
+ "components": [
197
+ "Hero"
198
+ ],
199
+ "code": "<div className=\"grid w-full gap-(--cue-space-7)\">\n <Hero\n eyebrow={<Eyebrow>Category report</Eyebrow>}\n title=\"Snacks and nuts\"\n titleSecond=\"Range review, week 32\"\n lede=\"Every recommendation has a boundary, and every boundary has a reason you can read.\"\n actions={\n <>\n <Button variant=\"primary\">Open the report</Button>\n <Button>Download the deck</Button>\n </>\n }\n media={<div className=\"aspect-[4/3] w-full rounded-(--radius-surface) bg-surface-2\" />}\n />\n <Hero\n surface=\"inverse\"\n eyebrow={<Eyebrow>This week</Eyebrow>}\n title=\"Availability held at 97.4%\"\n lede=\"The dark card is the page's choice, not the Look's: an island in dark mode, drawn in the Look's own dark palette.\"\n stats={\n <StatBand\n stats={[\n { label: \"Lines\", value: \"1,091\" },\n { label: \"Brands\", value: \"148\" },\n { label: \"Delisted\", value: \"37\", note: \"of 1,128\" },\n ]}\n />\n }\n />\n</div>",
200
+ "note": "The opening of a page. The style set decides the arrangement — one column or two, centred or start-aligned, art first or after — so this hero changes shape with the Look while its props stay put. With no media it is one column whatever the set says.",
201
+ "interaction": "none of its own; the actions are ordinary Buttons."
202
+ }
203
+ ]
204
+ }