@cueplusplus/ui 0.11.0 → 0.12.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.
- package/CHANGELOG.md +251 -0
- package/dist/elements/scroll-anchor.js +4 -2
- package/dist/index.d.ts +4 -2
- package/dist/index.js +2 -1
- package/dist/layout/_ground.d.ts +22 -0
- package/dist/layout/_ground.js +9 -0
- package/dist/layout/bento.js +1 -1
- package/dist/layout/frames.d.ts +70 -0
- package/dist/layout/frames.js +298 -0
- package/dist/layout/index.d.ts +4 -2
- package/dist/layout/index.js +2 -1
- package/dist/layout/preview.d.ts +50 -3
- package/dist/layout/preview.js +179 -31
- package/dist/overlays/drawer.js +1 -1
- package/manifest/components/activity-graph.json +2 -1
- package/manifest/components/agent-card.json +2 -1
- package/manifest/components/agent-pile.json +2 -1
- package/manifest/components/background-inbox.json +2 -1
- package/manifest/components/bento.json +1 -1
- package/manifest/components/breadcrumb.json +2 -1
- package/manifest/components/chart-tooltip-content.json +2 -1
- package/manifest/components/checkpoint-history.json +2 -1
- package/manifest/components/code-diff.json +2 -1
- package/manifest/components/combobox.json +2 -1
- package/manifest/components/comparison-card.json +2 -1
- package/manifest/components/composer-attachment-chip.json +2 -1
- package/manifest/components/composer-context.json +2 -1
- package/manifest/components/composer-model-item.json +2 -1
- package/manifest/components/composer-person-item.json +2 -1
- package/manifest/components/computer-use.json +2 -1
- package/manifest/components/confidence-marker.json +2 -1
- package/manifest/components/context-breakdown.json +2 -1
- package/manifest/components/context-usage.json +2 -1
- package/manifest/components/conversation-search.json +2 -1
- package/manifest/components/cost-meter.json +2 -1
- package/manifest/components/day-separator.json +2 -1
- package/manifest/components/document-reference.json +2 -1
- package/manifest/components/elements-command-palette.json +2 -1
- package/manifest/components/elements-timeline.json +2 -1
- package/manifest/components/elicitation-form.json +2 -1
- package/manifest/components/file-tree.json +2 -1
- package/manifest/components/flow-graph.json +4 -2
- package/manifest/components/frac.json +1 -1
- package/manifest/components/frames.json +210 -0
- package/manifest/components/group-bar.json +2 -1
- package/manifest/components/inline-citation.json +2 -1
- package/manifest/components/job-progress.json +2 -1
- package/manifest/components/log-viewer.json +2 -1
- package/manifest/components/map-answer.json +2 -1
- package/manifest/components/math-block.json +1 -1
- package/manifest/components/mcp-server-panel.json +2 -1
- package/manifest/components/memory-chips.json +2 -1
- package/manifest/components/message-actions.json +2 -1
- package/manifest/components/message-attachments.json +2 -1
- package/manifest/components/message-queue.json +2 -1
- package/manifest/components/message-timing.json +2 -1
- package/manifest/components/meter.json +1 -1
- package/manifest/components/model-picker.json +2 -1
- package/manifest/components/multi-select.json +2 -1
- package/manifest/components/onboarding.json +2 -1
- package/manifest/components/preview.json +85 -8
- package/manifest/components/prompt-library.json +2 -1
- package/manifest/components/queue-dock.json +2 -1
- package/manifest/components/quote-reply.json +2 -1
- package/manifest/components/reasoning-effort.json +2 -1
- package/manifest/components/reasoning-panel.json +2 -1
- package/manifest/components/regenerate-menu.json +2 -1
- package/manifest/components/research-report.json +2 -1
- package/manifest/components/retrieval-chunks.json +2 -1
- package/manifest/components/reviewable-diff.json +2 -1
- package/manifest/components/schedule-card.json +2 -1
- package/manifest/components/score-breakdown.json +2 -1
- package/manifest/components/scroll-anchor.json +2 -1
- package/manifest/components/segmented-control.json +2 -1
- package/manifest/components/settings-panel.json +2 -1
- package/manifest/components/shared-conversation.json +2 -1
- package/manifest/components/sources.json +2 -1
- package/manifest/components/speaker-identity.json +2 -1
- package/manifest/components/spec-sheet.json +2 -1
- package/manifest/components/spectrum-visualizer.json +2 -1
- package/manifest/components/stepper.json +2 -1
- package/manifest/components/streaming-text.json +2 -1
- package/manifest/components/sub.json +1 -1
- package/manifest/components/subagent-list.json +4 -2
- package/manifest/components/sup.json +1 -1
- package/manifest/components/swap-label.json +2 -1
- package/manifest/components/thread-list.json +2 -1
- package/manifest/components/thread-search.json +2 -1
- package/manifest/components/todo-list.json +2 -1
- package/manifest/components/tool-group.json +2 -1
- package/manifest/components/trace-waterfall.json +2 -1
- package/manifest/components/tree.json +2 -1
- package/manifest/components/universe-grid.json +2 -1
- package/manifest/components/usage-chart.json +2 -1
- package/manifest/components/voice-conversation.json +2 -1
- package/manifest/components/web-search.json +2 -1
- package/manifest/fixtures.json +665 -0
- package/manifest/manifest.json +97 -84
- package/manifest/tokens.json +1 -1
- package/package.json +5 -5
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "Frames",
|
|
3
|
+
"slug": "frames",
|
|
4
|
+
"group": "layout",
|
|
5
|
+
"importPath": "@cueplusplus/ui",
|
|
6
|
+
"peerDependencies": [],
|
|
7
|
+
"clientOnly": true,
|
|
8
|
+
"description": "A design canvas: frames side by side, each holding one axis of one component.\n\n`Frames.Root` is the canvas — short, wide, scrollable sideways, focusable,\nand pannable with the pointer. `Frames.Item` is one captioned cell, and it is\nused **inside a `Preview`** rather than inside the Root. The two are apart\nbecause that is how they are used, and a props-only API cannot say it.\n\n**The canvas knows nothing about its children.** It does not count them, does\nnot index them and does not select one; `hint` is where a caller puts what it\nknows. A canvas that knew its frames would be a manifest API, and this is a\nslot API.",
|
|
9
|
+
"props": [],
|
|
10
|
+
"typeReferences": [],
|
|
11
|
+
"subcomponents": [
|
|
12
|
+
"Root",
|
|
13
|
+
"Item"
|
|
14
|
+
],
|
|
15
|
+
"parts": [
|
|
16
|
+
{
|
|
17
|
+
"name": "Root",
|
|
18
|
+
"usage": "Frames.Root",
|
|
19
|
+
"description": "The canvas: a short, wide, focusable scroll region that holds frames.\n\n**It knows nothing about its children.** It does not count them, index them\nor select one — a canvas that knew its frames would be a manifest API, and\nthis is a slot API. `hint` is where a caller puts the count it knows and this\ndoes not.",
|
|
20
|
+
"props": [
|
|
21
|
+
{
|
|
22
|
+
"name": "children",
|
|
23
|
+
"type": "ReactNode",
|
|
24
|
+
"required": true,
|
|
25
|
+
"defaultValue": null,
|
|
26
|
+
"description": "The frames. Anything — this never inspects them.",
|
|
27
|
+
"control": {
|
|
28
|
+
"kind": "node",
|
|
29
|
+
"fixture": "children.text"
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"name": "label",
|
|
34
|
+
"type": "string",
|
|
35
|
+
"required": true,
|
|
36
|
+
"defaultValue": null,
|
|
37
|
+
"description": "The canvas's accessible name — \"Button frames\". Required: the canvas is a\nfocusable scroll region, and a scroll region with no name is one a screen\nreader announces as nothing.",
|
|
38
|
+
"control": {
|
|
39
|
+
"kind": "string"
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"name": "height",
|
|
44
|
+
"type": "\"short\" | \"tall\"",
|
|
45
|
+
"required": false,
|
|
46
|
+
"defaultValue": "short",
|
|
47
|
+
"description": "`\"short\"` is 18.5rem, `\"tall\"` 27rem. A CSS length in `style` overrides both.",
|
|
48
|
+
"control": {
|
|
49
|
+
"kind": "enum",
|
|
50
|
+
"members": [
|
|
51
|
+
"short",
|
|
52
|
+
"tall"
|
|
53
|
+
]
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
"name": "ground",
|
|
58
|
+
"type": "\"none\" | \"plain\" | \"dots\"",
|
|
59
|
+
"required": false,
|
|
60
|
+
"defaultValue": "dots",
|
|
61
|
+
"description": "The canvas ground. Defaults to `\"dots\"`.",
|
|
62
|
+
"control": {
|
|
63
|
+
"kind": "enum",
|
|
64
|
+
"members": [
|
|
65
|
+
"none",
|
|
66
|
+
"plain",
|
|
67
|
+
"dots"
|
|
68
|
+
]
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
"name": "hint",
|
|
73
|
+
"type": "ReactNode",
|
|
74
|
+
"required": false,
|
|
75
|
+
"defaultValue": null,
|
|
76
|
+
"description": "The line in the bottom-right corner — \"drag to pan · 8 frames\". Unset, none is drawn.",
|
|
77
|
+
"control": {
|
|
78
|
+
"kind": "node",
|
|
79
|
+
"fixture": "children.text"
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
"name": "pan",
|
|
84
|
+
"type": "boolean",
|
|
85
|
+
"required": false,
|
|
86
|
+
"defaultValue": "true",
|
|
87
|
+
"description": "Drag-to-pan with the pointer. Defaults to `true`. A drag that starts on a\ncontrol is never a pan, so a frame's own controls stay usable — and \"on a\ncontrol\" counts the control's own contents: the words inside a\n`role=\"menuitem\"` row, the icon inside a `button`. A drag inside a\nrole-bearing box that is not itself a control — a `role=\"group\"` frame, a\n`role=\"region\"` — still pans, because a frame is such a box and a board is\nmostly frames. Only the primary button drags; `false` binds no pointer\nlistener at all; and the keyboard scrolls the canvas either way.",
|
|
88
|
+
"control": {
|
|
89
|
+
"kind": "boolean"
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
],
|
|
93
|
+
"typeReferences": [
|
|
94
|
+
"Omit<React.ComponentPropsWithoutRef<\"div\">, \"children\">"
|
|
95
|
+
]
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
"name": "Item",
|
|
99
|
+
"usage": "Frames.Item",
|
|
100
|
+
"description": "One captioned cell of a frame.\n\n**It is used inside a `Preview`, not inside `Frames.Root`** — that is the\nwhole reason this is a compound rather than a props API: the canvas holds\nframes, a frame holds a stage, and the stage holds these. `Frames.Root` never\nlooks for one.\n\n**A stage does not arrange them, and the caller does.** A stage is a centred\ngrid in both presentations, so two items left to it stack; the row every\nexample here draws is `<div className=\"flex flex-wrap items-end gap-(--cue-space-6)\">`,\nand `items-end` is what lines the captions up when the specimens are\ndifferent heights.",
|
|
101
|
+
"props": [
|
|
102
|
+
{
|
|
103
|
+
"name": "children",
|
|
104
|
+
"type": "ReactNode",
|
|
105
|
+
"required": true,
|
|
106
|
+
"defaultValue": null,
|
|
107
|
+
"description": "The specimen.",
|
|
108
|
+
"control": {
|
|
109
|
+
"kind": "node",
|
|
110
|
+
"fixture": "children.text"
|
|
111
|
+
}
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
"name": "caption",
|
|
115
|
+
"type": "ReactNode",
|
|
116
|
+
"required": false,
|
|
117
|
+
"defaultValue": null,
|
|
118
|
+
"description": "The line under it. Hidden — not removed — when the frame sets `captions={false}`.",
|
|
119
|
+
"control": {
|
|
120
|
+
"kind": "node",
|
|
121
|
+
"fixture": "children.text"
|
|
122
|
+
}
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
"name": "selected",
|
|
126
|
+
"type": "boolean",
|
|
127
|
+
"required": false,
|
|
128
|
+
"defaultValue": "false",
|
|
129
|
+
"description": "Draws the selection outline the frame gives the item a reader is inspecting.",
|
|
130
|
+
"control": {
|
|
131
|
+
"kind": "boolean"
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
],
|
|
135
|
+
"typeReferences": [
|
|
136
|
+
"React.ComponentPropsWithoutRef<\"div\">"
|
|
137
|
+
]
|
|
138
|
+
}
|
|
139
|
+
],
|
|
140
|
+
"variants": {},
|
|
141
|
+
"defaultVariants": {},
|
|
142
|
+
"tokensUsed": [
|
|
143
|
+
"--cue-accent",
|
|
144
|
+
"--cue-border",
|
|
145
|
+
"--cue-fg-subtle",
|
|
146
|
+
"--cue-font-mono",
|
|
147
|
+
"--cue-hair-strong",
|
|
148
|
+
"--cue-radius-control",
|
|
149
|
+
"--cue-radius-surface",
|
|
150
|
+
"--cue-space-2",
|
|
151
|
+
"--cue-space-3",
|
|
152
|
+
"--cue-space-4",
|
|
153
|
+
"--cue-space-6",
|
|
154
|
+
"--cue-space-8",
|
|
155
|
+
"--cue-surface-1",
|
|
156
|
+
"--cue-text-micro"
|
|
157
|
+
],
|
|
158
|
+
"summary": "A design canvas: frames side by side, each holding one axis of one component. Short, wide, scrollable sideways, focusable, and pannable with the pointer.",
|
|
159
|
+
"examples": [
|
|
160
|
+
{
|
|
161
|
+
"title": "A short board that pans",
|
|
162
|
+
"code": "<Frames.Root label=\"Button frames\" hint=\"drag to pan · 2 frames\">\n <Preview presentation=\"frame\" label=\"Tone\" count={2}>\n <div className=\"flex flex-wrap items-end gap-(--cue-space-6)\">\n <Frames.Item caption=\"accent\">\n <Button variant=\"primary\">Take cue</Button>\n </Frames.Item>\n <Frames.Item caption=\"default\">\n <Button>Take cue</Button>\n </Frames.Item>\n </div>\n </Preview>\n</Frames.Root>",
|
|
163
|
+
"language": "tsx"
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
"title": "Tall, flat, and still",
|
|
167
|
+
"code": "<Frames.Root label=\"Grid frames\" height=\"tall\" ground=\"plain\" pan={false}>\n <Preview presentation=\"frame\" label=\"Columns\" count={3} captions={false}>\n …\n </Preview>\n</Frames.Root>",
|
|
168
|
+
"language": "tsx"
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
"title": "Usage",
|
|
172
|
+
"code": "<Frames.Root label=\"Button frames\" hint=\"drag to pan · 3 frames\">\n <Preview presentation=\"frame\" label=\"Tone\" count={3} name={<ToneMenu />}>\n <div className=\"flex flex-wrap items-end gap-(--cue-space-6)\">\n <Frames.Item caption=\"accent\"><Button tone=\"accent\">Take cue</Button></Frames.Item>\n <Frames.Item caption=\"ok\"><Button tone=\"ok\">Take cue</Button></Frames.Item>\n <Frames.Item caption=\"warn\"><Button tone=\"warn\">Take cue</Button></Frames.Item>\n </div>\n </Preview>\n</Frames.Root>",
|
|
173
|
+
"language": "tsx"
|
|
174
|
+
}
|
|
175
|
+
],
|
|
176
|
+
"status": "stable",
|
|
177
|
+
"url": "/docs/components/frames",
|
|
178
|
+
"mdUrl": "/docs/components/frames.md",
|
|
179
|
+
"jsonUrl": "/r/components/frames.json",
|
|
180
|
+
"whenToUse": [
|
|
181
|
+
"Showing a component's axes at once — one frame per axis, each with its own name row and its own settings — instead of one preview a reader has to re-configure.",
|
|
182
|
+
"Any short, wide board of specimens a reader scans rather than reads: a theme sheet, a size ladder, a state matrix.",
|
|
183
|
+
"Beside `Preview presentation=\"frame\"`, which is what a frame on this canvas is."
|
|
184
|
+
],
|
|
185
|
+
"whenNotToUse": [
|
|
186
|
+
"Laying components out in a page. That is `Grid` or `Bento`; a canvas is a viewport that scrolls, and everything in it is off-screen by design.",
|
|
187
|
+
"A board a reader zooms. This does not zoom, and it will not: a transformed subtree breaks every popover anchored inside it.",
|
|
188
|
+
"Scrolling down. The canvas is `overflow-y: hidden` on purpose — it is short and wide, not a second page."
|
|
189
|
+
],
|
|
190
|
+
"commonMistakes": [
|
|
191
|
+
"Putting `Frames.Item` inside `Frames.Root`. The item belongs on a frame's stage — `Frames.Root` holds frames, and a frame is a `Preview`.",
|
|
192
|
+
"Expecting a frame to arrange its items. A stage is a centred grid in both presentations, so two items stack; put them in a row yourself — the row is `<div className=\"flex flex-wrap items-end gap-(--cue-space-6)\">`, and every example here uses exactly that one.",
|
|
193
|
+
"Leaving `label` off, or repeating the page's heading in it. The canvas is a focusable scroll region, and its name is what a screen reader announces when a reader tabs into it.",
|
|
194
|
+
"Expecting the canvas to count its frames. It never inspects its children — pass the count yourself, in `hint`.",
|
|
195
|
+
"Expecting a long `caption` to wrap or to ellipsise on its own. A cell does not shrink, so a caption longer than its specimen widens the cell instead, and the wrapping row it sits in wraps a cell sooner — the `truncate` on the caption has no narrower box to fire in. Bound the cell yourself when a caption can run long: `<Frames.Item className=\"max-w-[12rem]\" caption=\"…\">`.",
|
|
196
|
+
"Reading `captions={false}` as a way to take a caption out of the page. It is visual only — the caption goes to `opacity: 0` and stops taking pointer events, keeping its box so nothing re-flows and keeping its place in the accessibility tree, so a screen reader still reads it. Delete the `caption` prop if the words should not be there at all."
|
|
197
|
+
],
|
|
198
|
+
"specimens": [
|
|
199
|
+
{
|
|
200
|
+
"title": "Frames",
|
|
201
|
+
"group": "layout",
|
|
202
|
+
"components": [
|
|
203
|
+
"Frames"
|
|
204
|
+
],
|
|
205
|
+
"code": "<Frames.Root\n label=\"Button frames\"\n hint=\"drag to pan · 2 frames\"\n className=\"w-full\"\n>\n <Preview\n label=\"Button tone\"\n presentation=\"frame\"\n count={3}\n tools={<Chip variant=\"outline\">tone</Chip>}\n >\n <div className=\"flex flex-wrap items-end gap-(--cue-space-6)\">\n <Frames.Item caption=\"accent\" selected>\n <Button variant=\"primary\">Take cue</Button>\n </Frames.Item>\n <Frames.Item caption=\"default\">\n <Button>Take cue</Button>\n </Frames.Item>\n <Frames.Item caption=\"subtle\">\n <Button variant=\"ghost\">Take cue</Button>\n </Frames.Item>\n </div>\n </Preview>\n <Preview label=\"Button density\" presentation=\"frame\" count={2} captions={false}>\n <div className=\"flex flex-wrap items-end gap-(--cue-space-6)\">\n <Frames.Item caption=\"compact\">\n <Button size=\"sm\">Go</Button>\n </Frames.Item>\n <Frames.Item caption=\"normal\">\n <Button>Go</Button>\n </Frames.Item>\n </div>\n </Preview>\n</Frames.Root>",
|
|
206
|
+
"note": "A design canvas: frames side by side, each holding one axis of one component. The canvas is a focusable scroll region; a frame is a `Preview` in its `frame` presentation, with its name row above the stage and four crosshairs at the corners; an item is one captioned cell on that stage.",
|
|
207
|
+
"interaction": "the canvas scrolls sideways: click it and Left and Right step one rung of the space ladder, PageUp and PageDown a viewport, Home and End the two ends. Dragging it pans it — except a drag that starts on a control, which stays a click. `pan={false}` turns the dragging off and leaves the keyboard."
|
|
208
|
+
}
|
|
209
|
+
]
|
|
210
|
+
}
|
|
@@ -74,7 +74,7 @@
|
|
|
74
74
|
"Sub",
|
|
75
75
|
"Sup"
|
|
76
76
|
],
|
|
77
|
-
"code": "<Specimens>\n <Specimen label=\"worked through\" wide>\n <MathBlock label=\"illuminance at the deck\" steps={MATH} visibleSteps={
|
|
77
|
+
"code": "<Specimens>\n <Specimen label=\"worked through\" wide>\n <MathBlock label=\"illuminance at the deck\" steps={MATH} visibleSteps={3} />\n </Specimen>\n <Specimen label=\"first step only\" wide>\n <MathBlock steps={MATH} visibleSteps={1} />\n </Specimen>\n</Specimens>",
|
|
78
78
|
"note": "Maths with the working shown, a step at a time. The expressions are nodes rather than a string, so there is no parser and no KaTeX in the bundle — `Frac` stacks a numerator over a rule, `Sup` and `Sub` set an index upright inside the serif italic, and anything else is text.",
|
|
79
79
|
"interaction": "none. Each step's note says what justified it, which is what turns three lines of algebra into an explanation."
|
|
80
80
|
}
|
|
@@ -142,7 +142,7 @@
|
|
|
142
142
|
"components": [
|
|
143
143
|
"Meter"
|
|
144
144
|
],
|
|
145
|
-
"code": "<Panel className=\"w-full max-w-[36rem]\">\n {CHANNELS.map((channel) => (\n <Row key={channel.name} className=\"gap-(--cue-space-4)\">\n <span className=\"w-[7rem] shrink-0 truncate\">{channel.name}</span>\n <Meter percent={channel.level} tone={channel.tone} className=\"flex-1\" />\n <span className=\"w-[3rem] shrink-0 text-right font-mono tabular-nums\">\n {channel.level}%\n </span>\n </Row>\n ))}\n <Row className=\"gap-(--cue-space-4)\">\n <span className=\"w-[7rem] shrink-0 truncate\">Pace tick</span>\n <Meter percent={64} paceTick={
|
|
145
|
+
"code": "<Panel className=\"w-full max-w-[36rem]\">\n {CHANNELS.map((channel) => (\n <Row key={channel.name} className=\"gap-(--cue-space-4)\">\n <span className=\"w-[7rem] shrink-0 truncate\">{channel.name}</span>\n <Meter percent={channel.level} tone={channel.tone} className=\"flex-1\" />\n <span className=\"w-[3rem] shrink-0 text-right font-mono tabular-nums\">\n {channel.level}%\n </span>\n </Row>\n ))}\n <Row className=\"gap-(--cue-space-4)\">\n <span className=\"w-[7rem] shrink-0 truncate\">Pace tick</span>\n <Meter percent={64} paceTick={0.6} className=\"flex-1\" label=\"64% used, 60% of period elapsed\" />\n </Row>\n <Row className=\"gap-(--cue-space-4)\">\n <span className=\"w-[7rem] shrink-0 truncate\">Estimated</span>\n <Meter percent={40} provenance=\"estimated\" className=\"flex-1\" />\n </Row>\n <Row className=\"gap-(--cue-space-4)\">\n <span className=\"w-[7rem] shrink-0 truncate\">Unbounded</span>\n <Meter percent={0} provenance=\"unbounded\" className=\"flex-1\" />\n </Row>\n <Row className=\"gap-(--cue-space-4)\">\n <span className=\"w-[7rem] shrink-0 truncate\">No data</span>\n <Meter percent={0} empty className=\"flex-1\" />\n </Row>\n</Panel>",
|
|
146
146
|
"note": "Never invents a number: an unbounded meter draws no percentage, an empty one draws stripes rather than a zero, and an estimated ceiling is hatched so it cannot pass for a measurement.",
|
|
147
147
|
"interaction": "the over-pace pulse stills under prefers-reduced-motion and stays readable as a data attribute."
|
|
148
148
|
}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"importPath": "@cueplusplus/ui",
|
|
6
6
|
"peerDependencies": [],
|
|
7
7
|
"clientOnly": true,
|
|
8
|
-
"description": "A
|
|
8
|
+
"description": "A card for one component: a stage that is its own theme island, a slot for\ntools at the top right, and a footer.\n\n**Two presentations, one stage.** `\"panel\"`, the default and what every\nexisting caller gets, is that card: a border, a fill, a dot grid under the\nspecimen, and the tools floating over the stage's top right. `\"frame\"` is a\ndesign-canvas frame — no card, no border, no fill; the name, the count and\nthe tools sit in a row *above* the stage rather than over it, four crosshairs\nmark the stage's outer corners, and the stage paints nothing by default, so\nwhatever canvas the frame sits on shows through. Everything below holds in\nboth.\n\n**The stage is the island; the chrome is not.** `theme`, `mode`, `density`\nand `font` land on the stage element only, and the stage republishes the\ntheme and density contexts so an overlay opened on it follows it. The tools,\nthe footer, the grips and anything they open stay in the scope around the\nPreview — a `terminal` preview's own controls do not turn cyan. With none of\nthe four set, the stage carries no attribute and costs what a `<div>` costs.\nA stage `theme` with no `mode` repeats the page's mode beside it.\n\n**`resizable` is handles of its own**, both axes by default: an edge grip per\naxis that is a keyboard-operable `separator` valued in pixels, and a corner\ngrip for the pointer. Double-click resets an axis. The width never outgrows\nthe frame: its bound in force is the frame's own width, observed live, when\nthat is under `maxWidth`. Not `Resizable`, which is split panes on an\noptional peer.\n\nProps, not a compound: one stage and its slots, each saying what it is.",
|
|
9
9
|
"props": [
|
|
10
10
|
{
|
|
11
11
|
"name": "children",
|
|
@@ -121,6 +121,66 @@
|
|
|
121
121
|
"kind": "node",
|
|
122
122
|
"fixture": "children.text"
|
|
123
123
|
}
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
"name": "presentation",
|
|
127
|
+
"type": "\"frame\" | \"panel\"",
|
|
128
|
+
"required": false,
|
|
129
|
+
"defaultValue": "panel",
|
|
130
|
+
"description": "`\"panel\"` (the default, and what every existing caller gets): a bordered\ncard, `tools` floating at the stage's top right, `footer` under it.\n`\"frame\"`: a design-canvas frame — the label row drawn *above* the stage\nrather than over it, four crosshair corners at the stage's outer corners,\nand a transparent stage so whatever the frame sits on shows through.",
|
|
131
|
+
"control": {
|
|
132
|
+
"kind": "enum",
|
|
133
|
+
"members": [
|
|
134
|
+
"frame",
|
|
135
|
+
"panel"
|
|
136
|
+
]
|
|
137
|
+
}
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
"name": "name",
|
|
141
|
+
"type": "ReactNode",
|
|
142
|
+
"required": false,
|
|
143
|
+
"defaultValue": null,
|
|
144
|
+
"description": "The label row's leading slot, drawn only in `\"frame\"`. A plain node, or a\ncontrol: apps/docs passes a `DropdownMenu` whose trigger is the frame's\nname. Unset, the row opens with `label` as text.\n\nA slot and not a built-in menu, because `Preview` imports no overlay today\nand `/` draws seventeen of it under a 766-byte headroom.",
|
|
145
|
+
"control": {
|
|
146
|
+
"kind": "node",
|
|
147
|
+
"fixture": "children.text"
|
|
148
|
+
}
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
"name": "count",
|
|
152
|
+
"type": "number",
|
|
153
|
+
"required": false,
|
|
154
|
+
"defaultValue": null,
|
|
155
|
+
"description": "The count drawn after the name — how many items this frame holds. Frame only.",
|
|
156
|
+
"control": {
|
|
157
|
+
"kind": "number"
|
|
158
|
+
}
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
"name": "ground",
|
|
162
|
+
"type": "\"none\" | \"plain\" | \"dots\"",
|
|
163
|
+
"required": false,
|
|
164
|
+
"defaultValue": null,
|
|
165
|
+
"description": "The stage's ground. Defaults to `\"dots\"` in `\"panel\"` and `\"none\"` in\n`\"frame\"`, where the canvas under it already carries a ground and two dot\ngrids at different pitches read as a moiré.",
|
|
166
|
+
"control": {
|
|
167
|
+
"kind": "enum",
|
|
168
|
+
"members": [
|
|
169
|
+
"none",
|
|
170
|
+
"plain",
|
|
171
|
+
"dots"
|
|
172
|
+
]
|
|
173
|
+
}
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
"name": "captions",
|
|
177
|
+
"type": "boolean",
|
|
178
|
+
"required": false,
|
|
179
|
+
"defaultValue": "true",
|
|
180
|
+
"description": "Whether `Frames.Item` captions are shown inside this stage. Defaults to\n`true`. Off is paint and nothing more: a hidden caption is still rendered,\nstill in the tree and still read aloud (§4.1 Decision 4).",
|
|
181
|
+
"control": {
|
|
182
|
+
"kind": "boolean"
|
|
183
|
+
}
|
|
124
184
|
}
|
|
125
185
|
],
|
|
126
186
|
"typeReferences": [
|
|
@@ -137,6 +197,7 @@
|
|
|
137
197
|
"--cue-control-sm",
|
|
138
198
|
"--cue-fg",
|
|
139
199
|
"--cue-fg-muted",
|
|
200
|
+
"--cue-fg-subtle",
|
|
140
201
|
"--cue-font-mono",
|
|
141
202
|
"--cue-hair-strong",
|
|
142
203
|
"--cue-radius-control",
|
|
@@ -149,9 +210,10 @@
|
|
|
149
210
|
"--cue-surface-1",
|
|
150
211
|
"--cue-surface-2",
|
|
151
212
|
"--cue-surface-3",
|
|
152
|
-
"--cue-text-label"
|
|
213
|
+
"--cue-text-label",
|
|
214
|
+
"--cue-text-micro"
|
|
153
215
|
],
|
|
154
|
-
"summary": "A
|
|
216
|
+
"summary": "A card for one component: a stage that is its own theme island, tools at the top right — or, in the `frame` presentation a design canvas draws, in a label row above the stage beside the name and the count — a footer, and grips that resize it on both axes.",
|
|
155
217
|
"examples": [
|
|
156
218
|
{
|
|
157
219
|
"title": "Inheriting the page, resizable",
|
|
@@ -163,9 +225,19 @@
|
|
|
163
225
|
"code": "<Preview label=\"Chip preview\" theme=\"terminal\" density=\"compact\">\n <Chip tone=\"accent\">Standby</Chip>\n</Preview>",
|
|
164
226
|
"language": "tsx"
|
|
165
227
|
},
|
|
228
|
+
{
|
|
229
|
+
"title": "A canvas frame",
|
|
230
|
+
"code": "<Preview\n presentation=\"frame\"\n label=\"Button tone\"\n name={<ToneMenu />}\n count={3}\n tools={<IconButton aria-label=\"Configure Button tone\" icon={Wrench} />}\n>\n <div className=\"flex flex-wrap items-end gap-(--cue-space-6)\">\n <Frames.Item caption=\"accent\">\n <Button variant=\"primary\">Take cue</Button>\n </Frames.Item>\n </div>\n</Preview>",
|
|
231
|
+
"language": "tsx"
|
|
232
|
+
},
|
|
233
|
+
{
|
|
234
|
+
"title": "A frame with its captions off",
|
|
235
|
+
"code": "<Preview presentation=\"frame\" label=\"Button density\" count={2} captions={false}>\n <div className=\"flex flex-wrap items-end gap-(--cue-space-6)\">\n <Frames.Item caption=\"compact\">\n <Button size=\"sm\">Go</Button>\n </Frames.Item>\n <Frames.Item caption=\"normal\">\n <Button>Go</Button>\n </Frames.Item>\n </div>\n</Preview>",
|
|
236
|
+
"language": "tsx"
|
|
237
|
+
},
|
|
166
238
|
{
|
|
167
239
|
"title": "Usage",
|
|
168
|
-
"code": "<Preview label=\"Button preview\" tools={<IconButton aria-label=\"Configure Button\" icon={Wrench} />}>\n <Button variant=\"primary\">Take cue</Button>\n</Preview>\n<Preview label=\"Chip preview\" theme=\"terminal\" density=\"compact\" resizable>\n <Chip tone=\"accent\">Standby</Chip>\n</Preview>",
|
|
240
|
+
"code": "<Preview label=\"Button preview\" tools={<IconButton aria-label=\"Configure Button\" icon={Wrench} />}>\n <Button variant=\"primary\">Take cue</Button>\n</Preview>\n<Preview label=\"Chip preview\" theme=\"terminal\" density=\"compact\" resizable>\n <Chip tone=\"accent\">Standby</Chip>\n</Preview>\n<Preview label=\"Button\" presentation=\"frame\" count={3}>\n <Button variant=\"primary\">Take cue</Button>\n</Preview>",
|
|
169
241
|
"language": "tsx"
|
|
170
242
|
}
|
|
171
243
|
],
|
|
@@ -176,16 +248,21 @@
|
|
|
176
248
|
"whenToUse": [
|
|
177
249
|
"Showing one component in a state a reader can see and change — a gallery tile, a docs listing, a design review page.",
|
|
178
250
|
"Putting a component in a different theme, mode, density or font from the page around it, without re-theming the controls that change it.",
|
|
179
|
-
"Letting a reader watch a component respond to its container: pass `resizable` and drag it narrow, or short."
|
|
251
|
+
"Letting a reader watch a component respond to its container: pass `resizable` and drag it narrow, or short.",
|
|
252
|
+
"Drawing one axis of a component on a design canvas: `presentation=\"frame\"` moves the label row above the stage, puts `tools` in it, makes the stage transparent and marks the four corners."
|
|
180
253
|
],
|
|
181
254
|
"whenNotToUse": [
|
|
182
255
|
"Laying several components out side by side. That is `Bento` or `Grid`; a Preview holds one specimen.",
|
|
183
|
-
"Split panes a user resizes as part of an app. That is `Resizable`; a Preview's grips resize a stage, not a layout."
|
|
256
|
+
"Split panes a user resizes as part of an app. That is `Resizable`; a Preview's grips resize a stage, not a layout.",
|
|
257
|
+
"Building the frame's name menu into the Preview. `name` is a slot: pass your own `DropdownMenu`. This component imports no overlay, and a page that draws seventeen Previews cannot afford one."
|
|
184
258
|
],
|
|
185
259
|
"commonMistakes": [
|
|
186
260
|
"Naming a `theme` whose stylesheet is not on the page. The stage is scoped to `[data-theme]`, and a Preview loads no CSS — import `@cueplusplus/theme-<name>/theme.css` yourself, or the stage paints the blank base.",
|
|
187
261
|
"Setting `mode` outside any `ThemeProvider` and expecting a change. A theme's light block needs the theme on the same element, and with no provider there is no theme to restate.",
|
|
188
|
-
"Putting the controls that configure the specimen in `children`. They would take the stage's theme; put them in `tools`, which follows the page."
|
|
262
|
+
"Putting the controls that configure the specimen in `children`. They would take the stage's theme; put them in `tools`, which follows the page.",
|
|
263
|
+
"Setting `presentation=\"frame\"` and leaving `ground` alone on a page that already draws a dot grid. A frame's ground defaults to `none` for exactly that reason; naming `dots` puts a second grid at a second pitch over the first, and the two read as a moiré.",
|
|
264
|
+
"Reading `count` as something the Preview works out. It counts nothing — `count` is what the caller knows, and `0` is a count it will draw.",
|
|
265
|
+
"Passing `resizable` to a `presentation=\"frame\"` Preview. The crosshair marks follow the frame box, not a resized stage, so dragging the grips puts the marks off the stage's corners — use `resizable` on a panel, or keep the frame a fixed size."
|
|
189
266
|
],
|
|
190
267
|
"specimens": [
|
|
191
268
|
{
|
|
@@ -195,7 +272,7 @@
|
|
|
195
272
|
"Preview"
|
|
196
273
|
],
|
|
197
274
|
"code": "<Specimens>\n <Specimen label=\"inherits the page, resizable\" wide>\n <Preview\n label=\"Button preview\"\n resizable\n footer={<span className=\"font-mono text-(length:--cue-text-label) text-fg-subtle\">Button · inherits</span>}\n >\n <Button variant=\"primary\">Take cue</Button>\n </Preview>\n </Specimen>\n <Specimen label=\"its own theme and density\" wide>\n <Preview\n label=\"Chip preview\"\n theme=\"terminal\"\n density=\"compact\"\n footer={<span className=\"font-mono text-(length:--cue-text-label) text-fg-subtle\">Chip · terminal · compact</span>}\n >\n <Chip tone=\"accent\">Standby</Chip>\n </Preview>\n </Specimen>\n</Specimens>",
|
|
198
|
-
"note": "A
|
|
275
|
+
"note": "A card for one component. The stage is its own theme island — theme, mode, density and font land on it and nowhere else — while the tools, the footer and anything they open follow the page.",
|
|
199
276
|
"interaction": "with `resizable`, the width and height grips are separators: Left and Right step the width, Up and Down the height, 8 px a press and 64 with Shift; Home and End reach the bounds, and a double-click resets an axis. The corner grip is a pointer convenience over the two."
|
|
200
277
|
}
|
|
201
278
|
]
|
|
@@ -16,7 +16,8 @@
|
|
|
16
16
|
"defaultValue": null,
|
|
17
17
|
"description": "The turns waiting to send, in the order they will drain. Ordering is the\ncaller's: Cursor lets a person drag one up the list, and a component that\nsorted the array it was given could not be dragged.",
|
|
18
18
|
"control": {
|
|
19
|
-
"kind": "array"
|
|
19
|
+
"kind": "array",
|
|
20
|
+
"fixture": "agents.follow-ups"
|
|
20
21
|
}
|
|
21
22
|
},
|
|
22
23
|
{
|