@cloudgrid-io/ui 0.29.2 → 0.31.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/README.md +63 -0
- package/dist/blocks/agent-prompt.d.ts +17 -1
- package/dist/blocks/agent-prompt.d.ts.map +1 -1
- package/dist/blocks/agent-prompt.js +33 -3
- package/dist/blocks/agent-prompt.js.map +1 -1
- package/dist/blocks/cloudgrid-install.d.ts +67 -0
- package/dist/blocks/cloudgrid-install.d.ts.map +1 -0
- package/dist/blocks/cloudgrid-install.js +192 -0
- package/dist/blocks/cloudgrid-install.js.map +1 -0
- package/dist/blocks/command-field.d.ts +38 -0
- package/dist/blocks/command-field.d.ts.map +1 -0
- package/dist/blocks/command-field.js +70 -0
- package/dist/blocks/command-field.js.map +1 -0
- package/dist/blocks/drop-zone.d.ts +2 -1
- package/dist/blocks/drop-zone.d.ts.map +1 -1
- package/dist/blocks/drop-zone.js.map +1 -1
- package/dist/blocks/entity-card.d.ts +81 -24
- package/dist/blocks/entity-card.d.ts.map +1 -1
- package/dist/blocks/entity-card.js +235 -126
- package/dist/blocks/entity-card.js.map +1 -1
- package/dist/blocks/icons.d.ts +23 -1
- package/dist/blocks/icons.d.ts.map +1 -1
- package/dist/blocks/icons.js +23 -1
- package/dist/blocks/icons.js.map +1 -1
- package/dist/blocks/install-content.d.ts +228 -0
- package/dist/blocks/install-content.d.ts.map +1 -0
- package/dist/blocks/install-content.js +464 -0
- package/dist/blocks/install-content.js.map +1 -0
- package/dist/blocks/logo.d.ts +70 -1
- package/dist/blocks/logo.d.ts.map +1 -1
- package/dist/blocks/logo.js +75 -2
- package/dist/blocks/logo.js.map +1 -1
- package/dist/blocks/phosphor-marks.d.ts +6 -0
- package/dist/blocks/phosphor-marks.d.ts.map +1 -1
- package/dist/blocks/phosphor-marks.js +9 -0
- package/dist/blocks/phosphor-marks.js.map +1 -1
- package/dist/blocks/prompt-block.d.ts +57 -0
- package/dist/blocks/prompt-block.d.ts.map +1 -0
- package/dist/blocks/prompt-block.js +219 -0
- package/dist/blocks/prompt-block.js.map +1 -0
- package/dist/blocks/stage-panel.d.ts +19 -0
- package/dist/blocks/stage-panel.d.ts.map +1 -1
- package/dist/blocks/stage-panel.js +2 -4
- package/dist/blocks/stage-panel.js.map +1 -1
- package/dist/blocks/step-item.d.ts +21 -1
- package/dist/blocks/step-item.d.ts.map +1 -1
- package/dist/blocks/step-item.js +27 -2
- package/dist/blocks/step-item.js.map +1 -1
- package/dist/blocks/tool-logo.d.ts.map +1 -1
- package/dist/blocks/tool-logo.js +10 -6
- package/dist/blocks/tool-logo.js.map +1 -1
- package/dist/blocks/tool-setup.d.ts +95 -9
- package/dist/blocks/tool-setup.d.ts.map +1 -1
- package/dist/blocks/tool-setup.js +129 -49
- package/dist/blocks/tool-setup.js.map +1 -1
- package/dist/brand/mark-180.png +0 -0
- package/dist/brand/mark-192.png +0 -0
- package/dist/brand/mark-32.png +0 -0
- package/dist/brand/mark-512.png +0 -0
- package/dist/brand/mark-inverted-180.png +0 -0
- package/dist/brand/mark-inverted-192.png +0 -0
- package/dist/brand/mark-inverted-32.png +0 -0
- package/dist/brand/mark-inverted-512.png +0 -0
- package/dist/brand/mark-inverted.svg +8 -0
- package/dist/brand/mark.svg +7 -0
- package/dist/index.d.ts +4 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -1
- package/package.json +7 -2
- package/dist/blocks/plug-method.d.ts +0 -76
- package/dist/blocks/plug-method.d.ts.map +0 -1
- package/dist/blocks/plug-method.js +0 -30
- package/dist/blocks/plug-method.js.map +0 -1
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { SOCKET_GLYPH_PATH } from "./logo.js";
|
|
2
3
|
import { Panel } from "../ui/panel.js";
|
|
3
4
|
import { cn } from "../lib/cloudgrid-cn.js";
|
|
4
5
|
/**
|
|
@@ -20,11 +21,8 @@ import { cn } from "../lib/cloudgrid-cn.js";
|
|
|
20
21
|
* The socket is `aria-hidden`, as is the grid: both are texture, and a screen
|
|
21
22
|
* reader announcing a decorative wordmark twice per page is noise.
|
|
22
23
|
*/
|
|
23
|
-
/** The socket from the brand wordmark, the "o" of CloudGrid. Same path the favicon
|
|
24
|
-
* carries, so it is replaced from the brand asset rather than edited. */
|
|
25
|
-
const SOCKET_PATH = "M73.507 15.918C79.2174 15.918 83.9637 17.7685 87.6718 21.3962C91.4541 25.0239 93.3088 29.6883 93.3088 35.4631C93.3088 41.2378 91.454 45.9761 87.6718 49.6038C85.0356 52.1829 81.8742 53.8602 78.215 54.6154C77.054 54.855 76.0252 53.9204 76.0252 52.7349V47.5482C76.0252 46.6336 76.6575 45.8569 77.493 45.4848C81.0368 43.9067 83.2962 40.1577 83.2962 35.4872C83.2962 34.0556 83.0947 32.7167 82.7167 31.5015C82.5932 31.1043 82.2168 30.8479 81.8008 30.8479H80.8927V27.1501C80.8923 25.785 79.7842 24.6784 78.4167 24.6783C77.0492 24.6783 75.941 25.785 75.9407 27.1501V30.8479H71.3901V27.1501C71.3897 25.785 70.2801 24.6783 68.9126 24.6783C67.5454 24.6787 66.4369 25.7852 66.4366 27.1501V30.8479H65.2899C64.88 30.8479 64.5075 31.0968 64.381 31.4867C63.9866 32.7028 63.7916 34.0384 63.7916 35.4872C63.7916 38.5967 64.6821 41.188 66.5362 43.261C67.4434 44.239 68.4572 44.9856 69.5949 45.4935C70.4337 45.868 71.0717 46.6457 71.0717 47.5643V52.7493C71.0717 53.9323 70.0469 54.8663 68.8877 54.6302C65.2186 53.8826 62.07 52.2003 59.416 49.6038C55.708 45.9761 53.8545 41.2377 53.8545 35.4631C53.8545 29.6884 55.708 25.0239 59.416 21.3962C63.1241 17.7685 67.7966 15.918 73.507 15.918Z";
|
|
26
24
|
function StagePanel({ shadow = true, className, children, ...props }) {
|
|
27
|
-
return (_jsxs(Panel, { inset: "flush", shadow: shadow, "data-slot": "stage-panel", className: cn("relative overflow-hidden", className), ...props, children: [_jsx("span", { "aria-hidden": "true", className: "pointer-events-none absolute inset-0 [background-image:repeating-linear-gradient(to_right,color-mix(in_oklch,currentColor_7%,transparent)_0_1px,transparent_1px_64px),repeating-linear-gradient(to_bottom,color-mix(in_oklch,currentColor_7%,transparent)_0_1px,transparent_1px_64px)]" }), _jsx("span", { "aria-hidden": "true", className: "pointer-events-none absolute -right-[3%] -bottom-[14%] w-[clamp(180px,24vw,300px)] text-[color-mix(in_oklch,currentColor_10%,transparent)]", children: _jsx("svg", { viewBox: "41.58 3.28 64 64", fill: "currentColor", className: "h-auto w-full", children: _jsx("path", { d:
|
|
25
|
+
return (_jsxs(Panel, { inset: "flush", shadow: shadow, "data-slot": "stage-panel", className: cn("relative overflow-hidden", className), ...props, children: [_jsx("span", { "aria-hidden": "true", className: "pointer-events-none absolute inset-0 [background-image:repeating-linear-gradient(to_right,color-mix(in_oklch,currentColor_7%,transparent)_0_1px,transparent_1px_64px),repeating-linear-gradient(to_bottom,color-mix(in_oklch,currentColor_7%,transparent)_0_1px,transparent_1px_64px)]" }), _jsx("span", { "aria-hidden": "true", className: "pointer-events-none absolute -right-[3%] -bottom-[14%] w-[clamp(180px,24vw,300px)] text-[color-mix(in_oklch,currentColor_10%,transparent)]", children: _jsx("svg", { viewBox: "41.58 3.28 64 64", fill: "currentColor", className: "h-auto w-full", children: _jsx("path", { d: SOCKET_GLYPH_PATH }) }) }), _jsx("div", { className: "relative", children: children })] }));
|
|
28
26
|
}
|
|
29
27
|
export { StagePanel };
|
|
30
28
|
//# sourceMappingURL=stage-panel.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stage-panel.js","sourceRoot":"","sources":["../../src/blocks/stage-panel.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAA;AAC3C,OAAO,EAAE,EAAE,EAAE,MAAM,oBAAoB,CAAA;AAEvC;;;;;;;;;;;;;;;;;;GAkBG;AAEH
|
|
1
|
+
{"version":3,"file":"stage-panel.js","sourceRoot":"","sources":["../../src/blocks/stage-panel.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AACtD,OAAO,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAA;AAC3C,OAAO,EAAE,EAAE,EAAE,MAAM,oBAAoB,CAAA;AAEvC;;;;;;;;;;;;;;;;;;GAkBG;AAEH,SAAS,UAAU,CAAC,EAClB,MAAM,GAAG,IAAI,EACb,SAAS,EACT,QAAQ,EACR,GAAG,KAAK,EAGT;IACC,OAAO,CACL,MAAC,KAAK,IACJ,KAAK,EAAC,OAAO,EACb,MAAM,EAAE,MAAM,eACJ,aAAa,EACvB,SAAS,EAAE,EAAE,CAAC,0BAA0B,EAAE,SAAS,CAAC,KAChD,KAAK,aAET,8BACc,MAAM,EAClB,SAAS,EAAC,wRAAwR,GAClS,EACF,8BACc,MAAM,EAClB,SAAS,EAAC,4IAA4I,YAEtJ,cAAK,OAAO,EAAC,kBAAkB,EAAC,IAAI,EAAC,cAAc,EAAC,SAAS,EAAC,eAAe,YAI3E,eAAM,CAAC,EAAE,iBAAiB,GAAI,GAC1B,GACD,EAEP,cAAK,SAAS,EAAC,UAAU,YAAE,QAAQ,GAAO,IACpC,CACT,CAAA;AACH,CAAC;AAED,OAAO,EAAE,UAAU,EAAE,CAAA"}
|
|
@@ -14,11 +14,31 @@
|
|
|
14
14
|
* One deliberate change. v0's badge is 26px, which is on no step of the 4px
|
|
15
15
|
* spacing ramp. This is 24px (`size-6`), which is. Two pixels, and it stops the
|
|
16
16
|
* component being the reason someone thinks the ramp has exceptions.
|
|
17
|
+
*
|
|
18
|
+
* ## `tone="outline"` (#262)
|
|
19
|
+
*
|
|
20
|
+
* The install blocks number a sequence — ChatGPT's two connector steps, Claude's
|
|
21
|
+
* two — inside a pane that already carries a filled brand badge on the column
|
|
22
|
+
* beside it. Two filled pills of two different brand colours in one pane is the
|
|
23
|
+
* exact collision the note above warns about ("do not put an accent button beside
|
|
24
|
+
* one"), so those numerals are drawn as a hairline circle with the body colour
|
|
25
|
+
* inside instead.
|
|
26
|
+
*
|
|
27
|
+
* It is a TONE and not a second component because everything else about the item
|
|
28
|
+
* — the `<li>`, the aria-hidden numeral, the title, the body slot — is identical,
|
|
29
|
+
* and a fork would be a second place for the `<ol>` rule to be forgotten.
|
|
30
|
+
* `default` paints exactly what it painted before.
|
|
17
31
|
*/
|
|
32
|
+
declare const TONES: {
|
|
33
|
+
readonly default: "bg-cyan font-bold text-on-accent";
|
|
34
|
+
readonly outline: "border border-line bg-(--cg-hover) font-medium text-body";
|
|
35
|
+
};
|
|
18
36
|
declare function StepList({ className, ...props }: React.ComponentProps<"ol">): import("react").JSX.Element;
|
|
19
|
-
declare function StepItem({ index, title, className, children, ...props }: React.ComponentProps<"li"> & {
|
|
37
|
+
declare function StepItem({ index, title, tone, className, children, ...props }: React.ComponentProps<"li"> & {
|
|
20
38
|
index: number;
|
|
21
39
|
title: string;
|
|
40
|
+
/** `outline` is the hairline numeral, for a pane that already has a filled badge. */
|
|
41
|
+
tone?: keyof typeof TONES;
|
|
22
42
|
}): import("react").JSX.Element;
|
|
23
43
|
export { StepItem, StepList };
|
|
24
44
|
//# sourceMappingURL=step-item.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"step-item.d.ts","sourceRoot":"","sources":["../../src/blocks/step-item.tsx"],"names":[],"mappings":"AAEA
|
|
1
|
+
{"version":3,"file":"step-item.d.ts","sourceRoot":"","sources":["../../src/blocks/step-item.tsx"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,QAAA,MAAM,KAAK;;;CAUD,CAAA;AAEV,iBAAS,QAAQ,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,IAAI,CAAC,+BAepE;AAED,iBAAS,QAAQ,CAAC,EAChB,KAAK,EACL,KAAK,EACL,IAAgB,EAChB,SAAS,EACT,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,IAAI,CAAC,GAAG;IAC9B,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,qFAAqF;IACrF,IAAI,CAAC,EAAE,MAAM,OAAO,KAAK,CAAA;CAC1B,+BA0BA;AAED,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAA"}
|
package/dist/blocks/step-item.js
CHANGED
|
@@ -16,7 +16,32 @@ import { cn } from "../lib/cloudgrid-cn.js";
|
|
|
16
16
|
* One deliberate change. v0's badge is 26px, which is on no step of the 4px
|
|
17
17
|
* spacing ramp. This is 24px (`size-6`), which is. Two pixels, and it stops the
|
|
18
18
|
* component being the reason someone thinks the ramp has exceptions.
|
|
19
|
+
*
|
|
20
|
+
* ## `tone="outline"` (#262)
|
|
21
|
+
*
|
|
22
|
+
* The install blocks number a sequence — ChatGPT's two connector steps, Claude's
|
|
23
|
+
* two — inside a pane that already carries a filled brand badge on the column
|
|
24
|
+
* beside it. Two filled pills of two different brand colours in one pane is the
|
|
25
|
+
* exact collision the note above warns about ("do not put an accent button beside
|
|
26
|
+
* one"), so those numerals are drawn as a hairline circle with the body colour
|
|
27
|
+
* inside instead.
|
|
28
|
+
*
|
|
29
|
+
* It is a TONE and not a second component because everything else about the item
|
|
30
|
+
* — the `<li>`, the aria-hidden numeral, the title, the body slot — is identical,
|
|
31
|
+
* and a fork would be a second place for the `<ol>` rule to be forgotten.
|
|
32
|
+
* `default` paints exactly what it painted before.
|
|
19
33
|
*/
|
|
34
|
+
const TONES = {
|
|
35
|
+
// No border at all on the default, rather than a transparent one. `size-6`
|
|
36
|
+
// is a border-box, so a 1px transparent ring would quietly shrink the
|
|
37
|
+
// numeral's content area by two pixels on every existing step list.
|
|
38
|
+
default: "bg-cyan font-bold text-on-accent",
|
|
39
|
+
// `bg-(--cg-hover)` rather than `bg-subtle`: --cg-surface-subtle is declared at
|
|
40
|
+
// :root only, so on ink it freezes to a near-white lavender and the numeral
|
|
41
|
+
// becomes a white disc. --cg-hover is the one ground token declared in all
|
|
42
|
+
// three scopes. See the FIELD note in prompt-block.tsx.
|
|
43
|
+
outline: "border border-line bg-(--cg-hover) font-medium text-body",
|
|
44
|
+
};
|
|
20
45
|
function StepList({ className, ...props }) {
|
|
21
46
|
return (_jsx("ol", {
|
|
22
47
|
// Explicit, and load-bearing. WebKit drops the implicit `list` role from an
|
|
@@ -27,8 +52,8 @@ function StepList({ className, ...props }) {
|
|
|
27
52
|
// in review on #42.
|
|
28
53
|
role: "list", "data-slot": "step-list", className: cn("flex list-none flex-col gap-5 p-0", className), ...props }));
|
|
29
54
|
}
|
|
30
|
-
function StepItem({ index, title, className, children, ...props }) {
|
|
31
|
-
return (_jsxs("li", { "data-slot": "step-item", className: cn("flex items-start gap-4", className), ...props, children: [_jsx("span", { "aria-hidden": "true", className: "flex size-6 shrink-0 items-center justify-center rounded-pill
|
|
55
|
+
function StepItem({ index, title, tone = "default", className, children, ...props }) {
|
|
56
|
+
return (_jsxs("li", { "data-slot": "step-item", className: cn("flex items-start gap-4", className), ...props, children: [_jsx("span", { "aria-hidden": "true", "data-slot": "step-item-numeral", "data-tone": tone, className: cn("flex size-6 shrink-0 items-center justify-center rounded-pill text-caption", TONES[tone]), children: index }), _jsxs("div", { className: "flex min-w-0 flex-1 flex-col gap-2", children: [_jsx("span", { className: "text-heading-sm font-medium text-ink", children: title }), children ? _jsx("div", { className: "text-body-sm text-body", children: children }) : null] })] }));
|
|
32
57
|
}
|
|
33
58
|
export { StepItem, StepList };
|
|
34
59
|
//# sourceMappingURL=step-item.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"step-item.js","sourceRoot":"","sources":["../../src/blocks/step-item.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,oBAAoB,CAAA;AAEvC
|
|
1
|
+
{"version":3,"file":"step-item.js","sourceRoot":"","sources":["../../src/blocks/step-item.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,oBAAoB,CAAA;AAEvC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,MAAM,KAAK,GAAG;IACZ,2EAA2E;IAC3E,sEAAsE;IACtE,oEAAoE;IACpE,OAAO,EAAE,kCAAkC;IAC3C,gFAAgF;IAChF,4EAA4E;IAC5E,2EAA2E;IAC3E,wDAAwD;IACxD,OAAO,EAAE,0DAA0D;CAC3D,CAAA;AAEV,SAAS,QAAQ,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAA8B;IACnE,OAAO,CACL;QACE,4EAA4E;QAC5E,4EAA4E;QAC5E,wEAAwE;QACxE,2EAA2E;QAC3E,0EAA0E;QAC1E,oBAAoB;QACpB,IAAI,EAAC,MAAM,eACD,WAAW,EACrB,SAAS,EAAE,EAAE,CAAC,mCAAmC,EAAE,SAAS,CAAC,KACzD,KAAK,GACT,CACH,CAAA;AACH,CAAC;AAED,SAAS,QAAQ,CAAC,EAChB,KAAK,EACL,KAAK,EACL,IAAI,GAAG,SAAS,EAChB,SAAS,EACT,QAAQ,EACR,GAAG,KAAK,EAMT;IACC,OAAO,CACL,2BACY,WAAW,EACrB,SAAS,EAAE,EAAE,CAAC,wBAAwB,EAAE,SAAS,CAAC,KAC9C,KAAK,aAET,8BACc,MAAM,eACR,mBAAmB,eAClB,IAAI,EACf,SAAS,EAAE,EAAE,CACX,4EAA4E,EAC5E,KAAK,CAAC,IAAI,CAAC,CACZ,YAEA,KAAK,GACD,EACP,eAAK,SAAS,EAAC,oCAAoC,aACjD,eAAM,SAAS,EAAC,sCAAsC,YAAE,KAAK,GAAQ,EAGpE,QAAQ,CAAC,CAAC,CAAC,cAAK,SAAS,EAAC,wBAAwB,YAAE,QAAQ,GAAO,CAAC,CAAC,CAAC,IAAI,IACvE,IACH,CACN,CAAA;AACH,CAAC;AAED,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool-logo.d.ts","sourceRoot":"","sources":["../../src/blocks/tool-logo.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"tool-logo.d.ts","sourceRoot":"","sources":["../../src/blocks/tool-logo.tsx"],"names":[],"mappings":"AAoDA,iBAAS,QAAQ,CAAC,EAChB,IAAI,EACJ,IAAI,EACJ,GAAG,EACH,IAAS,EACT,IAAc,EACd,YAAgB,EAChB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,MAAM,CAAC,EAAE,KAAK,CAAC,GAAG;IAC7C,qEAAqE;IACrE,IAAI,EAAE,MAAM,CAAA;IACZ,qEAAqE;IACrE,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACtB,kFAAkF;IAClF,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,uEAAuE;IACvE,IAAI,CAAC,EAAE,OAAO,GAAG,KAAK,CAAA;IACtB,6EAA6E;IAC7E,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB,+BA8CA;AAED,OAAO,EAAE,QAAQ,EAAE,CAAA"}
|
package/dist/blocks/tool-logo.js
CHANGED
|
@@ -3,12 +3,16 @@ import { cn } from "../lib/cloudgrid-cn.js";
|
|
|
3
3
|
/**
|
|
4
4
|
* Renders a tool's brand mark at a consistent size and weight.
|
|
5
5
|
*
|
|
6
|
-
* **This
|
|
7
|
-
* split is deliberate: how a mark is sized and
|
|
8
|
-
*
|
|
9
|
-
* when the design changes
|
|
10
|
-
*
|
|
11
|
-
*
|
|
6
|
+
* **This component holds no marks; the package does.** It is a renderer, and the
|
|
7
|
+
* caller supplies the SVG. That split is still deliberate: how a mark is sized and
|
|
8
|
+
* coloured is design-system work, and which marks exist changes when a partnership
|
|
9
|
+
* is signed, not when the design changes.
|
|
10
|
+
*
|
|
11
|
+
* The original note said the library ships no marks at all. That stopped being true
|
|
12
|
+
* when `tool-marks.tsx` arrived with the vendor set and each one's brand hex, and
|
|
13
|
+
* the founder's ruling of 2026-10-05 (#266) settles it: the install content, and
|
|
14
|
+
* the marks it names, ship in this package. Take a mark from `TOOL_MARKS` and pass
|
|
15
|
+
* it here; `CloudGridInstall` does exactly that for every tool tab.
|
|
12
16
|
*
|
|
13
17
|
* It is also the shape `CompareTable` and `HubIndex` already assume, both of which
|
|
14
18
|
* take the mark from the caller.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool-logo.js","sourceRoot":"","sources":["../../src/blocks/tool-logo.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,oBAAoB,CAAA;AAEvC
|
|
1
|
+
{"version":3,"file":"tool-logo.js","sourceRoot":"","sources":["../../src/blocks/tool-logo.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,oBAAoB,CAAA;AAEvC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AAEH,mFAAmF;AACnF,SAAS,SAAS,CAAC,GAAW;IAC5B,MAAM,CAAC,GAAG,QAAQ,CAAC,GAAG,EAAE,EAAE,CAAC,CAAA;IAC3B,OAAO,MAAM,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,GAAG,GAAG,CAAC,GAAG,MAAM,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,GAAG,CAAC,GAAG,MAAM,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,CAAA;AACpF,CAAC;AAED,SAAS,QAAQ,CAAC,EAChB,IAAI,EACJ,IAAI,EACJ,GAAG,EACH,IAAI,GAAG,EAAE,EACT,IAAI,GAAG,OAAO,EACd,YAAY,GAAG,CAAC,EAChB,SAAS,EACT,GAAG,KAAK,EAaT;IACC,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,OAAO,CACL,4BACY,WAAW,iBACT,MAAM,EAClB,KAAK,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,GAAG,GAAG,EAAE,EAC1D,SAAS,EAAE,EAAE,CACX,2GAA2G,EAC3G,SAAS,CACV,KACG,KAAK,YAER,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAC/B,CACR,CAAA;IACH,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,KAAK,OAAO,IAAI,GAAG,IAAI,SAAS,CAAC,GAAG,CAAC,GAAG,EAAE,CAAA;IAE7D,OAAO,CACL,4BACY,WAAW,iBAGT,MAAM,EAClB,KAAK,EAAE;YACL,KAAK,EAAE,IAAI;YACX,MAAM,EAAE,IAAI;YACZ,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;SAC/C,EACD,SAAS,EAAE,EAAE,CACX,oEAAoE,EACpE,SAAS,CACV,KACG,KAAK,YAER,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CACpB,IAAI,CACL,CAAC,CAAC,CAAC,CACF,eAAM,KAAK,EAAE,EAAE,SAAS,EAAE,SAAS,YAAY,GAAG,EAAE,EAAE,SAAS,EAAC,uBAAuB,YACpF,IAAI,GACA,CACR,GACI,CACR,CAAA;AACH,CAAC;AAED,OAAO,EAAE,QAAQ,EAAE,CAAA"}
|
|
@@ -9,11 +9,38 @@ import { PageHeading } from "./page-heading.js";
|
|
|
9
9
|
* were heading for two implementations of one screen, which is how the two come
|
|
10
10
|
* to disagree about the same setup with nothing to catch it.
|
|
11
11
|
*
|
|
12
|
-
* ## The
|
|
12
|
+
* ## The repaint that the PROVISIONAL note was waiting for (#262)
|
|
13
13
|
*
|
|
14
14
|
* Founder, 2026-08-25: a better component design exists and is not ready yet —
|
|
15
|
-
* "make this nice and we will replace the full component shortly".
|
|
16
|
-
*
|
|
15
|
+
* "make this nice and we will replace the full component shortly". It arrived on
|
|
16
|
+
* 2026-09-23, and this file is that design: the bordered method pills, the tool
|
|
17
|
+
* strip with a glyph per group and a rule under it, the brand fill on the
|
|
18
|
+
* selected tab, the 60/40 pane with a badge per column, and `PromptBlock` and
|
|
19
|
+
* `CommandField` in place of an ink slab.
|
|
20
|
+
*
|
|
21
|
+
* The bet the original note made paid off exactly as written: the props were the
|
|
22
|
+
* contract and the class lists were the disposable half, so the repaint changed
|
|
23
|
+
* what this renders and not what a consumer passes. Everything the note protected
|
|
24
|
+
* is untouched — the methods x tools x steps engine, the render-time fallbacks,
|
|
25
|
+
* the two reconcile-after-paint effects, the grouping that rides on each tab's
|
|
26
|
+
* accessible name.
|
|
27
|
+
*
|
|
28
|
+
* ## THIS IS A COMPONENT, NOT A PAGE (founder ruling, 2026-09-23)
|
|
29
|
+
*
|
|
30
|
+
* The first pass of #262 also grew a `header` (a wordmark over a row of vendor
|
|
31
|
+
* logos), a `layout: "bare" | "card"`, a `prompt` slot and a `footnote` — enough
|
|
32
|
+
* to rebuild the marketing install page inside the library, which is what it then
|
|
33
|
+
* did in the gallery. Rejected in review, in as many words: *"I didn't mean you
|
|
34
|
+
* will design it similarly to what I showed you. The entire idea was to design it
|
|
35
|
+
* the way it already looks like in the UI library. The problem now is that we
|
|
36
|
+
* have two versions."*
|
|
37
|
+
*
|
|
38
|
+
* All four are gone. A wordmark is a page's, a hero headline is a page's, and a
|
|
39
|
+
* footer with source links is a page's; this renders a title, a sub, a control
|
|
40
|
+
* and a pane, on whichever of the library's surfaces it is dropped on. If a
|
|
41
|
+
* marketing page wants the rest, the page composes it around this.
|
|
42
|
+
*
|
|
43
|
+
* The original reasoning, kept because it is still why the repaint was cheap:
|
|
17
44
|
*
|
|
18
45
|
* - **The props are the contract.** `tools`, `value`/`defaultValue`/
|
|
19
46
|
* `onValueChange`, `onContinue`. A redesign changes what this renders, not
|
|
@@ -28,13 +55,61 @@ import { PageHeading } from "./page-heading.js";
|
|
|
28
55
|
* Do not build anything on the internals — the slots and the class lists are
|
|
29
56
|
* the disposable half.
|
|
30
57
|
*
|
|
31
|
-
* ##
|
|
58
|
+
* ## The selected tab is the brand FILL, and that closes #223
|
|
59
|
+
*
|
|
60
|
+
* The selected tool tab used to be `bg-code`/`text-on-code`, the library's own
|
|
61
|
+
* ink pair. `--cg-surface-code` is `#222` in all three scopes and that is also
|
|
62
|
+
* the ink GROUND, so inside `data-cg-surface="ink"` the pill was the colour of
|
|
63
|
+
* what sits behind it. The backlog offered two ways out — a new semantic token
|
|
64
|
+
* declared in all three scopes, or a ruling that this is not an ink component —
|
|
65
|
+
* and the design answers it a third way that needs neither: the brand fill,
|
|
66
|
+
* which is what `hub.html` draws (`.tab.on{background:var(--cg-primary)}`).
|
|
67
|
+
*
|
|
68
|
+
* `--cg-primary` and `--cg-text-on-primary` are declared at `:root` and
|
|
69
|
+
* redeclared on NEITHER surface, so the pair is one value everywhere and carries
|
|
70
|
+
* its own ground, exactly the construction `Button`'s `cta` variant relies on
|
|
71
|
+
* (#225, #236). Measured on all three gallery strips: the selected label is
|
|
72
|
+
* 5.84:1 on its own pill in every scope, the same number by construction.
|
|
73
|
+
*
|
|
74
|
+
* ONE CAVEAT, recorded rather than fixed. On the PURPLE PANEL the pill's ground
|
|
75
|
+
* is the panel's own hue, so what separates the selected tab from the strip
|
|
76
|
+
* around it there is the 10% white wash on the bar plus the idle labels being
|
|
77
|
+
* 82% white against the selected one's 100% — a much smaller margin than on the
|
|
78
|
+
* page or on ink, where the pill reads at a glance. The label itself is legible
|
|
79
|
+
* everywhere, which is the floor; "which tab is selected" is quieter on that one
|
|
80
|
+
* surface. Fixing it means a panel-scoped selected treatment, which is a design
|
|
81
|
+
* decision and not a worker's to make. The strip is on the gallery's panel
|
|
82
|
+
* surface so it stays visible.
|
|
32
83
|
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
84
|
+
* ## THE CALLER CHOOSES WHAT IS ON SCREEN
|
|
85
|
+
*
|
|
86
|
+
* `tools` and `methods` are lists, and every one of them is the caller's: which
|
|
87
|
+
* tools, which methods, and in what order. Two tools is a valid strip. One method
|
|
88
|
+
* is a valid axis. This component renders what it is handed and sorts nothing,
|
|
89
|
+
* filters nothing by its own opinion and adds nothing that was not passed —
|
|
90
|
+
* founder, 2026-09-23: *"it's important to pick what I want to show each time —
|
|
91
|
+
* not to show all if I want, only two integrations if I want, or only CLI or only
|
|
92
|
+
* MCP."*
|
|
93
|
+
*
|
|
94
|
+
* The one thing it decides for itself is that a control with a single option is
|
|
95
|
+
* not a control. Pass one method and the method axis still works — the pane is
|
|
96
|
+
* still read from `steps[method]` — but no pill row renders, because a row of one
|
|
97
|
+
* is furniture for a choice nobody has. Pass none and there is no axis at all,
|
|
98
|
+
* which is the older shape where a tool carries a single `prompt`.
|
|
99
|
+
*
|
|
100
|
+
* ## The engine, not the content (and the package ships the content now)
|
|
101
|
+
*
|
|
102
|
+
* This component still carries no CloudGrid prompt, no MCP command and no tool
|
|
103
|
+
* list of its own. It renders the tools it is handed and reports which is
|
|
104
|
+
* selected, and that is what lets one engine serve every configuration.
|
|
105
|
+
*
|
|
106
|
+
* What changed is where the strings live. The line #117, #121 and #126 drew was
|
|
107
|
+
* that the PACKAGE ships no content at all. Founder ruling 2026-10-05 (#266)
|
|
108
|
+
* reverses that: the old integrations app is discontinued and every install
|
|
109
|
+
* panel takes its words from this library. They are `install-content.ts`, plain
|
|
110
|
+
* data with no React in it, and `CloudGridInstall` hands them to this component
|
|
111
|
+
* along with the fetch prompt and the footer. A surface that wants the install
|
|
112
|
+
* panel renders `CloudGridInstall`; this file stays the presentational half.
|
|
38
113
|
*
|
|
39
114
|
* ## Why tabs and not the picker beside it
|
|
40
115
|
*
|
|
@@ -69,6 +144,17 @@ export interface ToolSetupMethod {
|
|
|
69
144
|
export interface ToolSetupGroup {
|
|
70
145
|
value: string;
|
|
71
146
|
label: string;
|
|
147
|
+
/**
|
|
148
|
+
* A glyph in place of the visible label. The design labels a run of tools with
|
|
149
|
+
* a terminal or a chat bubble rather than a word, so the strip stays one row.
|
|
150
|
+
*
|
|
151
|
+
* It replaces the label ON SCREEN only. The label is still required and is
|
|
152
|
+
* still what reaches assistive tech, through each tab's own accessible name —
|
|
153
|
+
* see the note on the strip below for why the visible marker cannot carry it.
|
|
154
|
+
* A glyph with no words behind it would take the grouping away from everyone
|
|
155
|
+
* who is not looking at the screen.
|
|
156
|
+
*/
|
|
157
|
+
icon?: React.ReactNode;
|
|
72
158
|
}
|
|
73
159
|
/**
|
|
74
160
|
* One step of a pane.
|
|
@@ -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;
|
|
1
|
+
{"version":3,"file":"tool-setup.d.ts","sourceRoot":"","sources":["../../src/blocks/tool-setup.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1,21 +1,28 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
3
|
import * as React from "react";
|
|
4
|
+
import { Badge } from "../ui/badge.js";
|
|
4
5
|
import { Button } from "../ui/button.js";
|
|
5
6
|
import { CodeBlock } from "../ui/code-block.js";
|
|
7
|
+
import { CommandField } from "./command-field.js";
|
|
6
8
|
import { PageHeading } from "./page-heading.js";
|
|
9
|
+
import { PromptBlock } from "./prompt-block.js";
|
|
7
10
|
import { Separator } from "../ui/separator.js";
|
|
8
11
|
import { StepItem, StepList } from "./step-item.js";
|
|
9
12
|
import { Tabs, TabsContent, TabsList, TabsTrigger } from "../ui/tabs.js";
|
|
10
13
|
import { cn } from "../lib/cloudgrid-cn.js";
|
|
11
14
|
/**
|
|
12
|
-
* The tab
|
|
13
|
-
* "ChatGPT Desktop", and a strip that truncates them makes two tools read alike.
|
|
15
|
+
* The tab: the tool's mark, then its name, in one 36px row.
|
|
14
16
|
*
|
|
15
17
|
* The overrides earn their place: `TabsList` pins itself to `h-8` for a compact
|
|
16
|
-
* strip
|
|
17
|
-
*
|
|
18
|
-
* goes auto and
|
|
18
|
+
* strip and `TabsTrigger` sets `flex-1`, and eight tools at a fixed list height
|
|
19
|
+
* is either a horizontal scrollbar on a laptop or a row painted over by the
|
|
20
|
+
* panel below it. The list goes `h-auto!` and wraps instead — see the note at
|
|
21
|
+
* the call site, which is where that one cost a session.
|
|
22
|
+
*
|
|
23
|
+
* The mark is sized by the CALLER, the way every glyph in this library is: a
|
|
24
|
+
* mark carries no width or height of its own, `ToolLogo` sizes by an inline
|
|
25
|
+
* style, and a class here could not beat it anyway. The design draws 15px.
|
|
19
26
|
*/
|
|
20
27
|
const TRIGGER_CLASS = cn(
|
|
21
28
|
// No `grow`. It stretched every tab to consume the row, so a strip that
|
|
@@ -26,20 +33,49 @@ const TRIGGER_CLASS = cn(
|
|
|
26
33
|
// `basis-auto` rather than a fixed basis for the same reason: a tab is as wide
|
|
27
34
|
// as its label, and forcing "Cursor" to the width of "ChatGPT Desktop" is the
|
|
28
35
|
// same mistake one level down.
|
|
29
|
-
|
|
30
|
-
//
|
|
31
|
-
//
|
|
32
|
-
//
|
|
33
|
-
//
|
|
34
|
-
|
|
35
|
-
|
|
36
|
+
//
|
|
37
|
+
// One row per tab since #262: the mark sits BESIDE the label at 36px rather
|
|
38
|
+
// than above it at 60. The strip still wraps rather than scrolling, which is
|
|
39
|
+
// what `tool-setup.spec.ts` measures and what keeps a laptop from hiding the
|
|
40
|
+
// eighth tool behind a horizontal scrollbar.
|
|
41
|
+
"h-9 flex-none basis-auto gap-2 whitespace-nowrap", "rounded-xs border border-transparent px-2.5 text-caption font-normal text-body",
|
|
42
|
+
// THE SELECTED PILL, and the answer to #223. `bg-code`/`text-on-code` was the
|
|
43
|
+
// ink ground itself, so on `data-cg-surface="ink"` the pill was the colour of
|
|
44
|
+
// what was behind it. `--cg-primary` and `--cg-text-on-primary` are :root-only
|
|
45
|
+
// and never redeclared per scope, so this pair is one value in all three and
|
|
46
|
+
// carries its own ground. See the module docblock.
|
|
47
|
+
"data-active:border-brand data-active:bg-brand data-active:text-on-primary", "hover:bg-card hover:text-ink data-active:hover:bg-brand-press data-active:hover:text-on-primary");
|
|
48
|
+
/**
|
|
49
|
+
* The method pills, inside their own bordered container.
|
|
50
|
+
*
|
|
51
|
+
* Same selected treatment as the tool strip, deliberately: two controls stacked
|
|
52
|
+
* on one screen that mean "pick one of these" should not say it two different
|
|
53
|
+
* ways, and the method pill is the one a reader meets first.
|
|
54
|
+
*/
|
|
55
|
+
const METHOD_TRIGGER_CLASS = cn("h-[30px] flex-none basis-auto rounded-xs px-3 text-caption font-normal text-faint", "data-active:bg-brand data-active:text-on-primary", "hover:text-ink data-active:hover:bg-brand-press data-active:hover:text-on-primary");
|
|
36
56
|
/** The body of one step: prompt, command and link, in that order. */
|
|
37
57
|
function StepBody({ step }) {
|
|
38
|
-
return (_jsxs(_Fragment, { children: [step.body ? _jsx("div", { className: "text-
|
|
58
|
+
return (_jsxs(_Fragment, { children: [step.body ? _jsx("div", { className: "text-caption text-body", children: step.body }) : null, step.prompt ? _jsx(PromptBlock, { prompt: step.prompt, clip: true }) : null, step.code ? _jsx(CommandField, { command: step.code }) : null, step.link ? (_jsxs(Button, { render: _jsx("a", { href: step.link.href, target: "_blank", rel: "noopener noreferrer" }),
|
|
39
59
|
// The rendered element is an anchor, so Base UI must not assume native
|
|
40
60
|
// button semantics.
|
|
41
61
|
nativeButton: false, variant: step.link.primary ? "default" : "secondary", size: "sm", className: "w-fit gap-2", children: [step.link.icon, step.link.label] })) : null] }));
|
|
42
62
|
}
|
|
63
|
+
/**
|
|
64
|
+
* The column geometry both pane shapes share.
|
|
65
|
+
*
|
|
66
|
+
* A 22px gutter and a hairline BETWEEN columns, never around them: the live
|
|
67
|
+
* block zeroes the outer gutters in its bare variant and the note in its
|
|
68
|
+
* stylesheet says what happens otherwise — "column two's text then started hard
|
|
69
|
+
* against the divider line". Expressing it as a right gutter on all but the last
|
|
70
|
+
* and a left gutter on all but the first gets the same result with no first/last
|
|
71
|
+
* exception to keep in sync.
|
|
72
|
+
*
|
|
73
|
+
* All of it is `md:`-prefixed. Below that the columns stack, and a vertical rule
|
|
74
|
+
* beside a full-width column is a line down the middle of nothing.
|
|
75
|
+
*/
|
|
76
|
+
function columnEdges(i, count) {
|
|
77
|
+
return cn(i < count - 1 && "md:border-r md:border-hairline md:pr-[22px]", i > 0 && "md:pl-[22px]");
|
|
78
|
+
}
|
|
43
79
|
/**
|
|
44
80
|
* One pane: the steps for a tool under the selected method.
|
|
45
81
|
*
|
|
@@ -50,15 +86,42 @@ function StepBody({ step }) {
|
|
|
50
86
|
*/
|
|
51
87
|
function StepPane({ steps }) {
|
|
52
88
|
const alternatives = Boolean(steps[0]?.label);
|
|
53
|
-
const cols = steps.length >= 3
|
|
89
|
+
const cols = steps.length >= 3
|
|
90
|
+
? "md:grid-cols-3"
|
|
91
|
+
: steps.length === 2
|
|
92
|
+
? // 60/40, not 50/50. The recommended path carries a five-line prompt and
|
|
93
|
+
// the alternative carries one command, so equal columns give the short
|
|
94
|
+
// one half the screen and wrap the long one. `1.5fr 1fr` is the live
|
|
95
|
+
// block's own ratio.
|
|
96
|
+
"md:grid-cols-[1.5fr_1fr]"
|
|
97
|
+
: "";
|
|
54
98
|
if (alternatives) {
|
|
55
|
-
return (_jsx("div", { className: cn("grid grid-cols-1 gap-6", cols), children: steps.map((step, i) => (_jsxs("div", { className: "flex flex-col gap-
|
|
99
|
+
return (_jsx("div", { "data-slot": "tool-setup-alternatives", className: cn("grid grid-cols-1 gap-6 md:gap-0", cols), children: steps.map((step, i) => (_jsxs("div", { className: cn("flex min-w-0 flex-col gap-2.5", columnEdges(i, steps.length)), children: [_jsx(Badge, { variant: i === 0 ? "default" : "outline", className: "h-6 rounded-pill px-3 font-normal", children: step.label }), _jsx("span", { className: "text-body-sm font-bold text-ink", children: step.title }), _jsx(StepBody, { step: step })] }, i))) }));
|
|
56
100
|
}
|
|
57
|
-
return (
|
|
101
|
+
return (
|
|
102
|
+
// No `data-slot` here: `StepList` spreads props after its own, so one passed
|
|
103
|
+
// in would silently replace `step-list` rather than sit beside it.
|
|
104
|
+
_jsx(StepList, { className: cn("grid grid-cols-1 gap-6 md:gap-0", cols), children: steps.map((step, i) => (_jsx(StepItem, { index: i + 1, title: step.title,
|
|
105
|
+
// The numeral is outlined here rather than the filled cyan default:
|
|
106
|
+
// this pane sits beside one that carries a filled BRAND badge, and two
|
|
107
|
+
// filled pills in two brand colours in one pane is the collision
|
|
108
|
+
// step-item.tsx's own note warns about.
|
|
109
|
+
tone: "outline", className: cn("min-w-0 flex-col gap-2.5", columnEdges(i, steps.length)), children: _jsx(StepBody, { step: step }) }, i))) }));
|
|
58
110
|
}
|
|
59
111
|
function ToolSetup({ tools, methods, groups, method, defaultMethod, onMethodChange, value, defaultValue, onValueChange, title, sub, eyebrow, level = 1, headingSize = "md", continueLabel = "Continue", emptyLabel = "Nothing to set up for this one yet.", onContinue, canContinue = true, footer, className, ...props }) {
|
|
60
112
|
const headingId = React.useId();
|
|
61
113
|
const hasMethods = Boolean(methods?.length);
|
|
114
|
+
/**
|
|
115
|
+
* Whether to draw the method PILLS, which is not the same question as whether
|
|
116
|
+
* there is a method axis.
|
|
117
|
+
*
|
|
118
|
+
* One method is a real axis: `steps` is still keyed by it and the pane is still
|
|
119
|
+
* read from it, so `hasMethods` stays true and every filter and fallback below
|
|
120
|
+
* behaves exactly as it does with three. What a single method does not need is
|
|
121
|
+
* a segmented control with one segment — a choice with one option, drawn as
|
|
122
|
+
* though it were a choice. Founder asked for it here and on the live panel.
|
|
123
|
+
*/
|
|
124
|
+
const showMethods = (methods?.length ?? 0) > 1;
|
|
62
125
|
// ---- the method axis -------------------------------------------------
|
|
63
126
|
const firstMethod = methods?.find((m) => !m.disabled)?.value ?? methods?.[0]?.value;
|
|
64
127
|
const [ownMethod, setOwnMethod] = React.useState(defaultMethod ?? firstMethod);
|
|
@@ -240,15 +303,27 @@ function ToolSetup({ tools, methods, groups, method, defaultMethod, onMethodChan
|
|
|
240
303
|
out.push({ group: null, items: ungrouped });
|
|
241
304
|
return out;
|
|
242
305
|
}, [groups, visible]);
|
|
243
|
-
return (_jsxs("section", { "data-slot": "tool-setup", className: cn("flex flex-col gap-
|
|
306
|
+
return (_jsxs("section", { "data-slot": "tool-setup", className: cn("flex flex-col gap-6", className), ...props, children: [title ? (_jsx(PageHeading, { id: headingId, eyebrow: eyebrow, title: title, sub: sub, size: headingSize, level: level })) : null, showMethods ? (_jsx(Tabs, { value: activeMethod, onValueChange: (next) => changeMethod(String(next)), "data-slot": "tool-setup-methods", children: _jsx(TabsList
|
|
244
307
|
// Same `h-auto!` reasoning as the tool strip below: the strip must
|
|
245
308
|
// be free to grow, and the prefixed `h-8` wins the cascade without
|
|
246
309
|
// the important.
|
|
310
|
+
//
|
|
311
|
+
// The bordered container is the design's: a hairline box on the card
|
|
312
|
+
// ground with 3px of inset, so the selected pill sits INSIDE a track
|
|
313
|
+
// rather than floating on the page. `bg-muted` is what the default
|
|
314
|
+
// variant paints and it is a filled grey track, which is a second
|
|
315
|
+
// ground behind the brand fill.
|
|
247
316
|
, {
|
|
248
317
|
// Same `h-auto!` reasoning as the tool strip below: the strip must
|
|
249
318
|
// be free to grow, and the prefixed `h-8` wins the cascade without
|
|
250
319
|
// the important.
|
|
251
|
-
|
|
320
|
+
//
|
|
321
|
+
// The bordered container is the design's: a hairline box on the card
|
|
322
|
+
// ground with 3px of inset, so the selected pill sits INSIDE a track
|
|
323
|
+
// rather than floating on the page. `bg-muted` is what the default
|
|
324
|
+
// variant paints and it is a filled grey track, which is a second
|
|
325
|
+
// ground behind the brand fill.
|
|
326
|
+
className: "h-auto! w-fit flex-wrap gap-0.5 rounded-sm border border-line bg-card p-[3px]", children: methods.map((m) => (_jsx(TabsTrigger, { value: m.value, disabled: m.disabled, "data-slot": "tool-setup-method", className: METHOD_TRIGGER_CLASS, children: m.label }, m.value))) }) })) : null, visible.length === 0 ? (_jsx("p", { "data-slot": "tool-setup-empty", className: "m-0 rounded-lg border border-hairline bg-card p-5 text-body-sm text-faint", children: emptyLabel })) : (_jsx(Tabs
|
|
252
327
|
// Never undefined: Base UI warns when a value goes from uncontrolled to
|
|
253
328
|
// controlled, which is what an empty strip filling in later would do.
|
|
254
329
|
, {
|
|
@@ -259,37 +334,42 @@ function ToolSetup({ tools, methods, groups, method, defaultMethod, onMethodChan
|
|
|
259
334
|
if (value === undefined)
|
|
260
335
|
setOwnTool(id);
|
|
261
336
|
onValueChange?.(id);
|
|
262
|
-
}, className: "flex flex-col gap-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
337
|
+
}, className: "flex flex-col gap-0", children: _jsxs("div", { className: "flex flex-col overflow-hidden rounded-lg border border-hairline bg-card", children: [_jsx("div", { className: "flex items-center border-b border-hairline bg-(--cg-hover) px-3 py-2", children: _jsx(TabsList
|
|
338
|
+
// Labelled by the lockup when there is one, so the strip is
|
|
339
|
+
// announced as the setup's tool list rather than an unnamed
|
|
340
|
+
// set of tabs.
|
|
341
|
+
, { ...(title ? { "aria-labelledby": headingId } : {}), "data-slot": "tool-setup-tabs",
|
|
342
|
+
// `h-auto!` — important, and that is load-bearing.
|
|
343
|
+
//
|
|
344
|
+
// `tabsListVariants` pins the strip with
|
|
345
|
+
// `group-data-horizontal/tabs:h-8` for a compact single row.
|
|
346
|
+
// Eight tools do not fit one row, so the list must grow — and a
|
|
347
|
+
// bare `h-auto` does not make it: both utilities survive `cn()`
|
|
348
|
+
// because they carry different variant prefixes, and the
|
|
349
|
+
// prefixed rule wins the cascade. Measured, not assumed:
|
|
350
|
+
// `getComputedStyle` reported a 32px list around a 60px tab.
|
|
351
|
+
//
|
|
352
|
+
// The consequence was invisible. The eighth tool wrapped into
|
|
353
|
+
// height that was never reserved and the panel painted straight
|
|
354
|
+
// over it, while every other assertion passed — the tab was
|
|
355
|
+
// present, focusable, correctly announced and correctly
|
|
356
|
+
// painted. It was simply underneath.
|
|
357
|
+
//
|
|
358
|
+
// Important settles it without depending on which utility
|
|
359
|
+
// `cn()` keeps or what order Tailwind emits them in.
|
|
360
|
+
className: "h-auto! w-full flex-wrap justify-start gap-0.5 bg-transparent p-0", children: grouped.map(({ group, items }, gi) => (_jsxs(React.Fragment, { children: [gi > 0 ? (_jsx(Separator, { orientation: "vertical", "aria-hidden": "true", className: "mx-2 h-5 self-center" })) : null, group ? (_jsx("span", { "aria-hidden": "true", "data-slot": "tool-setup-group", "data-group": group.value, className: cn("self-center text-caption text-faint", group.icon
|
|
361
|
+
? "mr-1 inline-flex size-[22px] items-center justify-center [&_svg]:size-3.5"
|
|
362
|
+
: "px-1"), children: group.icon ?? group.label })) : null, items.map((tool) => (_jsxs(TabsTrigger, { value: tool.value, disabled: tool.disabled, "data-slot": "tool-setup-tab", ...(group ? { "aria-label": `${tool.label}, ${group.label}` } : {}), className: TRIGGER_CLASS, children: [tool.mark, tool.label] }, tool.value)))] }, group?.value ?? `ungrouped-${gi}`))) }) }), visible.map((tool) => {
|
|
363
|
+
const pane = hasMethods && activeMethod ? tool.steps?.[activeMethod] : undefined;
|
|
364
|
+
return (_jsx(TabsContent, { value: tool.value, "data-slot": "tool-setup-panel", className: "p-5", children: _jsxs("div", { className: "flex flex-col gap-4", children: [tool.instruction || tool.alternative ? (_jsxs("div", { className: "flex flex-wrap items-baseline justify-between gap-x-4 gap-y-1", children: [tool.instruction ? (_jsx("p", { className: "m-0 text-body-sm text-body", children: tool.instruction })) : (_jsx("span", {})), tool.alternative ? (_jsx("a", { href: tool.alternative.href, "data-slot": "tool-setup-alternative",
|
|
365
|
+
// `--cg-link` is a token but NOT a generated utility —
|
|
366
|
+
// there is no `--color-link`, so `text-link` emits
|
|
367
|
+
// nothing and the link paints as body text. The
|
|
368
|
+
// arbitrary form is how the library reaches an
|
|
369
|
+
// ungenerated token, the same way onboarding-question
|
|
370
|
+
// writes `ring-(--cg-border-strong)`.
|
|
371
|
+
className: "text-body-sm text-(--cg-link) underline-offset-4 hover:text-(--cg-link-hover) hover:underline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring", children: tool.alternative.label })) : null] })) : null, pane?.length ? (_jsx(StepPane, { steps: pane })) : tool.prompt ? (_jsx(CodeBlock, { code: tool.prompt })) : null] }) }, tool.value));
|
|
372
|
+
})] }) })), continueLabel !== null || footer ? (_jsxs("div", { "data-slot": "tool-setup-actions", className: "flex flex-col items-start gap-4", children: [continueLabel !== null ? (_jsx(Button, { type: "button", size: "lg", "data-slot": "tool-setup-continue", onClick: onContinue, disabled: !canContinue, children: continueLabel })) : null, footer] })) : null] }));
|
|
293
373
|
}
|
|
294
374
|
export { ToolSetup };
|
|
295
375
|
//# sourceMappingURL=tool-setup.js.map
|