@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.
Files changed (74) hide show
  1. package/README.md +63 -0
  2. package/dist/blocks/agent-prompt.d.ts +17 -1
  3. package/dist/blocks/agent-prompt.d.ts.map +1 -1
  4. package/dist/blocks/agent-prompt.js +33 -3
  5. package/dist/blocks/agent-prompt.js.map +1 -1
  6. package/dist/blocks/cloudgrid-install.d.ts +67 -0
  7. package/dist/blocks/cloudgrid-install.d.ts.map +1 -0
  8. package/dist/blocks/cloudgrid-install.js +192 -0
  9. package/dist/blocks/cloudgrid-install.js.map +1 -0
  10. package/dist/blocks/command-field.d.ts +38 -0
  11. package/dist/blocks/command-field.d.ts.map +1 -0
  12. package/dist/blocks/command-field.js +70 -0
  13. package/dist/blocks/command-field.js.map +1 -0
  14. package/dist/blocks/drop-zone.d.ts +2 -1
  15. package/dist/blocks/drop-zone.d.ts.map +1 -1
  16. package/dist/blocks/drop-zone.js.map +1 -1
  17. package/dist/blocks/entity-card.d.ts +81 -24
  18. package/dist/blocks/entity-card.d.ts.map +1 -1
  19. package/dist/blocks/entity-card.js +235 -126
  20. package/dist/blocks/entity-card.js.map +1 -1
  21. package/dist/blocks/icons.d.ts +23 -1
  22. package/dist/blocks/icons.d.ts.map +1 -1
  23. package/dist/blocks/icons.js +23 -1
  24. package/dist/blocks/icons.js.map +1 -1
  25. package/dist/blocks/install-content.d.ts +228 -0
  26. package/dist/blocks/install-content.d.ts.map +1 -0
  27. package/dist/blocks/install-content.js +464 -0
  28. package/dist/blocks/install-content.js.map +1 -0
  29. package/dist/blocks/logo.d.ts +70 -1
  30. package/dist/blocks/logo.d.ts.map +1 -1
  31. package/dist/blocks/logo.js +75 -2
  32. package/dist/blocks/logo.js.map +1 -1
  33. package/dist/blocks/phosphor-marks.d.ts +6 -0
  34. package/dist/blocks/phosphor-marks.d.ts.map +1 -1
  35. package/dist/blocks/phosphor-marks.js +9 -0
  36. package/dist/blocks/phosphor-marks.js.map +1 -1
  37. package/dist/blocks/prompt-block.d.ts +57 -0
  38. package/dist/blocks/prompt-block.d.ts.map +1 -0
  39. package/dist/blocks/prompt-block.js +219 -0
  40. package/dist/blocks/prompt-block.js.map +1 -0
  41. package/dist/blocks/stage-panel.d.ts +19 -0
  42. package/dist/blocks/stage-panel.d.ts.map +1 -1
  43. package/dist/blocks/stage-panel.js +2 -4
  44. package/dist/blocks/stage-panel.js.map +1 -1
  45. package/dist/blocks/step-item.d.ts +21 -1
  46. package/dist/blocks/step-item.d.ts.map +1 -1
  47. package/dist/blocks/step-item.js +27 -2
  48. package/dist/blocks/step-item.js.map +1 -1
  49. package/dist/blocks/tool-logo.d.ts.map +1 -1
  50. package/dist/blocks/tool-logo.js +10 -6
  51. package/dist/blocks/tool-logo.js.map +1 -1
  52. package/dist/blocks/tool-setup.d.ts +95 -9
  53. package/dist/blocks/tool-setup.d.ts.map +1 -1
  54. package/dist/blocks/tool-setup.js +129 -49
  55. package/dist/blocks/tool-setup.js.map +1 -1
  56. package/dist/brand/mark-180.png +0 -0
  57. package/dist/brand/mark-192.png +0 -0
  58. package/dist/brand/mark-32.png +0 -0
  59. package/dist/brand/mark-512.png +0 -0
  60. package/dist/brand/mark-inverted-180.png +0 -0
  61. package/dist/brand/mark-inverted-192.png +0 -0
  62. package/dist/brand/mark-inverted-32.png +0 -0
  63. package/dist/brand/mark-inverted-512.png +0 -0
  64. package/dist/brand/mark-inverted.svg +8 -0
  65. package/dist/brand/mark.svg +7 -0
  66. package/dist/index.d.ts +4 -1
  67. package/dist/index.d.ts.map +1 -1
  68. package/dist/index.js +4 -1
  69. package/dist/index.js.map +1 -1
  70. package/package.json +7 -2
  71. package/dist/blocks/plug-method.d.ts +0 -76
  72. package/dist/blocks/plug-method.d.ts.map +0 -1
  73. package/dist/blocks/plug-method.js +0 -30
  74. 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: SOCKET_PATH }) }) }), _jsx("div", { className: "relative", children: children })] }));
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;0EAC0E;AAC1E,MAAM,WAAW,GACf,+oCAA+oC,CAAA;AAEjpC,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,YAC3E,eAAM,CAAC,EAAE,WAAW,GAAI,GACpB,GACD,EAEP,cAAK,SAAS,EAAC,UAAU,YAAE,QAAQ,GAAO,IACpC,CACT,CAAA;AACH,CAAC;AAED,OAAO,EAAE,UAAU,EAAE,CAAA"}
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;;;;;;;;;;;;;;;;GAgBG;AACH,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,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;CACd,+BAqBA;AAED,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAA"}
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"}
@@ -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 bg-cyan text-caption font-bold text-on-accent", 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] })] }));
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;;;;;;;;;;;;;;;;GAgBG;AACH,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,SAAS,EACT,QAAQ,EACR,GAAG,KAAK,EAIT;IACC,OAAO,CACL,2BACY,WAAW,EACrB,SAAS,EAAE,EAAE,CAAC,wBAAwB,EAAE,SAAS,CAAC,KAC9C,KAAK,aAET,8BACc,MAAM,EAClB,SAAS,EAAC,6GAA6G,YAEtH,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
+ {"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":"AAgDA,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"}
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"}
@@ -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 ships no marks.** It is a renderer, and the caller supplies the SVG. That
7
- * split is deliberate: how a mark is sized and coloured is design-system work, but
8
- * *which* marks exist is content. The set changes when a partnership is signed, not
9
- * when the design changes, and vendors rebrand on their own schedule. A library
10
- * holding fourteen logos carries a maintenance burden that is not about UI, plus a
11
- * trademark surface that travels to every consumer who installs it.
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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;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"}
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 visual treatment here is PROVISIONAL
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". So this file
16
- * is written to be *replaced*, and the effort went where replacement is cheap:
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
- * ## Presentation only
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
- * The line #117 and #121 drew, held again. This component carries no CloudGrid
34
- * prompt, no MCP command, no tool list, and no idea what comes next. It renders
35
- * the tools it is handed and reports which is selected. That is exactly what
36
- * lets one component serve onboarding and a public guide: the strings differ,
37
- * the screen does not.
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":"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"}
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. Sized for two lines because the real labels are "Claude Desktop" and
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, and `TabsTrigger` sets `flex-1` and `whitespace-nowrap`. Eight tools at
17
- * a fixed height with nowrap is a horizontal scrollbar on a laptop, so height
18
- * goes auto and the list wraps to a second row instead.
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
- "h-auto min-h-[3.75rem] flex-none basis-auto flex-col gap-0.5 whitespace-normal", "rounded-lg px-3 py-2 text-center text-body-sm leading-tight",
30
- // The dark selected pill is `bg-code`/`text-on-code` — the library's OWN
31
- // ink-surface pair, the one AgentPrompt and CodeBlock already paint with. A
32
- // first pass invented `bg-ink-strong`/`text-on-ink`, which are not tokens:
33
- // `--color-ink` is a TEXT colour and the other two do not exist, so Tailwind
34
- // emitted nothing and the selected tab rendered identically to the rest.
35
- "data-active:bg-code data-active:text-on-code");
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-body-sm text-faint", children: step.body }) : null, step.prompt ? _jsx(CodeBlock, { code: step.prompt }) : null, step.code ? _jsx(CodeBlock, { code: step.code }) : null, step.link ? (_jsxs(Button, { render: _jsx("a", { href: step.link.href, target: "_blank", rel: "noopener noreferrer" }),
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 ? "md:grid-cols-3" : steps.length === 2 ? "md:grid-cols-2" : "";
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-3", children: [_jsx("span", { className: "text-caption font-medium text-faint", children: step.label }), _jsx("span", { className: "text-heading-sm font-medium", children: step.title }), _jsx(StepBody, { step: step })] }, i))) }));
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 (_jsx(StepList, { className: cn("grid grid-cols-1 gap-6", cols), children: steps.map((step, i) => (_jsx(StepItem, { index: i + 1, title: step.title, className: "flex-col md:flex-row", children: _jsx(StepBody, { step: step }) }, i))) }));
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-8", className), ...props, children: [title ? (_jsx(PageHeading, { id: headingId, eyebrow: eyebrow, title: title, sub: sub, size: headingSize, level: level })) : null, hasMethods ? (_jsx(Tabs, { value: activeMethod, onValueChange: (next) => changeMethod(String(next)), "data-slot": "tool-setup-methods", children: _jsx(TabsList
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
- className: "h-auto! w-fit flex-wrap gap-2", children: methods.map((m) => (_jsx(TabsTrigger, { value: m.value, disabled: m.disabled, 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 })) : (_jsxs(Tabs
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-4", children: [_jsx(TabsList
263
- // Labelled by the lockup when there is one, so the strip is announced
264
- // as the setup's tool list rather than an unnamed set of tabs.
265
- , { ...(title ? { "aria-labelledby": headingId } : {}), "data-slot": "tool-setup-tabs",
266
- // `h-auto!` — important, and that is load-bearing.
267
- //
268
- // `tabsListVariants` pins the strip with `group-data-horizontal/tabs:h-8`
269
- // for a compact single row. Eight tools do not fit one row, so the list
270
- // must grow — and a bare `h-auto` does not make it: both utilities
271
- // survive `cn()` because they carry different variant prefixes, and the
272
- // prefixed rule wins the cascade. Measured, not assumed:
273
- // `getComputedStyle` reported a 32px list around a 60px tab.
274
- //
275
- // The consequence was invisible. The eighth tool wrapped into height
276
- // that was never reserved and the panel painted straight over it, while
277
- // every other assertion passed — the tab was present, focusable,
278
- // correctly announced and correctly painted. It was simply underneath.
279
- //
280
- // Important settles it without depending on which utility `cn()` keeps
281
- // or what order Tailwind emits them in.
282
- className: "h-auto! w-full flex-wrap justify-start gap-2 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-1 h-8 self-center" })) : null, group ? (_jsx("span", { "aria-hidden": "true", "data-slot": "tool-setup-group", className: "self-center px-1 text-caption text-faint", children: 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) => {
283
- const pane = hasMethods && activeMethod ? tool.steps?.[activeMethod] : undefined;
284
- return (_jsx(TabsContent, { value: tool.value, "data-slot": "tool-setup-panel", className: "rounded-lg border border-hairline bg-card 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",
285
- // `--cg-link` is a token but NOT a generated utility —
286
- // there is no `--color-link`, so `text-link` emits
287
- // nothing and the link paints as body text. The arbitrary
288
- // form is how the library reaches an ungenerated token,
289
- // the same way onboarding-question writes
290
- // `ring-(--cg-border-strong)`.
291
- 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));
292
- })] })), 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] }));
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