@cloudgrid-io/ui 0.27.0 → 0.27.2

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.
@@ -0,0 +1,217 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import * as React from "react";
4
+ import { useRender } from "@base-ui/react/use-render";
5
+ import { ChevronDownIcon } from "./icons.js";
6
+ import { Eyebrow } from "./eyebrow.js";
7
+ import { cn } from "../lib/cloudgrid-cn.js";
8
+ /**
9
+ * The vertical navigation that stands inside a page box: a context line, a set
10
+ * of labelled groups, and a column of rows one of which is the page you are on.
11
+ *
12
+ * Read from the Console's redesigned app page (ui#225, Figma 8010:385,
13
+ * 8316:2158, 8306:2294). Three roles see three different columns of the same
14
+ * nav — an owner sees APP with `Build & run` collapsed, a grid admin sees it
15
+ * expanded with seven children, a viewer sees APP alone — so the shape that
16
+ * ships is one nav whose groups and rows are handed in, not three sidebars.
17
+ *
18
+ * ## It draws and it behaves. It does not know where anything is
19
+ *
20
+ * The line #117 drew for the entity card, and the reason `render` below exists.
21
+ * This block builds no `href`, matches no route and gates no role. The consumer
22
+ * decides which rows a reader may see, which one is `active`, and what element
23
+ * a row actually is. Anything else would put the Console's URL helpers and its
24
+ * role model inside the design system, where neither can be right for long.
25
+ *
26
+ * ## Three parts, and what each is for
27
+ *
28
+ * `SideNav` the `<nav>` landmark, the context slot, and the keyboard.
29
+ * `SideNavGroup` an eyebrow-labelled run of rows (APP, MANAGE), or a
30
+ * collapsible one with a header of its own (Build & run).
31
+ * `SideNavItem` one row: a glyph, a label, an optional count, and whether
32
+ * it is the page you are on.
33
+ *
34
+ * ## The keyboard
35
+ *
36
+ * Every row is a real tab stop, so Tab walks the column in DOM order. Arrow
37
+ * keys are laid over that rather than replacing it: ArrowDown and ArrowUp move
38
+ * focus between rows and wrap at the ends, which is what a reader who has
39
+ * landed in a 15-row column expects and what Tab alone makes tedious.
40
+ *
41
+ * This is deliberately NOT a roving-tabindex tablist. A tablist owns one tab
42
+ * stop because its tabs are one control; these rows are links to separate
43
+ * pages, and making fourteen of them unreachable by Tab to satisfy a pattern
44
+ * they are not an instance of is a worse nav, not a more correct one.
45
+ *
46
+ * A collapsible group's header is in the same ring as the rows. It sits in the
47
+ * column and looks like a row, so an arrow key that skipped it would strand the
48
+ * one control that reveals six more.
49
+ *
50
+ * Space is handled explicitly, and only where the browser does not. A `<button>`
51
+ * activates on both Enter and Space already; an `<a href>` activates on Enter
52
+ * and SCROLLS THE PAGE on Space. Since a row is normally an anchor — that is
53
+ * what `render={<Link />}` makes it — the nav synthesises the click for Space
54
+ * on anything that is not a button. Doing it unconditionally would fire a
55
+ * button's activation twice, once here and once natively.
56
+ *
57
+ * ## The active row does not flip, and that is the decision
58
+ *
59
+ * The frame's active row is a pale lavender chip carrying purple text:
60
+ * `--cg-primary-tint` under `--cg-primary`. Both are declared at `:root` only,
61
+ * so the row paints the same two values on the page, on the purple panel and on
62
+ * ink — and that is the point rather than an oversight.
63
+ *
64
+ * It is the kind badge's rule (#196) applied to a row: the chip brings its own
65
+ * ground, so it does not need the surface's answer for one. The pair measures
66
+ * 5.02:1, which clears AA for its 15px label everywhere, and the chip measures
67
+ * 1.16:1 against the white card, 5.02:1 against the panel and 13.68:1 on ink.
68
+ * `packages/ui/test/contrast-guardrail.test.mjs` holds every one of those
69
+ * numbers, and says why the chip's own floor is not 3:1.
70
+ *
71
+ * The alternative was a surface-scoped `--cg-primary-tint`, and it fails on the
72
+ * panel for a measured reason the token file already records: a white wash over
73
+ * the brand purple gives white text 4.31:1, under the floor, and white is the
74
+ * lightest colour there is. AA on a tinted row over that ground needs the FILL
75
+ * to move, which is a brand decision and not this block's.
76
+ *
77
+ * Everything else in the nav does flip: the rows' text, the hover wash, the
78
+ * hairline, the count pill. The root sets `text-ink` because text does not flip
79
+ * by inheritance (rule 3).
80
+ *
81
+ * ## No hover ground you can name
82
+ *
83
+ * The rows hover on `var(--cg-hover)` directly. It is the one token that means
84
+ * "a wash over whatever this sits on" and it is declared in all three scopes;
85
+ * `theme.css` gives it no utility on purpose, because `bg-hover` sits one
86
+ * character from Tailwind's own `hover:` variant. `bg-subtle` would have been
87
+ * the obvious reach and it is lavender at `:root` only, so a hovered row on the
88
+ * purple panel would have been white text on near-white.
89
+ */
90
+ /** Rows and group headers, in the order the column draws them. */
91
+ const ROW_SELECTOR = '[data-slot="side-nav-item"],[data-slot="side-nav-group-header"]';
92
+ /**
93
+ * The rows a key press can actually reach.
94
+ *
95
+ * Filtered on `getClientRects()` rather than on the DOM, because a closed
96
+ * group's rows stay MOUNTED (see `SideNavGroup`) and a ring that counted them
97
+ * would move focus onto a `display: none` element, which silently drops it to
98
+ * the body.
99
+ */
100
+ function reachableRows(root) {
101
+ return Array.from(root.querySelectorAll(ROW_SELECTOR)).filter((el) => el.getClientRects().length > 0 && !el.hasAttribute("disabled"));
102
+ }
103
+ function SideNav({ label, context, className, children, onKeyDown, ...props }) {
104
+ function handleKeyDown(event) {
105
+ onKeyDown?.(event);
106
+ if (event.defaultPrevented)
107
+ return;
108
+ const step = event.key === "ArrowDown" ? 1 : event.key === "ArrowUp" ? -1 : 0;
109
+ if (step === 0)
110
+ return;
111
+ const rows = reachableRows(event.currentTarget);
112
+ const from = rows.indexOf(document.activeElement);
113
+ // Not -1 only when focus is already on a row. A key press while focus sits
114
+ // in the context line should scroll the page, as it would anywhere else.
115
+ if (from === -1 || rows.length === 0)
116
+ return;
117
+ event.preventDefault();
118
+ rows[(from + step + rows.length) % rows.length]?.focus();
119
+ }
120
+ return (_jsxs("nav", { "data-slot": "side-nav", "aria-label": label, onKeyDown: handleKeyDown,
121
+ // text-ink because text does not flip by inheritance: without it every
122
+ // row inside a panel would inherit the page's dark ink and stay dark on
123
+ // purple.
124
+ className: cn("flex w-full flex-col gap-6 text-ink", className), ...props, children: [context ? (_jsx("div", { "data-slot": "side-nav-context", className: "px-3 text-caption text-faint", children: context })) : null, children] }));
125
+ }
126
+ function SideNavGroup({ label, icon, collapsible, open, defaultOpen = false, onOpenChange, className, children, ...props }) {
127
+ const panelId = React.useId();
128
+ const [uncontrolled, setUncontrolled] = React.useState(defaultOpen);
129
+ const isControlled = open !== undefined;
130
+ const isOpen = isControlled ? open : uncontrolled;
131
+ function toggle() {
132
+ const next = !isOpen;
133
+ if (!isControlled)
134
+ setUncontrolled(next);
135
+ onOpenChange?.(next);
136
+ }
137
+ const rows = (_jsx("div", { className:
138
+ // The display utility is applied ONLY when open, and that is not a
139
+ // shortcut. The UA's `[hidden] { display: none }` is an author-beatable
140
+ // rule, so a `flex` class on the same element wins it and the panel
141
+ // stays visible while announcing itself collapsed.
142
+ //
143
+ // Tailwind v4's preflight covers for that with
144
+ // `[hidden]:where(:not([hidden='until-found'])) { display: none
145
+ // !important }`, which is why the trap does not bite in this repo's own
146
+ // gallery. It bites in a consumer that takes the theme without the
147
+ // preflight — the Astro surface this registry serves, and anyone who
148
+ // disables it — so the fix belongs in the component rather than in a
149
+ // stylesheet the component does not ship. Same argument as `Eyebrow`'s
150
+ // `m-0`.
151
+ isOpen ? "flex flex-col gap-0.5" : undefined, children: children }));
152
+ if (!collapsible) {
153
+ return (_jsxs("div", { "data-slot": "side-nav-group", className: cn("flex flex-col gap-1", className), ...props, children: [label ? (
154
+ // The library's eyebrow rather than its recipe, so retuning the label
155
+ // step is one edit in eyebrow.tsx. Caps and the caption size are this
156
+ // frame's treatment of it, which is what `className` is for — see the
157
+ // eyebrow's own note on not being uppercase by default.
158
+ _jsx(Eyebrow, { className: "px-3 text-caption uppercase", children: label })) : null, rows] }));
159
+ }
160
+ return (_jsxs("div", { "data-slot": "side-nav-group", "data-collapsible": "", "data-open": isOpen ? "" : undefined, className: cn("flex flex-col gap-0.5", className), ...props, children: [_jsxs("button", { type: "button", "data-slot": "side-nav-group-header", "aria-expanded": isOpen, "aria-controls": panelId, onClick: toggle, className: cn("flex w-full items-center gap-2 rounded-lg px-3 py-2 text-left text-body-sm text-body", "transition-colors hover:bg-(--cg-hover) hover:text-ink", "focus-visible:ring-3 focus-visible:ring-ring focus-visible:outline-none"), children: [icon ? (_jsx("span", { "data-slot": "side-nav-icon", className: "flex size-4 shrink-0 items-center justify-center", children: icon })) : null, _jsx("span", { className: "min-w-0 flex-1 truncate", children: label }), _jsx(ChevronDownIcon
161
+ // The caret is the only thing in this block that moves. It rotates
162
+ // rather than swapping to a second glyph, so the direction it points
163
+ // is continuous with the panel opening under it.
164
+ , {
165
+ // The caret is the only thing in this block that moves. It rotates
166
+ // rather than swapping to a second glyph, so the direction it points
167
+ // is continuous with the panel opening under it.
168
+ className: cn("size-4 shrink-0 transition-transform duration-[var(--cg-duration)] ease-out", isOpen ? "rotate-0" : "-rotate-90") })] }), _jsx("div", { id: panelId, hidden: !isOpen, className: isOpen ? "pl-3" : undefined, children: rows })] }));
169
+ }
170
+ function SideNavItem({ label, icon, count, active, render, className, onKeyDown, ...props }) {
171
+ function handleKeyDown(event) {
172
+ onKeyDown?.(event);
173
+ if (event.defaultPrevented)
174
+ return;
175
+ // See the module note: Space on an anchor scrolls. Synthesised only for the
176
+ // elements the browser does not already activate, or a button fires twice.
177
+ if (event.key !== " ")
178
+ return;
179
+ const el = event.currentTarget;
180
+ if (el.tagName === "BUTTON")
181
+ return;
182
+ event.preventDefault();
183
+ el.click();
184
+ }
185
+ return useRender({
186
+ render,
187
+ defaultTagName: "button",
188
+ props: {
189
+ "data-slot": "side-nav-item",
190
+ "data-active": active ? "" : undefined,
191
+ // aria-current is what says "this is the page you are on". The tint says
192
+ // it to a reader who can see it, and colour is never the only channel.
193
+ "aria-current": active ? "page" : undefined,
194
+ // Only when this really is a <button>. `type` on an anchor is invalid,
195
+ // and `render={<Link />}` is the common case.
196
+ ...(render ? {} : { type: "button" }),
197
+ onKeyDown: handleKeyDown,
198
+ className: cn("flex w-full items-center gap-2 rounded-lg px-3 py-2 text-left text-body-sm no-underline", "transition-colors focus-visible:ring-3 focus-visible:ring-ring focus-visible:outline-none", active
199
+ ? // The self-contained chip. See the module note for the numbers and
200
+ // for why it is the same two values on all three surfaces.
201
+ "bg-brand-tint font-medium text-brand"
202
+ : "text-body hover:bg-(--cg-hover) hover:text-ink", className),
203
+ // The row's content is composed from the three slots rather than taken as
204
+ // `children`, which is why `children` is omitted from the props type: a
205
+ // caller who could pass both would have two ways to fill one row and no
206
+ // rule about which wins.
207
+ children: (_jsxs(_Fragment, { children: [icon ? (_jsx("span", { "data-slot": "side-nav-icon", className: "flex size-4 shrink-0 items-center justify-center", children: icon })) : null, _jsx("span", { className: "min-w-0 flex-1 truncate", children: label }), count === undefined ? null : (_jsx("span", { "data-slot": "side-nav-count",
208
+ // The wash again, for the reason the hover uses it: a pale grey
209
+ // pill named `bg-raised` is neutral-50 at :root only, so it would
210
+ // be a near-white pill on the purple panel.
211
+ className: "shrink-0 rounded-pill bg-(--cg-hover) px-2 text-caption text-body", children: count }))] })),
212
+ ...props,
213
+ },
214
+ });
215
+ }
216
+ export { SideNav, SideNavGroup, SideNavItem };
217
+ //# sourceMappingURL=side-nav.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"side-nav.js","sourceRoot":"","sources":["../../src/blocks/side-nav.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,69 @@
1
+ import * as React from "react";
2
+ /**
3
+ * One metric, in a bordered card: a small label, a large value, one line of
4
+ * sub-label under it.
5
+ *
6
+ * Every number on the Console's redesigned app page is this tile (ui#227, Figma
7
+ * 8010:385 and 8036:780) — Views, Time on view, AI tokens, Requests,
8
+ * Deployments, App type — laid out in rows of three or four. The Console
9
+ * hand-rolls the arrangement in `EntityAnalyticsBoard` today and Home keeps a
10
+ * second copy, which is two places for one tile and the reason this exists.
11
+ *
12
+ * ## `value` is a node, and that is load-bearing
13
+ *
14
+ * Six of the eight tiles in the Insights frame carry a number, and the other
15
+ * two carry "Static" and "11 plugs · 0 errors". A tile that took a `number`
16
+ * would have forced the Console to keep its own component for the two that are
17
+ * words, which is the duplication this block is replacing.
18
+ *
19
+ * ## `pending`, so a tile never invents a number
20
+ *
21
+ * The frame's "Time per request" tile reads "Coming soon" in the value's own
22
+ * position, muted, with the hint still saying "Latency". That is the whole
23
+ * state: the metric is real, the reporting is not built, and the tile says so
24
+ * rather than showing a zero that a reader would take for a measurement. The
25
+ * words are this block's rather than the caller's on purpose — one spelling,
26
+ * everywhere it is true.
27
+ *
28
+ * ## The hint's two tones
29
+ *
30
+ * `neutral` is the reporting period ("Last 30 days", "Median", "All time"), and
31
+ * it is the common case. `positive` is the one the frames do not draw and the
32
+ * issue asks for: "+50 this week", growth said in the state palette's own
33
+ * green.
34
+ *
35
+ * It resolves `--cg-online-strong` rather than `--cg-online`. The tone is tuned
36
+ * for a dot and its own note says so — "3.40:1 on white, never body text on
37
+ * white" — while `-strong` is the rung the system added for a status as WORDS
38
+ * and it holds 4.5:1. Inside the panel and ink scopes `-strong` resolves to the
39
+ * surface's own primary text, which is the token file's recorded decision, not
40
+ * a fallback invented here: there is no green on the purple panel that clears
41
+ * AA at any value. So a positive hint on a dark surface reads as the surface's
42
+ * brightest text beside a muted neutral one, which is still a difference a
43
+ * reader can see.
44
+ *
45
+ * No new colour was added for it, per ui#227.
46
+ *
47
+ * ## Type
48
+ *
49
+ * The value takes the display rung and the display face, and deliberately not
50
+ * `PageHeading`'s uppercase and display tracking: those are tuned for a lockup
51
+ * of words. `tabular-nums` because a column of tiles whose digits are
52
+ * proportional jitters when one of them ticks over.
53
+ */
54
+ /** The hint's tone. `positive` is growth; there is no negative, because the frames draw none. */
55
+ export type StatHintTone = "neutral" | "positive";
56
+ declare function StatTile({ label, value, hint, hintTone, pending, className, ...props }: Omit<React.ComponentProps<"div">, "ref" | "children"> & {
57
+ /** Names the metric. Small and muted, above the value. */
58
+ label: React.ReactNode;
59
+ /** The measurement. Ignored when `pending`. */
60
+ value?: React.ReactNode;
61
+ /** One line under the value: the reporting period, or what moved. */
62
+ hint?: React.ReactNode;
63
+ hintTone?: StatHintTone;
64
+ /** The metric is real and the number is not available yet. */
65
+ pending?: boolean;
66
+ }): React.JSX.Element;
67
+ declare function StatTileRow({ className, children, ...props }: Omit<React.ComponentProps<"div">, "ref">): React.JSX.Element;
68
+ export { StatTile, StatTileRow };
69
+ //# sourceMappingURL=stat-tile.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stat-tile.d.ts","sourceRoot":"","sources":["../../src/blocks/stat-tile.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAI9B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmDG;AAEH,iGAAiG;AACjG,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,UAAU,CAAA;AAOjD,iBAAS,QAAQ,CAAC,EAChB,KAAK,EACL,KAAK,EACL,IAAI,EACJ,QAAoB,EACpB,OAAO,EACP,SAAS,EACT,GAAG,KAAK,EACT,EAAE,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,KAAK,GAAG,UAAU,CAAC,GAAG;IACzD,0DAA0D;IAC1D,KAAK,EAAE,KAAK,CAAC,SAAS,CAAA;IACtB,+CAA+C;IAC/C,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACvB,qEAAqE;IACrE,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACtB,QAAQ,CAAC,EAAE,YAAY,CAAA;IACvB,8DAA8D;IAC9D,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB,qBAkCA;AAsBD,iBAAS,WAAW,CAAC,EACnB,SAAS,EACT,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,qBAiB1C;AAcD,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,CAAA"}
@@ -0,0 +1,54 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import * as React from "react";
3
+ import { cn } from "../lib/cloudgrid-cn.js";
4
+ const HINT_TONE = {
5
+ neutral: "text-faint",
6
+ positive: "text-online-strong",
7
+ };
8
+ function StatTile({ label, value, hint, hintTone = "neutral", pending, className, ...props }) {
9
+ return (_jsxs("div", { "data-slot": "stat-tile", "data-pending": pending ? "" : undefined,
10
+ // text-ink on the root, because text does not flip by inheritance
11
+ // (rule 3): without it a tile inside a panel inherits the page's dark ink
12
+ // and its value stays dark on purple.
13
+ className: cn("flex min-w-0 flex-col gap-1 rounded-xl border border-hairline bg-card p-4 text-ink", className), ...props, children: [_jsx("span", { "data-slot": "stat-tile-label", className: "text-caption text-faint", children: label }), _jsx("span", { "data-slot": "stat-tile-value", "data-pending": pending ? "" : undefined, className: cn("font-display text-display-sm leading-display font-medium tabular-nums", pending && "text-faint"), children: pending ? "Coming soon" : value }), hint ? (_jsx("span", { "data-slot": "stat-tile-hint", "data-tone": hintTone, className: cn("text-caption", HINT_TONE[hintTone]), children: hint })) : null] }));
14
+ }
15
+ /**
16
+ * A row of tiles: two, three or four, side by side, stacking as the column
17
+ * narrows.
18
+ *
19
+ * The frames draw three on Overview and four on Insights, so the count is the
20
+ * caller's and the breakpoints are derived from it rather than passed. Four
21
+ * across at phone width would be four columns of two characters each.
22
+ *
23
+ * The class strings are a lookup rather than a template, and that is not
24
+ * stylistic: Tailwind emits only the utilities it finds by scanning source, so
25
+ * a built `lg:grid-cols-${n}` compiles to a class that exists in the markup and
26
+ * in no stylesheet. Nothing errors; the row simply never becomes a grid.
27
+ */
28
+ const ROW_COLUMNS = {
29
+ 1: "grid-cols-1",
30
+ 2: "grid-cols-1 sm:grid-cols-2",
31
+ 3: "grid-cols-1 sm:grid-cols-2 lg:grid-cols-3",
32
+ 4: "grid-cols-1 sm:grid-cols-2 lg:grid-cols-4",
33
+ };
34
+ function StatTileRow({ className, children, ...props }) {
35
+ // Counted rather than taken as a prop, so a tile added to a row cannot leave
36
+ // the layout describing the row it used to be. Anything over four falls to
37
+ // the four-column ramp: it wraps, which is a legible answer, and the issue's
38
+ // range is two to four.
39
+ const count = Math.min(4, Math.max(1, countTiles(children)));
40
+ return (_jsx("div", { "data-slot": "stat-tile-row", "data-tiles": count, className: cn("grid gap-4", ROW_COLUMNS[count], className), ...props, children: children }));
41
+ }
42
+ /**
43
+ * How many tiles a caller actually handed over.
44
+ *
45
+ * `React.Children.count` counts a mapped array as one child, and a row built
46
+ * from data — which is how a consumer will build it — is exactly that shape. So
47
+ * this flattens first, and drops the nulls a `cond && <StatTile />` leaves
48
+ * behind, since a conditional tile that is absent must not hold a column open.
49
+ */
50
+ function countTiles(children) {
51
+ return React.Children.toArray(children).length;
52
+ }
53
+ export { StatTile, StatTileRow };
54
+ //# sourceMappingURL=stat-tile.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stat-tile.js","sourceRoot":"","sources":["../../src/blocks/stat-tile.tsx"],"names":[],"mappings":";AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,EAAE,EAAE,EAAE,MAAM,oBAAoB,CAAA;AA0DvC,MAAM,SAAS,GAAiC;IAC9C,OAAO,EAAE,YAAY;IACrB,QAAQ,EAAE,oBAAoB;CAC/B,CAAA;AAED,SAAS,QAAQ,CAAC,EAChB,KAAK,EACL,KAAK,EACL,IAAI,EACJ,QAAQ,GAAG,SAAS,EACpB,OAAO,EACP,SAAS,EACT,GAAG,KAAK,EAWT;IACC,OAAO,CACL,4BACY,WAAW,kBACP,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS;QACtC,kEAAkE;QAClE,0EAA0E;QAC1E,sCAAsC;QACtC,SAAS,EAAE,EAAE,CACX,oFAAoF,EACpF,SAAS,CACV,KACG,KAAK,aAET,4BAAgB,iBAAiB,EAAC,SAAS,EAAC,yBAAyB,YAClE,KAAK,GACD,EACP,4BACY,iBAAiB,kBACb,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,EACtC,SAAS,EAAE,EAAE,CACX,uEAAuE,EACvE,OAAO,IAAI,YAAY,CACxB,YAEA,OAAO,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,KAAK,GAC3B,EACN,IAAI,CAAC,CAAC,CAAC,CACN,4BAAgB,gBAAgB,eAAY,QAAQ,EAAE,SAAS,EAAE,EAAE,CAAC,cAAc,EAAE,SAAS,CAAC,QAAQ,CAAC,CAAC,YACrG,IAAI,GACA,CACR,CAAC,CAAC,CAAC,IAAI,IACJ,CACP,CAAA;AACH,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,GAA2B;IAC1C,CAAC,EAAE,aAAa;IAChB,CAAC,EAAE,4BAA4B;IAC/B,CAAC,EAAE,2CAA2C;IAC9C,CAAC,EAAE,2CAA2C;CAC/C,CAAA;AAED,SAAS,WAAW,CAAC,EACnB,SAAS,EACT,QAAQ,EACR,GAAG,KAAK,EACiC;IACzC,6EAA6E;IAC7E,2EAA2E;IAC3E,6EAA6E;IAC7E,wBAAwB;IACxB,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAA;IAE5D,OAAO,CACL,2BACY,eAAe,gBACb,KAAK,EACjB,SAAS,EAAE,EAAE,CAAC,YAAY,EAAE,WAAW,CAAC,KAAK,CAAC,EAAE,SAAS,CAAC,KACtD,KAAK,YAER,QAAQ,GACL,CACP,CAAA;AACH,CAAC;AAED;;;;;;;GAOG;AACH,SAAS,UAAU,CAAC,QAAyB;IAC3C,OAAO,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAA;AAChD,CAAC;AAED,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,CAAA"}
@@ -44,7 +44,64 @@ import { PageHeading } from "./page-heading.js";
44
44
  * that an answer had been given when the user was reading. Tabs say "same
45
45
  * screen, different content", which is what this is.
46
46
  */
47
- export interface ToolSetupTool {
47
+ /**
48
+ * An install METHOD: MCP, CLI, Skills. Optional, and everything about the method
49
+ * axis is keyed on whether any are passed.
50
+ *
51
+ * A tool supports a method when it has steps for it. Nothing declares support
52
+ * separately, because two places to say the same thing is one place to get it
53
+ * wrong: the CLI tab drops ChatGPT because ChatGPT has no CLI steps, not because
54
+ * a flag says so.
55
+ */
56
+ export interface ToolSetupMethod {
57
+ value: string;
58
+ label: string;
59
+ disabled?: boolean;
60
+ }
61
+ /**
62
+ * A heading for a run of tools in the strip. Coding agents, chat apps.
63
+ *
64
+ * A group whose tools are all filtered out by the current method disappears,
65
+ * along with the divider that would have sat beside it. That is the same rule
66
+ * `HubIndex` encodes for its own groups, and for the same reason: a group may
67
+ * legitimately name nothing right now.
68
+ */
69
+ export interface ToolSetupGroup {
70
+ value: string;
71
+ label: string;
72
+ }
73
+ /**
74
+ * One step of a pane.
75
+ *
76
+ * `label` is an alternative marker ("Easiest", "Or") rather than a sequence
77
+ * position. A pane whose first step carries one is a set of CHOICES and renders
78
+ * as columns; a pane without is a SEQUENCE and renders as a numbered `StepList`,
79
+ * whose `<ol>` does the numbering for a screen reader.
80
+ *
81
+ * `body` is a node, not a string. Body copy carries emphasis, and a text grammar
82
+ * in the design system is a second content system arriving through the side
83
+ * door. The caller renders its own Markdown, or HTML, or nothing, and hands over
84
+ * what it wants painted. Same line #117, #121 and #126 drew.
85
+ */
86
+ export interface ToolSetupStep {
87
+ /** "Easiest", "Or". Present on the first step makes the pane a set of choices. */
88
+ label?: string;
89
+ title: string;
90
+ body?: React.ReactNode;
91
+ /** A multi line prompt to hand an agent. */
92
+ prompt?: string;
93
+ /** A single command to run. */
94
+ code?: string;
95
+ link?: {
96
+ label: string;
97
+ href: string;
98
+ /** The caller's glyph. The library does not pick it, per HubIndex and #47. */
99
+ icon?: React.ReactNode;
100
+ /** Draw it as the primary action rather than a secondary one. */
101
+ primary?: boolean;
102
+ };
103
+ }
104
+ interface ToolSetupToolBase {
48
105
  /** What `onValueChange` reports. Stable, and never shown. */
49
106
  value: string;
50
107
  /** The words on the tab. Two short words wrap; they are not truncated. */
@@ -55,8 +112,14 @@ export interface ToolSetupTool {
55
112
  * boilerplate at the exact moment the user needs to know where the text goes.
56
113
  */
57
114
  instruction?: string;
58
- /** The text to paste. Multi-line is normal here; `CodeBlock` preserves it. */
59
- prompt: string;
115
+ /** Which `ToolSetupGroup` this sits under. Ignored when no groups are passed. */
116
+ group?: string;
117
+ /**
118
+ * The vendor mark, supplied by the caller. A node rather than a name: which
119
+ * marks exist is content, and the trademark question in #47 is not this
120
+ * component's to answer.
121
+ */
122
+ mark?: React.ReactNode;
60
123
  /** Shown beside the instruction. For a tool with a manual path as well. */
61
124
  alternative?: {
62
125
  label: string;
@@ -64,8 +127,38 @@ export interface ToolSetupTool {
64
127
  };
65
128
  disabled?: boolean;
66
129
  }
67
- declare function ToolSetup({ tools, value, defaultValue, onValueChange, title, sub, eyebrow, level, headingSize, continueLabel, onContinue, canContinue, footer, className, ...props }: Omit<React.ComponentProps<"section">, "ref" | "title" | "defaultValue" | "onChange"> & {
130
+ /**
131
+ * A tool has to have something to show, and the type says so.
132
+ *
133
+ * Making `prompt` merely optional was wrong: it took the guarantee away from
134
+ * every existing caller, so a typo in `prompt` stopped being a compile error and
135
+ * became a tab with an empty bordered panel under it. The union keeps the old
136
+ * contract for callers that pass no steps and adds the new one, without a
137
+ * runtime check standing in for a type.
138
+ *
139
+ * `prompt` stays readable on the union because both arms declare it, so the
140
+ * panel can fall back to it without narrowing.
141
+ *
142
+ * `steps` is keyed by method value. Passing it is what puts a tool on the method
143
+ * axis; a tool with no entry for the selected method is filtered out of the
144
+ * strip, which is also why a `prompt` only tool never appears in method mode.
145
+ */
146
+ export type ToolSetupTool = ToolSetupToolBase & ({
147
+ prompt: string;
148
+ steps?: Record<string, ToolSetupStep[]>;
149
+ } | {
150
+ prompt?: string;
151
+ steps: Record<string, ToolSetupStep[]>;
152
+ });
153
+ declare function ToolSetup({ tools, methods, groups, method, defaultMethod, onMethodChange, value, defaultValue, onValueChange, title, sub, eyebrow, level, headingSize, continueLabel, emptyLabel, onContinue, canContinue, footer, className, ...props }: Omit<React.ComponentProps<"section">, "ref" | "title" | "defaultValue" | "onChange"> & {
68
154
  tools: ToolSetupTool[];
155
+ /** Pass these and the method strip appears above the tool strip. */
156
+ methods?: ToolSetupMethod[];
157
+ /** Pass these and the tool strip is grouped, with empty groups dropped. */
158
+ groups?: ToolSetupGroup[];
159
+ method?: string;
160
+ defaultMethod?: string;
161
+ onMethodChange?: (method: string) => void;
69
162
  value?: string;
70
163
  defaultValue?: string;
71
164
  onValueChange?: (value: string) => void;
@@ -89,6 +182,14 @@ declare function ToolSetup({ tools, value, defaultValue, onValueChange, title, s
89
182
  * declarative opt-out works from both.
90
183
  */
91
184
  continueLabel?: string | null;
185
+ /**
186
+ * Shown when the selected method leaves no tools to pick from. A default
187
+ * rather than a required prop, on the same reasoning as `continueLabel`: the
188
+ * state is reachable by passing a method nothing supports, and a heading over
189
+ * blank space is the "reads as broken" outcome the note on `first` exists to
190
+ * prevent.
191
+ */
192
+ emptyLabel?: string;
92
193
  onContinue?: () => void;
93
194
  /**
94
195
  * Defaults to `true`, unlike `OnboardingQuestion`'s. Nothing here is an answer
@@ -1 +1 @@
1
- {"version":3,"file":"tool-setup.d.ts","sourceRoot":"","sources":["../../src/blocks/tool-setup.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAI9B,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAA;AAIxD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AAEH,MAAM,WAAW,aAAa;IAC5B,6DAA6D;IAC7D,KAAK,EAAE,MAAM,CAAA;IACb,0EAA0E;IAC1E,KAAK,EAAE,MAAM,CAAA;IACb;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,8EAA8E;IAC9E,MAAM,EAAE,MAAM,CAAA;IACd,2EAA2E;IAC3E,WAAW,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAA;IAC7C,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB;AA8BD,iBAAS,SAAS,CAAC,EACjB,KAAK,EACL,KAAK,EACL,YAAY,EACZ,aAAa,EACb,KAAK,EACL,GAAG,EACH,OAAO,EACP,KAAS,EACT,WAAkB,EAClB,aAA0B,EAC1B,UAAU,EACV,WAAkB,EAClB,MAAM,EACN,SAAS,EACT,GAAG,KAAK,EACT,EAAE,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,SAAS,CAAC,EAAE,KAAK,GAAG,OAAO,GAAG,cAAc,GAAG,UAAU,CAAC,GAAG;IACxF,KAAK,EAAE,aAAa,EAAE,CAAA;IACtB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IACvC,iFAAiF;IACjF,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,2EAA2E;IAC3E,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,CAAA;IACb,WAAW,CAAC,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAA;IAC9D;;;;;;;;;;;OAWG;IACH,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC7B,UAAU,CAAC,EAAE,MAAM,IAAI,CAAA;IACvB;;;;OAIG;IACH,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,sEAAsE;IACtE,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;CACzB,qBA4HA;AAED,OAAO,EAAE,SAAS,EAAE,CAAA"}
1
+ {"version":3,"file":"tool-setup.d.ts","sourceRoot":"","sources":["../../src/blocks/tool-setup.tsx"],"names":[],"mappings":"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"}