@cloudflare/kumo 1.18.0 → 1.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (228) hide show
  1. package/CHANGELOG.md +90 -0
  2. package/ai/component-registry.json +174 -66
  3. package/ai/component-registry.md +836 -503
  4. package/ai/schemas.ts +19 -3
  5. package/dist/.build-complete +1 -1
  6. package/dist/ai/schemas.d.ts +55 -8
  7. package/dist/ai/schemas.d.ts.map +1 -1
  8. package/dist/ai/schemas.js +163 -146
  9. package/dist/ai/schemas.js.map +1 -1
  10. package/dist/chunks/{Legend-o0ntojbaplmszwk0.js → Legend-ks7se6149vsa3tze.js} +127 -118
  11. package/dist/chunks/Legend-ks7se6149vsa3tze.js.map +1 -0
  12. package/dist/chunks/{breadcrumbs-k39s28qx05vbxxth.js → breadcrumbs-ge20hcb3o5spswrk.js} +2 -2
  13. package/dist/chunks/{breadcrumbs-k39s28qx05vbxxth.js.map → breadcrumbs-ge20hcb3o5spswrk.js.map} +1 -1
  14. package/dist/chunks/{button-cdxnqcgzwko8ooha.js → button-oaqi7ykdisyskoos.js} +12 -12
  15. package/dist/chunks/button-oaqi7ykdisyskoos.js.map +1 -0
  16. package/dist/chunks/{checkbox-kt1uojk2f9e0d0h1.js → checkbox-mwgmohffm22ut13s.js} +5 -5
  17. package/dist/chunks/checkbox-mwgmohffm22ut13s.js.map +1 -0
  18. package/dist/chunks/{clipboard-text-vcbvmtne4zjk4b18.js → clipboard-text-dxczqon3d27xp6f0.js} +10 -10
  19. package/dist/chunks/{clipboard-text-vcbvmtne4zjk4b18.js.map → clipboard-text-dxczqon3d27xp6f0.js.map} +1 -1
  20. package/dist/chunks/{cloudflare-logo-bgts2jgsdh7sslw4.js → cloudflare-logo-pbavoe1wu8nr5c4n.js} +9 -9
  21. package/dist/chunks/{cloudflare-logo-bgts2jgsdh7sslw4.js.map → cloudflare-logo-pbavoe1wu8nr5c4n.js.map} +1 -1
  22. package/dist/chunks/{combobox-he2hd9e2ruknq5mp.js → combobox-eaowwt1xr4d23gsn.js} +113 -101
  23. package/dist/chunks/combobox-eaowwt1xr4d23gsn.js.map +1 -0
  24. package/dist/chunks/{command-palette-jc1w07jwakxvj23a.js → command-palette-maqtbmpfev9mysqd.js} +19 -19
  25. package/dist/chunks/command-palette-maqtbmpfev9mysqd.js.map +1 -0
  26. package/dist/chunks/{dialog-oqh8l3l3zutpibxx.js → dialog-e3m5bhs7fds26p9y.js} +25 -25
  27. package/dist/chunks/dialog-e3m5bhs7fds26p9y.js.map +1 -0
  28. package/dist/chunks/{dropdown-ncwhcd912vmone8k.js → dropdown-ewte287db3vyt8t5.js} +94 -92
  29. package/dist/chunks/{dropdown-ncwhcd912vmone8k.js.map → dropdown-ewte287db3vyt8t5.js.map} +1 -1
  30. package/dist/chunks/{empty-cj898km1r8xwuw44.js → empty-dr1eckm2z40euns6.js} +2 -2
  31. package/dist/chunks/{empty-cj898km1r8xwuw44.js.map → empty-dr1eckm2z40euns6.js.map} +1 -1
  32. package/dist/chunks/{field-krp6z6vfbkrvufz2.js → field-bo5gmna16odrrb1q.js} +3 -3
  33. package/dist/chunks/{field-krp6z6vfbkrvufz2.js.map → field-bo5gmna16odrrb1q.js.map} +1 -1
  34. package/dist/chunks/{grid-m9r71jxo2b8q1972.js → grid-hj1ylz16p7g5uelh.js} +2 -2
  35. package/dist/chunks/{grid-m9r71jxo2b8q1972.js.map → grid-hj1ylz16p7g5uelh.js.map} +1 -1
  36. package/dist/chunks/{input-area-no30c09udyjxshu5.js → input-area-jkkkjej6luumrqpa.js} +4 -4
  37. package/dist/chunks/{input-area-no30c09udyjxshu5.js.map → input-area-jkkkjej6luumrqpa.js.map} +1 -1
  38. package/dist/chunks/{input-h48k3uagzrgb98au.js → input-cw05pbqdburghkus.js} +31 -31
  39. package/dist/chunks/input-cw05pbqdburghkus.js.map +1 -0
  40. package/dist/chunks/{input-group-lxdd09p60cf27pe1.js → input-group-lfugneuz71g42n0w.js} +6 -6
  41. package/dist/chunks/input-group-lfugneuz71g42n0w.js.map +1 -0
  42. package/dist/chunks/label-cvyvbqmt4mt757ff.js +68 -0
  43. package/dist/chunks/{label-latndvb1ngem7we8.js.map → label-cvyvbqmt4mt757ff.js.map} +1 -1
  44. package/dist/chunks/layer-card-ljqth3yxgnk04v2o.js +46 -0
  45. package/dist/chunks/layer-card-ljqth3yxgnk04v2o.js.map +1 -0
  46. package/dist/chunks/{link-hn5ejal7nhh0o0b4.js → link-fjnhtxvfe5ieamjf.js} +2 -2
  47. package/dist/chunks/{link-hn5ejal7nhh0o0b4.js.map → link-fjnhtxvfe5ieamjf.js.map} +1 -1
  48. package/dist/chunks/menubar-e5e4zwfagr0wx023.js +96 -0
  49. package/dist/chunks/menubar-e5e4zwfagr0wx023.js.map +1 -0
  50. package/dist/chunks/{meter-gfa1hz9fhjnvx784.js → meter-duj3micor1lqj3y2.js} +2 -2
  51. package/dist/chunks/{meter-gfa1hz9fhjnvx784.js.map → meter-duj3micor1lqj3y2.js.map} +1 -1
  52. package/dist/chunks/pagination-olaypvwr8swsmn8m.js +266 -0
  53. package/dist/chunks/pagination-olaypvwr8swsmn8m.js.map +1 -0
  54. package/dist/chunks/{popover-h300w4vit0s2ayej.js → popover-nv9cmzbo7mf6bky0.js} +70 -74
  55. package/dist/chunks/popover-nv9cmzbo7mf6bky0.js.map +1 -0
  56. package/dist/chunks/{radio-jouttv89lbvhs55r.js → radio-ihxbe37us2jnqtzf.js} +5 -5
  57. package/dist/chunks/radio-ihxbe37us2jnqtzf.js.map +1 -0
  58. package/dist/chunks/select-nx6ded5swra74iar.js +213 -0
  59. package/dist/chunks/select-nx6ded5swra74iar.js.map +1 -0
  60. package/dist/chunks/{sensitive-input-hd4tpqkzifad1yca.js → sensitive-input-00fujb510rrn61v9.js} +4 -4
  61. package/dist/chunks/{sensitive-input-hd4tpqkzifad1yca.js.map → sensitive-input-00fujb510rrn61v9.js.map} +1 -1
  62. package/dist/chunks/{sidebar-hljy3ssm8itc0ucx.js → sidebar-ltbfius1eolkl8tb.js} +22 -26
  63. package/dist/chunks/sidebar-ltbfius1eolkl8tb.js.map +1 -0
  64. package/dist/chunks/surface-dfgurg5eu3et4vw1.js +29 -0
  65. package/dist/chunks/surface-dfgurg5eu3et4vw1.js.map +1 -0
  66. package/dist/chunks/{switch-ihaydbzem62bey4p.js → switch-fbv3iawqo3o3jgap.js} +17 -17
  67. package/dist/chunks/switch-fbv3iawqo3o3jgap.js.map +1 -0
  68. package/dist/chunks/table-of-contents-f813ivi7ta23vqdm.js +88 -0
  69. package/dist/chunks/table-of-contents-f813ivi7ta23vqdm.js.map +1 -0
  70. package/dist/chunks/table-olwwulga2l3hdwlx.js +189 -0
  71. package/dist/chunks/table-olwwulga2l3hdwlx.js.map +1 -0
  72. package/dist/chunks/{tabs-e7eh7l3mpk3xgmwq.js → tabs-lohcglgppp6gj0hp.js} +4 -4
  73. package/dist/chunks/{tabs-e7eh7l3mpk3xgmwq.js.map → tabs-lohcglgppp6gj0hp.js.map} +1 -1
  74. package/dist/chunks/{toast-bpz6iaq54u9jmuu8.js → toast-dg52x89yd231mxhe.js} +4 -4
  75. package/dist/chunks/{toast-bpz6iaq54u9jmuu8.js.map → toast-dg52x89yd231mxhe.js.map} +1 -1
  76. package/dist/chunks/{tooltip-belkznz8t8333h5f.js → tooltip-hikjvdbg3xghnq1x.js} +38 -37
  77. package/dist/chunks/tooltip-hikjvdbg3xghnq1x.js.map +1 -0
  78. package/dist/chunks/{vendor-base-ui-k7bzesq81ie36nya.js → vendor-base-ui-m5pz3e8c4grg5qmj.js} +21 -21
  79. package/dist/chunks/{vendor-base-ui-k7bzesq81ie36nya.js.map → vendor-base-ui-m5pz3e8c4grg5qmj.js.map} +1 -1
  80. package/dist/code.js +1 -1
  81. package/dist/components/breadcrumbs.js +1 -1
  82. package/dist/components/button.js +1 -1
  83. package/dist/components/chart.js +1 -1
  84. package/dist/components/checkbox.js +1 -1
  85. package/dist/components/clipboard-text.js +1 -1
  86. package/dist/components/cloudflare-logo.js +1 -1
  87. package/dist/components/combobox.js +1 -1
  88. package/dist/components/command-palette.js +1 -1
  89. package/dist/components/dialog.js +1 -1
  90. package/dist/components/dropdown.js +1 -1
  91. package/dist/components/empty.js +1 -1
  92. package/dist/components/field.js +1 -1
  93. package/dist/components/flow.js +2 -2
  94. package/dist/components/flow.js.map +1 -1
  95. package/dist/components/grid.js +1 -1
  96. package/dist/components/input.js +3 -3
  97. package/dist/components/label.js +1 -1
  98. package/dist/components/layer-card.js +1 -1
  99. package/dist/components/link.js +1 -1
  100. package/dist/components/menubar.js +1 -1
  101. package/dist/components/meter.js +1 -1
  102. package/dist/components/pagination.js +1 -1
  103. package/dist/components/popover.js +1 -1
  104. package/dist/components/radio.js +1 -1
  105. package/dist/components/select.js +1 -1
  106. package/dist/components/sensitive-input.js +1 -1
  107. package/dist/components/sidebar.js +1 -1
  108. package/dist/components/surface.js +1 -1
  109. package/dist/components/switch.js +1 -1
  110. package/dist/components/table-of-contents.js +8 -0
  111. package/dist/components/table-of-contents.js.map +1 -0
  112. package/dist/components/table.js +1 -1
  113. package/dist/components/tabs.js +1 -1
  114. package/dist/components/toast.js +2 -2
  115. package/dist/components/tooltip.js +1 -1
  116. package/dist/index.js +124 -120
  117. package/dist/index.js.map +1 -1
  118. package/dist/primitives/accordion.js +1 -1
  119. package/dist/primitives/alert-dialog.js +1 -1
  120. package/dist/primitives/autocomplete.js +1 -1
  121. package/dist/primitives/avatar.js +1 -1
  122. package/dist/primitives/button.js +1 -1
  123. package/dist/primitives/checkbox-group.js +1 -1
  124. package/dist/primitives/checkbox.js +1 -1
  125. package/dist/primitives/collapsible.js +1 -1
  126. package/dist/primitives/combobox.js +1 -1
  127. package/dist/primitives/context-menu.js +1 -1
  128. package/dist/primitives/csp-provider.js +1 -1
  129. package/dist/primitives/dialog.js +1 -1
  130. package/dist/primitives/direction-provider.js +1 -1
  131. package/dist/primitives/drawer.js +1 -1
  132. package/dist/primitives/field.js +1 -1
  133. package/dist/primitives/fieldset.js +1 -1
  134. package/dist/primitives/form.js +1 -1
  135. package/dist/primitives/input.js +1 -1
  136. package/dist/primitives/menu.js +1 -1
  137. package/dist/primitives/menubar.js +1 -1
  138. package/dist/primitives/meter.js +1 -1
  139. package/dist/primitives/navigation-menu.js +1 -1
  140. package/dist/primitives/number-field.js +1 -1
  141. package/dist/primitives/popover.js +1 -1
  142. package/dist/primitives/preview-card.js +1 -1
  143. package/dist/primitives/progress.js +1 -1
  144. package/dist/primitives/radio-group.js +1 -1
  145. package/dist/primitives/radio.js +1 -1
  146. package/dist/primitives/scroll-area.js +1 -1
  147. package/dist/primitives/select.js +1 -1
  148. package/dist/primitives/separator.js +1 -1
  149. package/dist/primitives/slider.js +1 -1
  150. package/dist/primitives/switch.js +1 -1
  151. package/dist/primitives/tabs.js +1 -1
  152. package/dist/primitives/toast.js +1 -1
  153. package/dist/primitives/toggle-group.js +1 -1
  154. package/dist/primitives/toggle.js +1 -1
  155. package/dist/primitives/toolbar.js +1 -1
  156. package/dist/primitives/tooltip.js +1 -1
  157. package/dist/primitives.js +1 -1
  158. package/dist/scripts/theme-generator/config.d.ts.map +1 -1
  159. package/dist/scripts/theme-generator/config.js +3 -3
  160. package/dist/scripts/theme-generator/config.js.map +1 -1
  161. package/dist/src/components/button/button.d.ts +1 -1
  162. package/dist/src/components/button/button.d.ts.map +1 -1
  163. package/dist/src/components/chart/EChart.d.ts +18 -2
  164. package/dist/src/components/chart/EChart.d.ts.map +1 -1
  165. package/dist/src/components/chart/TimeseriesChart.d.ts.map +1 -1
  166. package/dist/src/components/chart/index.d.ts +1 -1
  167. package/dist/src/components/chart/index.d.ts.map +1 -1
  168. package/dist/src/components/combobox/combobox.d.ts +16 -2
  169. package/dist/src/components/combobox/combobox.d.ts.map +1 -1
  170. package/dist/src/components/dropdown/dropdown.d.ts.map +1 -1
  171. package/dist/src/components/input/input.d.ts.map +1 -1
  172. package/dist/src/components/label/label.d.ts.map +1 -1
  173. package/dist/src/components/layer-card/layer-card.d.ts +39 -5
  174. package/dist/src/components/layer-card/layer-card.d.ts.map +1 -1
  175. package/dist/src/components/menubar/menubar.d.ts.map +1 -1
  176. package/dist/src/components/pagination/pagination.d.ts +51 -1
  177. package/dist/src/components/pagination/pagination.d.ts.map +1 -1
  178. package/dist/src/components/popover/popover.d.ts +35 -8
  179. package/dist/src/components/popover/popover.d.ts.map +1 -1
  180. package/dist/src/components/radio/radio.d.ts +1 -1
  181. package/dist/src/components/select/select.d.ts +49 -5
  182. package/dist/src/components/select/select.d.ts.map +1 -1
  183. package/dist/src/components/sidebar/sidebar.d.ts +2 -2
  184. package/dist/src/components/sidebar/sidebar.d.ts.map +1 -1
  185. package/dist/src/components/surface/index.d.ts +3 -0
  186. package/dist/src/components/surface/index.d.ts.map +1 -1
  187. package/dist/src/components/surface/surface.d.ts +14 -10
  188. package/dist/src/components/surface/surface.d.ts.map +1 -1
  189. package/dist/src/components/table/table.d.ts.map +1 -1
  190. package/dist/src/components/table-of-contents/index.d.ts +2 -0
  191. package/dist/src/components/table-of-contents/index.d.ts.map +1 -0
  192. package/dist/src/components/table-of-contents/table-of-contents.d.ts +70 -0
  193. package/dist/src/components/table-of-contents/table-of-contents.d.ts.map +1 -0
  194. package/dist/src/components/tooltip/tooltip.d.ts +15 -6
  195. package/dist/src/components/tooltip/tooltip.d.ts.map +1 -1
  196. package/dist/src/index.d.ts +6 -2
  197. package/dist/src/index.d.ts.map +1 -1
  198. package/dist/styles/kumo-binding.css +1 -0
  199. package/dist/styles/kumo-standalone.css +1 -1
  200. package/dist/styles/theme-kumo.css +6 -6
  201. package/package.json +5 -1
  202. package/scripts/theme-generator/config.ts +8 -6
  203. package/dist/chunks/Legend-o0ntojbaplmszwk0.js.map +0 -1
  204. package/dist/chunks/button-cdxnqcgzwko8ooha.js.map +0 -1
  205. package/dist/chunks/checkbox-kt1uojk2f9e0d0h1.js.map +0 -1
  206. package/dist/chunks/combobox-he2hd9e2ruknq5mp.js.map +0 -1
  207. package/dist/chunks/command-palette-jc1w07jwakxvj23a.js.map +0 -1
  208. package/dist/chunks/dialog-oqh8l3l3zutpibxx.js.map +0 -1
  209. package/dist/chunks/input-group-lxdd09p60cf27pe1.js.map +0 -1
  210. package/dist/chunks/input-h48k3uagzrgb98au.js.map +0 -1
  211. package/dist/chunks/label-latndvb1ngem7we8.js +0 -62
  212. package/dist/chunks/layer-card-l5yjvrxry1dhte57.js +0 -44
  213. package/dist/chunks/layer-card-l5yjvrxry1dhte57.js.map +0 -1
  214. package/dist/chunks/menubar-f1pilzooe5mue7c4.js +0 -92
  215. package/dist/chunks/menubar-f1pilzooe5mue7c4.js.map +0 -1
  216. package/dist/chunks/pagination-cu5lm6p5dxuycta4.js +0 -243
  217. package/dist/chunks/pagination-cu5lm6p5dxuycta4.js.map +0 -1
  218. package/dist/chunks/popover-h300w4vit0s2ayej.js.map +0 -1
  219. package/dist/chunks/radio-jouttv89lbvhs55r.js.map +0 -1
  220. package/dist/chunks/select-kva5ru5f673kah1m.js +0 -179
  221. package/dist/chunks/select-kva5ru5f673kah1m.js.map +0 -1
  222. package/dist/chunks/sidebar-hljy3ssm8itc0ucx.js.map +0 -1
  223. package/dist/chunks/surface-cilvbyhmyujz1bee.js +0 -36
  224. package/dist/chunks/surface-cilvbyhmyujz1bee.js.map +0 -1
  225. package/dist/chunks/switch-ihaydbzem62bey4p.js.map +0 -1
  226. package/dist/chunks/table-inweecadl3her7pd.js +0 -183
  227. package/dist/chunks/table-inweecadl3her7pd.js.map +0 -1
  228. package/dist/chunks/tooltip-belkznz8t8333h5f.js.map +0 -1
@@ -372,7 +372,7 @@
372
372
  "secondary": "bg-kumo-base !text-kumo-default ring not-disabled:hover:border-secondary! not-disabled:hover:bg-kumo-tint disabled:bg-kumo-base/50 disabled:!text-kumo-default/70 ring-kumo-hairline data-[state=open]:bg-kumo-base",
373
373
  "ghost": "text-kumo-default hover:bg-kumo-tint shadow-none bg-inherit",
374
374
  "destructive": "bg-kumo-danger !text-white hover:bg-kumo-danger/70",
375
- "secondary-destructive": "bg-kumo-base !text-kumo-danger ring not-disabled:hover:border-secondary! not-disabled:hover:bg-kumo-base disabled:bg-kumo-base/50 disabled:!text-kumo-danger/70 ring-kumo-line data-[state=open]:bg-kumo-base",
375
+ "secondary-destructive": "bg-kumo-base !text-kumo-danger ring not-disabled:hover:border-secondary! not-disabled:hover:bg-kumo-base disabled:bg-kumo-base/50 disabled:!text-kumo-danger/70 ring-kumo-hairline data-[state=open]:bg-kumo-base",
376
376
  "outline": "bg-transparent text-kumo-default ring ring-kumo-hairline"
377
377
  },
378
378
  "stateClasses": {
@@ -475,7 +475,6 @@
475
475
  "bg-kumo-danger",
476
476
  "bg-kumo-tint",
477
477
  "ring-kumo-hairline",
478
- "ring-kumo-line",
479
478
  "text-kumo-danger",
480
479
  "text-kumo-default",
481
480
  "text-kumo-subtle"
@@ -579,7 +578,6 @@
579
578
  "ring-kumo-contrast",
580
579
  "ring-kumo-danger",
581
580
  "ring-kumo-hairline",
582
- "ring-kumo-line",
583
581
  "text-kumo-danger",
584
582
  "text-kumo-default",
585
583
  "text-kumo-inverse",
@@ -742,7 +740,7 @@
742
740
  ],
743
741
  "colors": [
744
742
  "bg-kumo-base",
745
- "border-kumo-line",
743
+ "border-kumo-hairline",
746
744
  "outline-kumo-fill",
747
745
  "text-kumo-default"
748
746
  ],
@@ -1945,11 +1943,11 @@
1945
1943
  "<div className=\"flex items-center gap-4\">\n <DropdownMenu>\n <DropdownMenu.Trigger>\n <button\n type=\"button\"\n className=\"flex items-center gap-2 rounded-lg bg-black px-4 py-3 text-white transition-opacity hover:opacity-80\"\n >\n <CloudflareLogo variant=\"glyph\" color=\"white\" className=\"w-8\" />\n <span className=\"font-medium\">Logo</span>\n </button>\n </DropdownMenu.Trigger>\n <DropdownMenu.Content>\n <DropdownMenu.Item\n icon={CloudIcon}\n onSelect={() =>\n copyToClipboard(\n generateCloudflareLogoSvg({ variant: \"glyph\" }),\n \"glyph\",\n )\n }\n >\n {copied === \"glyph\" ? \"Copied!\" : \"Copy logo as SVG\"}\n </DropdownMenu.Item>\n <DropdownMenu.Item\n icon={CodeIcon}\n onSelect={() =>\n copyToClipboard(\n generateCloudflareLogoSvg({ variant: \"full\" }),\n \"full\",\n )\n }\n >\n {copied === \"full\" ? \"Copied!\" : \"Copy full logo as SVG\"}\n </DropdownMenu.Item>\n <DropdownMenu.Item\n icon={DownloadSimpleIcon}\n onSelect={() =>\n window.open(\n \"https://www.cloudflare.com/press-kit/\",\n \"_blank\",\n \"noopener\",\n )\n }\n >\n Download brand assets\n </DropdownMenu.Item>\n <DropdownMenu.Separator />\n <DropdownMenu.Item\n icon={ArrowSquareOutIcon}\n onSelect={() =>\n window.open(\n \"https://www.cloudflare.com/brand-assets/\",\n \"_blank\",\n \"noopener\",\n )\n }\n >\n Visit brand guidelines\n </DropdownMenu.Item>\n </DropdownMenu.Content>\n </DropdownMenu>\n\n <span className=\"text-sm text-kumo-subtle\">\n Click to open the brand assets menu\n </span>\n </div>",
1946
1944
  "<PoweredByCloudflare />",
1947
1945
  "<div className=\"flex flex-wrap items-center gap-4\">\n <PoweredByCloudflare />\n <PoweredByCloudflare color=\"black\" />\n <div className=\"rounded-lg bg-black p-3\">\n <PoweredByCloudflare color=\"white\" />\n </div>\n </div>",
1948
- "<footer className=\"flex w-full items-center justify-between rounded-lg border border-kumo-line bg-kumo-elevated px-6 py-4\">\n <span className=\"text-sm text-kumo-subtle\">\n &copy; 2026 Your Company. All rights reserved.\n </span>\n <PoweredByCloudflare />\n </footer>"
1946
+ "<footer className=\"flex w-full items-center justify-between rounded-lg border border-kumo-hairline bg-kumo-elevated px-6 py-4\">\n <span className=\"text-sm text-kumo-subtle\">\n &copy; 2026 Your Company. All rights reserved.\n </span>\n <PoweredByCloudflare />\n </footer>"
1949
1947
  ],
1950
1948
  "colors": [
1951
1949
  "bg-kumo-base",
1952
- "ring-kumo-line",
1950
+ "ring-kumo-hairline",
1953
1951
  "text-kumo-default"
1954
1952
  ]
1955
1953
  },
@@ -2187,7 +2185,8 @@
2187
2185
  "bg-kumo-fill-hover",
2188
2186
  "bg-kumo-overlay",
2189
2187
  "bg-kumo-tint",
2190
- "border-kumo-line",
2188
+ "border-kumo-hairline",
2189
+ "ring-kumo-hairline",
2191
2190
  "ring-kumo-line",
2192
2191
  "text-kumo-default",
2193
2192
  "text-kumo-strong",
@@ -2316,17 +2315,17 @@
2316
2315
  }
2317
2316
  },
2318
2317
  "examples": [
2319
- "<div className=\"flex flex-col items-start gap-4\">\n <Button onClick={() => setOpen(true)}>Open Command Palette</Button>\n {selectedItem && (\n <p className=\"text-sm text-kumo-subtle\">\n Last selected:{\" \"}\n <span className=\"text-kumo-default\">{selectedItem}</span>\n </p>\n )}\n\n <CommandPalette.Root\n open={open}\n onOpenChange={setOpen}\n items={filteredGroups}\n value={search}\n onValueChange={setSearch}\n itemToStringValue={(group) => group.label}\n onSelect={(item, { newTab }) => {\n console.log(\"Selected:\", item.title, newTab ? \"(new tab)\" : \"\");\n handleSelect(item);\n }}\n getSelectableItems={getSelectableItems}\n >\n <CommandPalette.Input placeholder=\"Type a command or search...\" />\n <CommandPalette.List>\n <CommandPalette.Results>\n {(group: CommandGroup) => (\n <CommandPalette.Group key={group.id} items={group.items}>\n <CommandPalette.GroupLabel>\n {group.label}\n </CommandPalette.GroupLabel>\n <CommandPalette.Items>\n {(item: CommandItem) => (\n <CommandPalette.Item\n key={item.id}\n value={item}\n onClick={() => handleSelect(item)}\n >\n <span className=\"flex items-center gap-3\">\n {item.icon && (\n <span className=\"text-kumo-subtle\">{item.icon}</span>\n )}\n <span>{item.title}</span>\n </span>\n </CommandPalette.Item>\n )}\n </CommandPalette.Items>\n </CommandPalette.Group>\n )}\n </CommandPalette.Results>\n <CommandPalette.Empty>No commands found</CommandPalette.Empty>\n </CommandPalette.List>\n <CommandPalette.Footer>\n <span className=\"flex items-center gap-2\">\n <kbd className=\"rounded border border-kumo-line bg-kumo-base px-1.5 py-0.5 text-[10px]\">\n ↑↓\n </kbd>\n <span>Navigate</span>\n </span>\n <span className=\"flex items-center gap-2\">\n <kbd className=\"rounded border border-kumo-line bg-kumo-base px-1.5 py-0.5 text-[10px]\">\n ↵\n </kbd>\n <span>Select</span>\n </span>\n </CommandPalette.Footer>\n </CommandPalette.Root>\n </div>",
2318
+ "<div className=\"flex flex-col items-start gap-4\">\n <Button onClick={() => setOpen(true)}>Open Command Palette</Button>\n {selectedItem && (\n <p className=\"text-sm text-kumo-subtle\">\n Last selected:{\" \"}\n <span className=\"text-kumo-default\">{selectedItem}</span>\n </p>\n )}\n\n <CommandPalette.Root\n open={open}\n onOpenChange={setOpen}\n items={filteredGroups}\n value={search}\n onValueChange={setSearch}\n itemToStringValue={(group) => group.label}\n onSelect={(item, { newTab }) => {\n console.log(\"Selected:\", item.title, newTab ? \"(new tab)\" : \"\");\n handleSelect(item);\n }}\n getSelectableItems={getSelectableItems}\n >\n <CommandPalette.Input placeholder=\"Type a command or search...\" />\n <CommandPalette.List>\n <CommandPalette.Results>\n {(group: CommandGroup) => (\n <CommandPalette.Group key={group.id} items={group.items}>\n <CommandPalette.GroupLabel>\n {group.label}\n </CommandPalette.GroupLabel>\n <CommandPalette.Items>\n {(item: CommandItem) => (\n <CommandPalette.Item\n key={item.id}\n value={item}\n onClick={() => handleSelect(item)}\n >\n <span className=\"flex items-center gap-3\">\n {item.icon && (\n <span className=\"text-kumo-subtle\">{item.icon}</span>\n )}\n <span>{item.title}</span>\n </span>\n </CommandPalette.Item>\n )}\n </CommandPalette.Items>\n </CommandPalette.Group>\n )}\n </CommandPalette.Results>\n <CommandPalette.Empty>No commands found</CommandPalette.Empty>\n </CommandPalette.List>\n <CommandPalette.Footer>\n <span className=\"flex items-center gap-2\">\n <kbd className=\"rounded border border-kumo-hairline bg-kumo-base px-1.5 py-0.5 text-[10px]\">\n ↑↓\n </kbd>\n <span>Navigate</span>\n </span>\n <span className=\"flex items-center gap-2\">\n <kbd className=\"rounded border border-kumo-hairline bg-kumo-base px-1.5 py-0.5 text-[10px]\">\n ↵\n </kbd>\n <span>Select</span>\n </span>\n </CommandPalette.Footer>\n </CommandPalette.Root>\n </div>",
2320
2319
  "<div>\n <Button onClick={() => setOpen(true)}>Open Simple Palette</Button>\n\n <CommandPalette.Root\n open={open}\n onOpenChange={setOpen}\n items={simpleItems}\n value={search}\n onValueChange={setSearch}\n itemToStringValue={(item) => item.title}\n onSelect={(item) => {\n console.log(\"Selected:\", item.title);\n setOpen(false);\n }}\n getSelectableItems={(items) => items}\n >\n <CommandPalette.Input placeholder=\"Search actions...\" />\n <CommandPalette.List>\n <CommandPalette.Results>\n {(item: SimpleItem) => (\n <CommandPalette.Item\n key={item.id}\n value={item}\n onClick={() => {\n console.log(\"Clicked:\", item.title);\n setOpen(false);\n }}\n >\n {item.title}\n </CommandPalette.Item>\n )}\n </CommandPalette.Results>\n <CommandPalette.Empty>No actions found</CommandPalette.Empty>\n </CommandPalette.List>\n </CommandPalette.Root>\n </div>",
2321
2320
  "<div>\n <Button onClick={handleOpen}>Open with Loading</Button>\n\n <CommandPalette.Root\n open={open}\n onOpenChange={setOpen}\n items={loading ? [] : filteredGroups}\n value={search}\n onValueChange={setSearch}\n itemToStringValue={(group) => group.label}\n getSelectableItems={getSelectableItems}\n >\n <CommandPalette.Input placeholder=\"Search...\" />\n <CommandPalette.List>\n {loading ? (\n <CommandPalette.Loading />\n ) : (\n <>\n <CommandPalette.Results>\n {(group: CommandGroup) => (\n <CommandPalette.Group key={group.id} items={group.items}>\n <CommandPalette.GroupLabel>\n {group.label}\n </CommandPalette.GroupLabel>\n <CommandPalette.Items>\n {(item: CommandItem) => (\n <CommandPalette.Item\n key={item.id}\n value={item}\n onClick={() => setOpen(false)}\n >\n <span className=\"flex items-center gap-3\">\n {item.icon && (\n <span className=\"text-kumo-subtle\">\n {item.icon}\n </span>\n )}\n <span>{item.title}</span>\n </span>\n </CommandPalette.Item>\n )}\n </CommandPalette.Items>\n </CommandPalette.Group>\n )}\n </CommandPalette.Results>\n <CommandPalette.Empty>No results found</CommandPalette.Empty>\n </>\n )}\n </CommandPalette.List>\n </CommandPalette.Root>\n </div>",
2322
- "<div>\n <Button onClick={() => setOpen(true)}>Open with ResultItem</Button>\n\n <CommandPalette.Root\n open={open}\n onOpenChange={setOpen}\n items={searchResults}\n value={search}\n onValueChange={setSearch}\n itemToStringValue={(item) => item.title}\n getSelectableItems={(items) => items}\n >\n <CommandPalette.Input placeholder=\"Search documentation...\" />\n <CommandPalette.List>\n <CommandPalette.Results>\n {(item: SearchResult) => (\n <CommandPalette.ResultItem\n key={item.id}\n value={item}\n title={item.title}\n breadcrumbs={item.breadcrumbs}\n icon={item.icon}\n onClick={() => {\n console.log(\"Navigate to:\", item.title);\n setOpen(false);\n }}\n />\n )}\n </CommandPalette.Results>\n <CommandPalette.Empty>No pages found</CommandPalette.Empty>\n </CommandPalette.List>\n <CommandPalette.Footer>\n <span className=\"flex items-center gap-2\">\n <kbd className=\"rounded border border-kumo-line bg-kumo-base px-1.5 py-0.5 text-[10px]\">\n ↑↓\n </kbd>\n <span>Navigate</span>\n </span>\n <span className=\"flex items-center gap-2\">\n <kbd className=\"rounded border border-kumo-line bg-kumo-base px-1.5 py-0.5 text-[10px]\">\n ⌘↵\n </kbd>\n <span>Open in new tab</span>\n </span>\n </CommandPalette.Footer>\n </CommandPalette.Root>\n </div>"
2321
+ "<div>\n <Button onClick={() => setOpen(true)}>Open with ResultItem</Button>\n\n <CommandPalette.Root\n open={open}\n onOpenChange={setOpen}\n items={searchResults}\n value={search}\n onValueChange={setSearch}\n itemToStringValue={(item) => item.title}\n getSelectableItems={(items) => items}\n >\n <CommandPalette.Input placeholder=\"Search documentation...\" />\n <CommandPalette.List>\n <CommandPalette.Results>\n {(item: SearchResult) => (\n <CommandPalette.ResultItem\n key={item.id}\n value={item}\n title={item.title}\n breadcrumbs={item.breadcrumbs}\n icon={item.icon}\n onClick={() => {\n console.log(\"Navigate to:\", item.title);\n setOpen(false);\n }}\n />\n )}\n </CommandPalette.Results>\n <CommandPalette.Empty>No pages found</CommandPalette.Empty>\n </CommandPalette.List>\n <CommandPalette.Footer>\n <span className=\"flex items-center gap-2\">\n <kbd className=\"rounded border border-kumo-hairline bg-kumo-base px-1.5 py-0.5 text-[10px]\">\n ↑↓\n </kbd>\n <span>Navigate</span>\n </span>\n <span className=\"flex items-center gap-2\">\n <kbd className=\"rounded border border-kumo-hairline bg-kumo-base px-1.5 py-0.5 text-[10px]\">\n ⌘↵\n </kbd>\n <span>Open in new tab</span>\n </span>\n </CommandPalette.Footer>\n </CommandPalette.Root>\n </div>"
2323
2322
  ],
2324
2323
  "colors": [
2325
2324
  "bg-kumo-base",
2326
2325
  "bg-kumo-elevated",
2327
2326
  "bg-kumo-overlay",
2328
2327
  "bg-kumo-warning",
2329
- "ring-kumo-line",
2328
+ "ring-kumo-hairline",
2330
2329
  "text-kumo-default",
2331
2330
  "text-kumo-strong",
2332
2331
  "text-kumo-subtle"
@@ -2349,13 +2348,13 @@
2349
2348
  }
2350
2349
  },
2351
2350
  "examples": [
2352
- "<div className=\"flex flex-col gap-4\">\n <DatePicker mode=\"single\" selected={date} onChange={d => {\n if (d) {\n setDate(d);\n }\n }} />\n <p className=\"text-sm text-kumo-subtle\">\n Selected: {date ? date.toLocaleDateString() : \"None\"}\n </p>\n </div>",
2351
+ "<div className=\"flex flex-col gap-4\">\n <DatePicker\n mode=\"single\"\n selected={date}\n onChange={(d) => {\n if (d) {\n setDate(d);\n }\n }}\n />\n <p className=\"text-sm text-kumo-subtle\">\n Selected: {date ? date.toLocaleDateString() : \"None\"}\n </p>\n </div>",
2353
2352
  "<div className=\"flex flex-col gap-4\">\n <DatePicker\n mode=\"multiple\"\n selected={dates}\n onChange={setDates}\n max={5}\n />\n <p className=\"text-sm text-kumo-subtle\">\n Selected: {dates?.length ?? 0} date(s)\n </p>\n </div>",
2354
2353
  "<div className=\"flex flex-col gap-4\">\n <DatePicker\n mode=\"range\"\n selected={range}\n onChange={setRange}\n numberOfMonths={2}\n />\n <p className=\"text-sm text-kumo-subtle\">\n Range:{\" \"}\n {range?.from\n ? `${range.from.toLocaleDateString()} - ${range.to?.toLocaleDateString() ?? \"...\"}`\n : \"None\"}\n </p>\n </div>",
2355
2354
  "<div className=\"flex flex-col gap-4\">\n <DatePicker\n mode=\"range\"\n selected={range}\n onChange={setRange}\n min={3}\n max={7}\n footer={\n <span className=\"text-xs text-kumo-subtle\">Select 3-7 nights</span>\n }\n />\n </div>",
2356
- "<Popover>\n <Popover.Trigger asChild>\n <Button variant=\"outline\" icon={CalendarDotsIcon}>\n {date ? date.toLocaleDateString() : \"Pick a date\"}\n </Button>\n </Popover.Trigger>\n <Popover.Content className=\"p-3\">\n <DatePicker mode=\"single\" selected={date} onChange={setDate} />\n </Popover.Content>\n </Popover>",
2357
- "<Popover>\n <Popover.Trigger asChild>\n <Button variant=\"outline\" icon={CalendarDotsIcon}>\n {formatRange()}\n </Button>\n </Popover.Trigger>\n <Popover.Content className=\"p-3\">\n <DatePicker\n mode=\"range\"\n selected={range}\n onChange={setRange}\n numberOfMonths={2}\n />\n </Popover.Content>\n </Popover>",
2358
- "<Popover>\n <Popover.Trigger asChild>\n <Button variant=\"outline\" icon={CalendarDotsIcon}>\n {formatRange()}\n </Button>\n </Popover.Trigger>\n <Popover.Content className=\"p-0\">\n <div className=\"flex\">\n <div className=\"flex flex-col gap-1 border-r border-kumo-line p-2 text-sm\">\n {presets.map((preset) => {\n const isActive = isPresetActive(preset);\n return (\n <button\n key={preset.label}\n type=\"button\"\n onClick={() => handlePresetClick(preset)}\n className={`rounded-md px-3 py-1.5 text-left whitespace-nowrap ${isActive\n ? \"bg-kumo-bg-inverse text-kumo-text-inverse\"\n : \"text-kumo-strong hover:bg-kumo-control\"\n }`}\n >\n {preset.label}\n </button>\n );\n })}\n </div>\n <div className=\"p-3\">\n <DatePicker\n mode=\"range\"\n selected={range}\n onChange={setRange}\n month={month}\n onMonthChange={setMonth}\n numberOfMonths={2}\n />\n </div>\n </div>\n </Popover.Content>\n </Popover>",
2355
+ "<Popover>\n <Popover.Trigger\n render={<Button variant=\"outline\" icon={CalendarDotsIcon} />}\n >\n {date ? date.toLocaleDateString() : \"Pick a date\"}\n </Popover.Trigger>\n <Popover.Content className=\"p-3\">\n <DatePicker mode=\"single\" selected={date} onChange={setDate} />\n </Popover.Content>\n </Popover>",
2356
+ "<Popover>\n <Popover.Trigger\n render={<Button variant=\"outline\" icon={CalendarDotsIcon} />}\n >\n {formatRange()}\n </Popover.Trigger>\n <Popover.Content className=\"p-3\">\n <DatePicker\n mode=\"range\"\n selected={range}\n onChange={setRange}\n numberOfMonths={2}\n />\n </Popover.Content>\n </Popover>",
2357
+ "<Popover>\n <Popover.Trigger\n render={<Button variant=\"outline\" icon={CalendarDotsIcon} />}\n >\n {formatRange()}\n </Popover.Trigger>\n <Popover.Content className=\"p-0\">\n <div className=\"flex\">\n <div className=\"flex flex-col gap-1 border-r border-kumo-hairline p-2 text-sm\">\n {presets.map((preset) => {\n const isActive = isPresetActive(preset);\n return (\n <button\n key={preset.label}\n type=\"button\"\n onClick={() => handlePresetClick(preset)}\n className={`rounded-md px-3 py-1.5 text-left whitespace-nowrap ${\n isActive\n ? \"bg-kumo-bg-inverse text-kumo-text-inverse\"\n : \"text-kumo-strong hover:bg-kumo-control\"\n }`}\n >\n {preset.label}\n </button>\n );\n })}\n </div>\n <div className=\"p-3\">\n <DatePicker\n mode=\"range\"\n selected={range}\n onChange={setRange}\n month={month}\n onMonthChange={setMonth}\n numberOfMonths={2}\n />\n </div>\n </div>\n </Popover.Content>\n </Popover>",
2359
2358
  "<DatePicker\n mode=\"multiple\"\n selected={dates}\n onChange={setDates}\n max={maxDays}\n disabled={unavailableDates}\n fixedWeeks\n footer={\n <p className=\"text-xs text-kumo-subtle pt-2 w-full\">\n {selectedCount}/{maxDays} days selected. Grayed dates are unavailable.\n </p>\n }\n />"
2360
2359
  ],
2361
2360
  "colors": [
@@ -2542,6 +2541,7 @@
2542
2541
  "colors": [
2543
2542
  "bg-kumo-base",
2544
2543
  "bg-kumo-recessed",
2544
+ "ring-kumo-line",
2545
2545
  "text-kumo-default"
2546
2546
  ],
2547
2547
  "subComponents": {
@@ -2672,7 +2672,7 @@
2672
2672
  "colors": [
2673
2673
  "bg-kumo-control",
2674
2674
  "bg-kumo-danger",
2675
- "bg-kumo-line",
2675
+ "bg-kumo-hairline",
2676
2676
  "bg-kumo-overlay",
2677
2677
  "bg-kumo-tint",
2678
2678
  "ring-kumo-line",
@@ -3004,7 +3004,7 @@
3004
3004
  "<Grid variant=\"4up\" gap=\"base\" mobileDivider>\n <GridItem>\n <Surface className=\"rounded-lg p-4\">\n <Text bold>Item 1</Text>\n <div className=\"mt-1\">\n <Text variant=\"secondary\">Has divider on mobile</Text>\n </div>\n </Surface>\n </GridItem>\n <GridItem>\n <Surface className=\"rounded-lg p-4\">\n <Text bold>Item 2</Text>\n <div className=\"mt-1\">\n <Text variant=\"secondary\">Has divider on mobile</Text>\n </div>\n </Surface>\n </GridItem>\n <GridItem>\n <Surface className=\"rounded-lg p-4\">\n <Text bold>Item 3</Text>\n <div className=\"mt-1\">\n <Text variant=\"secondary\">Has divider on mobile</Text>\n </div>\n </Surface>\n </GridItem>\n <GridItem>\n <Surface className=\"rounded-lg p-4\">\n <Text bold>Item 4</Text>\n <div className=\"mt-1\">\n <Text variant=\"secondary\">Has divider on mobile</Text>\n </div>\n </Surface>\n </GridItem>\n </Grid>"
3005
3005
  ],
3006
3006
  "colors": [
3007
- "border-kumo-line"
3007
+ "border-kumo-hairline"
3008
3008
  ]
3009
3009
  },
3010
3010
  "Input": {
@@ -3096,13 +3096,14 @@
3096
3096
  "<div className=\"flex flex-col gap-4\">\n <Input type=\"email\" label=\"Email\" placeholder=\"you@example.com\" />\n <Input type=\"password\" label=\"Password\" placeholder=\"••••••••\" />\n <Input type=\"number\" label=\"Age\" placeholder=\"18\" />\n <Input type=\"tel\" label=\"Phone\" placeholder=\"+1 (555) 000-0000\" />\n </div>",
3097
3097
  "<Input\n label=\"Phone Number\"\n required={false}\n placeholder=\"+1 (555) 000-0000\"\n />",
3098
3098
  "<Input\n label=\"API Key\"\n labelTooltip=\"Find this in your dashboard under Settings > API Keys\"\n placeholder=\"sk_live_...\"\n />",
3099
- "<Input\n label={\n <span>\n Email for <strong>billing</strong>\n </span>\n }\n required\n placeholder=\"billing@company.com\"\n type=\"email\"\n />"
3099
+ "<Input\n label={\n <span>\n Email for <strong>billing</strong>\n </span>\n }\n required\n placeholder=\"billing@company.com\"\n type=\"email\"\n />",
3100
+ "<Input\n label=\"With onChange\"\n placeholder=\"Type something...\"\n description={value ? `Value: ${value}` : \"Uses e.target.value\"}\n value={value}\n onChange={(e) => setValue(e.target.value)}\n />",
3101
+ "<Input\n label=\"With onValueChange\"\n placeholder=\"Type something...\"\n description={value ? `Value: ${value}` : \"Receives the value directly\"}\n value={value}\n onValueChange={(v) => setValue(v)}\n />"
3100
3102
  ],
3101
3103
  "colors": [
3102
3104
  "bg-kumo-control",
3103
3105
  "ring-kumo-danger",
3104
3106
  "ring-kumo-hairline",
3105
- "ring-kumo-line",
3106
3107
  "text-kumo-default",
3107
3108
  "text-kumo-subtle"
3108
3109
  ],
@@ -3215,25 +3216,43 @@
3215
3216
  "importPath": "@cloudflare/kumo",
3216
3217
  "category": "Display",
3217
3218
  "props": {
3219
+ "render": {
3220
+ "type": "ReactNode",
3221
+ "optional": true,
3222
+ "description": "Allows you to replace the component’s HTML element with a different tag, or compose it with another component.\n\nAccepts a `ReactElement` or a function that returns the element to render."
3223
+ },
3218
3224
  "children": {
3219
3225
  "type": "ReactNode",
3220
3226
  "optional": true
3221
3227
  },
3222
3228
  "className": {
3223
3229
  "type": "string",
3224
- "optional": true,
3225
- "description": "Additional CSS classes merged via `cn()`."
3230
+ "optional": true
3231
+ },
3232
+ "id": {
3233
+ "type": "string",
3234
+ "optional": true
3235
+ },
3236
+ "lang": {
3237
+ "type": "string",
3238
+ "optional": true
3239
+ },
3240
+ "title": {
3241
+ "type": "string",
3242
+ "optional": true
3226
3243
  }
3227
3244
  },
3228
3245
  "examples": [
3229
3246
  "<LayerCard>\n <LayerCard.Secondary className=\"flex items-center justify-between\">\n <div>Next Steps</div>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n shape=\"square\"\n aria-label=\"Go to next steps\"\n >\n <ArrowRightIcon size={16} />\n </Button>\n </LayerCard.Secondary>\n\n <LayerCard.Primary>Get started with Kumo</LayerCard.Primary>\n </LayerCard>",
3230
3247
  "<LayerCard className=\"w-[250px]\">\n <LayerCard.Secondary>Getting Started</LayerCard.Secondary>\n <LayerCard.Primary>\n <p className=\"text-sm text-kumo-subtle\">\n Quick start guide for new users\n </p>\n </LayerCard.Primary>\n </LayerCard>",
3248
+ "<LayerCard className=\"w-[250px] p-4\">\n <p className=\"text-sm text-kumo-subtle\">Quick start guide for new users</p>\n </LayerCard>",
3231
3249
  "<div className=\"flex gap-4\">\n <LayerCard className=\"w-[200px]\">\n <LayerCard.Secondary>Components</LayerCard.Secondary>\n <LayerCard.Primary>\n <p className=\"text-sm\">Browse all components</p>\n </LayerCard.Primary>\n </LayerCard>\n <LayerCard className=\"w-[200px]\">\n <LayerCard.Secondary>Examples</LayerCard.Secondary>\n <LayerCard.Primary>\n <p className=\"text-sm\">View code examples</p>\n </LayerCard.Primary>\n </LayerCard>\n </div>"
3232
3250
  ],
3233
3251
  "colors": [
3234
3252
  "bg-kumo-base",
3235
3253
  "bg-kumo-elevated",
3236
3254
  "ring-kumo-fill",
3255
+ "ring-kumo-hairline",
3237
3256
  "ring-kumo-line",
3238
3257
  "text-kumo-strong"
3239
3258
  ],
@@ -3461,9 +3480,10 @@
3461
3480
  ],
3462
3481
  "colors": [
3463
3482
  "bg-kumo-base",
3483
+ "bg-kumo-elevated",
3464
3484
  "bg-kumo-recessed",
3465
- "border-kumo-fill",
3466
- "border-kumo-recessed"
3485
+ "border-kumo-recessed",
3486
+ "ring-kumo-line"
3467
3487
  ],
3468
3488
  "styling": {
3469
3489
  "container": {
@@ -3570,6 +3590,11 @@
3570
3590
  "optional": true,
3571
3591
  "description": "Additional CSS classes for the container"
3572
3592
  },
3593
+ "labels": {
3594
+ "type": "PaginationLabels",
3595
+ "optional": true,
3596
+ "description": "Labels for internationalization of aria-labels. All labels have English defaults.\n\nFor visible text like \"Showing X of Y\", use render props on sub-components:\n- `Pagination.Info` children for the info text\n- `Pagination.PageSize` label prop for the \"Per page:\" text"
3597
+ },
3573
3598
  "children": {
3574
3599
  "type": "ReactNode",
3575
3600
  "optional": true,
@@ -3604,11 +3629,12 @@
3604
3629
  "<Pagination\n page={page}\n setPage={setPage}\n perPage={perPage}\n totalCount={200}\n >\n <Pagination.Info />\n <Pagination.Separator />\n <Pagination.PageSize\n value={perPage}\n onChange={(size) => {\n setPerPage(size);\n setPage(1);\n }}\n options={[10, 20, 50]}\n />\n <Pagination.Controls />\n </Pagination>",
3605
3630
  "<Pagination page={page} setPage={setPage} perPage={25} totalCount={100}>\n <Pagination.Info>\n {({ page, totalCount }) =>\n `Page ${page} of ${Math.ceil((totalCount ?? 1) / 25)}`\n }\n </Pagination.Info>\n <Pagination.Controls />\n </Pagination>",
3606
3631
  "<Pagination\n page={page}\n setPage={setPage}\n perPage={perPage}\n totalCount={500}\n >\n <Pagination.Info />\n <Pagination.Separator />\n <Pagination.PageSize\n value={perPage}\n onChange={(size) => {\n setPerPage(size);\n setPage(1);\n }}\n />\n <Pagination.Controls pageSelector=\"dropdown\" />\n </Pagination>",
3607
- "<Pagination\n page={page}\n setPage={setPage}\n perPage={perPage}\n totalCount={500}\n >\n <Pagination.Info />\n <div className=\"flex items-center gap-2\">\n <Pagination.Controls />\n <Pagination.Separator />\n <Pagination.PageSize\n value={perPage}\n onChange={(size) => {\n setPerPage(size);\n setPage(1);\n }}\n />\n </div>\n </Pagination>"
3632
+ "<Pagination\n page={page}\n setPage={setPage}\n perPage={perPage}\n totalCount={500}\n >\n <Pagination.Info />\n <div className=\"flex items-center gap-2\">\n <Pagination.Controls />\n <Pagination.Separator />\n <Pagination.PageSize\n value={perPage}\n onChange={(size) => {\n setPerPage(size);\n setPage(1);\n }}\n />\n </div>\n </Pagination>",
3633
+ "<Pagination\n page={page}\n setPage={setPage}\n perPage={10}\n totalCount={100}\n labels={{\n firstPage: \"Première page\",\n previousPage: \"Page précédente\",\n nextPage: \"Page suivante\",\n lastPage: \"Dernière page\",\n pageNumber: \"Numéro de page\",\n pageSize: \"Taille de page\",\n }}\n >\n <Pagination.Info>\n {({ pageShowingRange, totalCount }) => (\n <>\n Affichage de{\" \"}\n <span className=\"tabular-nums\">{pageShowingRange}</span> sur{\" \"}\n <span className=\"tabular-nums\">{totalCount}</span>\n </>\n )}\n </Pagination.Info>\n <Pagination.Controls />\n </Pagination>"
3608
3634
  ],
3609
3635
  "colors": [
3610
- "border-kumo-line",
3611
- "ring-kumo-line",
3636
+ "border-kumo-hairline",
3637
+ "ring-kumo-hairline",
3612
3638
  "text-kumo-strong"
3613
3639
  ],
3614
3640
  "subComponents": {
@@ -3650,6 +3676,10 @@
3650
3676
  "type": "number[]",
3651
3677
  "optional": true
3652
3678
  },
3679
+ "page": {
3680
+ "type": "\"",
3681
+ "required": true
3682
+ },
3653
3683
  "label": {
3654
3684
  "type": "ReactNode",
3655
3685
  "optional": true
@@ -3727,12 +3757,13 @@
3727
3757
  }
3728
3758
  },
3729
3759
  "examples": [
3730
- "<Popover>\n <Popover.Trigger asChild>\n <Button shape=\"square\" icon={BellIcon} aria-label=\"Notifications\" />\n </Popover.Trigger>\n <Popover.Content>\n <Popover.Title>Notifications</Popover.Title>\n <Popover.Description>\n You are all caught up. Good job!\n </Popover.Description>\n </Popover.Content>\n </Popover>",
3731
- "<Popover>\n <Popover.Trigger asChild>\n <Button>Open Popover</Button>\n </Popover.Trigger>\n <Popover.Content>\n <Popover.Title>Popover Title</Popover.Title>\n <Popover.Description>\n This is a basic popover with a title and description.\n </Popover.Description>\n </Popover.Content>\n </Popover>",
3732
- "<Popover>\n <Popover.Trigger asChild>\n <Button>Open Settings</Button>\n </Popover.Trigger>\n <Popover.Content>\n <Popover.Title>Settings</Popover.Title>\n <Popover.Description>\n Configure your preferences below.\n </Popover.Description>\n <div className=\"mt-3\">\n <Popover.Close asChild>\n <Button variant=\"secondary\" size=\"sm\">\n Close\n </Button>\n </Popover.Close>\n </div>\n </Popover.Content>\n </Popover>",
3733
- "<div className=\"flex flex-wrap gap-4\">\n <Popover>\n <Popover.Trigger asChild>\n <Button variant=\"secondary\">Bottom</Button>\n </Popover.Trigger>\n <Popover.Content side=\"bottom\">\n <Popover.Title>Bottom</Popover.Title>\n <Popover.Description>\n Popover on bottom (default).\n </Popover.Description>\n </Popover.Content>\n </Popover>\n\n <Popover>\n <Popover.Trigger asChild>\n <Button variant=\"secondary\">Top</Button>\n </Popover.Trigger>\n <Popover.Content side=\"top\">\n <Popover.Title>Top</Popover.Title>\n <Popover.Description>Popover on top.</Popover.Description>\n </Popover.Content>\n </Popover>\n\n <Popover>\n <Popover.Trigger asChild>\n <Button variant=\"secondary\">Left</Button>\n </Popover.Trigger>\n <Popover.Content side=\"left\">\n <Popover.Title>Left</Popover.Title>\n <Popover.Description>Popover on left.</Popover.Description>\n </Popover.Content>\n </Popover>\n\n <Popover>\n <Popover.Trigger asChild>\n <Button variant=\"secondary\">Right</Button>\n </Popover.Trigger>\n <Popover.Content side=\"right\">\n <Popover.Title>Right</Popover.Title>\n <Popover.Description>Popover on right.</Popover.Description>\n </Popover.Content>\n </Popover>\n </div>",
3734
- "<Popover>\n <Popover.Trigger asChild>\n <Button>User Profile</Button>\n </Popover.Trigger>\n <Popover.Content className=\"w-64\">\n <div className=\"flex items-center gap-3\">\n <div className=\"size-10 rounded-full bg-kumo-recessed\" />\n <div>\n <Popover.Title>Jane Doe</Popover.Title>\n <p className=\"text-sm text-kumo-subtle\">jane@example.com</p>\n </div>\n </div>\n <div className=\"mt-3 flex gap-2 border-t border-kumo-line pt-3\">\n <Button variant=\"secondary\" size=\"sm\" className=\"flex-1\">\n Profile\n </Button>\n <Popover.Close asChild>\n <Button variant=\"ghost\" size=\"sm\" className=\"flex-1\">\n Sign Out\n </Button>\n </Popover.Close>\n </div>\n </Popover.Content>\n </Popover>",
3735
- "<Popover>\n <Popover.Trigger openOnHover delay={200} asChild>\n <Button variant=\"secondary\">Hover Me</Button>\n </Popover.Trigger>\n <Popover.Content>\n <Popover.Title>Hover Triggered</Popover.Title>\n <Popover.Description>\n This popover opens on hover with a 200ms delay. It can still contain\n interactive content like buttons and links.\n </Popover.Description>\n <div className=\"mt-3\">\n <Popover.Close asChild>\n <Button variant=\"secondary\" size=\"sm\">\n Got it\n </Button>\n </Popover.Close>\n </div>\n </Popover.Content>\n </Popover>"
3760
+ "<Popover>\n <Popover.Trigger\n render={\n <Button shape=\"square\" icon={BellIcon} aria-label=\"Notifications\" />\n }\n />\n <Popover.Content>\n <Popover.Title>Notifications</Popover.Title>\n <Popover.Description>\n You are all caught up. Good job!\n </Popover.Description>\n </Popover.Content>\n </Popover>",
3761
+ "<Popover>\n <Popover.Trigger render={<Button />}>Open Popover</Popover.Trigger>\n <Popover.Content>\n <Popover.Title>Popover Title</Popover.Title>\n <Popover.Description>\n This is a basic popover with a title and description.\n </Popover.Description>\n </Popover.Content>\n </Popover>",
3762
+ "<Popover>\n <Popover.Trigger render={<Button />}>Open Settings</Popover.Trigger>\n <Popover.Content>\n <Popover.Title>Settings</Popover.Title>\n <Popover.Description>\n Configure your preferences below.\n </Popover.Description>\n <div className=\"mt-3\">\n <Popover.Close render={<Button variant=\"secondary\" size=\"sm\" />}>\n Close\n </Popover.Close>\n </div>\n </Popover.Content>\n </Popover>",
3763
+ "<div className=\"flex flex-wrap gap-4\">\n <Popover>\n <Popover.Trigger render={<Button variant=\"secondary\" />}>\n Bottom\n </Popover.Trigger>\n <Popover.Content side=\"bottom\">\n <Popover.Title>Bottom</Popover.Title>\n <Popover.Description>\n Popover on bottom (default).\n </Popover.Description>\n </Popover.Content>\n </Popover>\n\n <Popover>\n <Popover.Trigger render={<Button variant=\"secondary\" />}>\n Top\n </Popover.Trigger>\n <Popover.Content side=\"top\">\n <Popover.Title>Top</Popover.Title>\n <Popover.Description>Popover on top.</Popover.Description>\n </Popover.Content>\n </Popover>\n\n <Popover>\n <Popover.Trigger render={<Button variant=\"secondary\" />}>\n Left\n </Popover.Trigger>\n <Popover.Content side=\"left\">\n <Popover.Title>Left</Popover.Title>\n <Popover.Description>Popover on left.</Popover.Description>\n </Popover.Content>\n </Popover>\n\n <Popover>\n <Popover.Trigger render={<Button variant=\"secondary\" />}>\n Right\n </Popover.Trigger>\n <Popover.Content side=\"right\">\n <Popover.Title>Right</Popover.Title>\n <Popover.Description>Popover on right.</Popover.Description>\n </Popover.Content>\n </Popover>\n </div>",
3764
+ "<Popover>\n <Popover.Trigger render={<Button />}>User Profile</Popover.Trigger>\n <Popover.Content className=\"w-64\">\n <div className=\"flex items-center gap-3\">\n <div className=\"size-10 rounded-full bg-kumo-recessed\" />\n <div>\n <Popover.Title>Jane Doe</Popover.Title>\n <p className=\"text-sm text-kumo-subtle\">jane@example.com</p>\n </div>\n </div>\n <div className=\"mt-3 flex gap-2 border-t border-kumo-hairline pt-3\">\n <Button variant=\"secondary\" size=\"sm\" className=\"flex-1\">\n Profile\n </Button>\n <Popover.Close\n render={<Button variant=\"ghost\" size=\"sm\" className=\"flex-1\" />}\n >\n Sign Out\n </Popover.Close>\n </div>\n </Popover.Content>\n </Popover>",
3765
+ "<Popover>\n <Popover.Trigger\n openOnHover\n delay={200}\n render={<Button variant=\"secondary\" />}\n >\n Hover Me\n </Popover.Trigger>\n <Popover.Content>\n <Popover.Title>Hover Triggered</Popover.Title>\n <Popover.Description>\n This popover opens on hover with a 200ms delay. It can still contain\n interactive content like buttons and links.\n </Popover.Description>\n <div className=\"mt-3\">\n <Popover.Close render={<Button variant=\"secondary\" size=\"sm\" />}>\n Got it\n </Popover.Close>\n </div>\n </Popover.Content>\n </Popover>",
3766
+ "<div className=\"w-full\">\n <div className=\"overflow-hidden rounded-lg border border-kumo-hairline\">\n <table className=\"w-full text-sm\">\n <thead className=\"bg-kumo-elevated\">\n <tr>\n <th className=\"px-4 py-2 text-left font-medium\">Name</th>\n <th className=\"px-4 py-2 text-left font-medium\">Status</th>\n <th className=\"w-12 px-4 py-2\"></th>\n </tr>\n </thead>\n <tbody className=\"divide-y divide-kumo-hairline\">\n {rows.map((row) => (\n <tr\n key={row.id}\n ref={(el) => {\n if (el) rowRefs.current.set(row.id, el);\n }}\n className={\n selectedRow === row.id ? \"bg-kumo-recessed\" : \"bg-kumo-base\"\n }\n >\n <td className=\"px-4 py-2 font-mono\">{row.name}</td>\n <td className=\"px-4 py-2 text-kumo-subtle\">{row.status}</td>\n <td className=\"px-4 py-2\">\n <Button\n size=\"xs\"\n variant=\"ghost\"\n shape=\"square\"\n icon={DotsThree}\n aria-label={`Actions for ${row.name}`}\n onClick={() => handleEdit(row.id)}\n />\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n <Popover\n open={!!selectedRow}\n onOpenChange={(open) => !open && setSelectedRow(null)}\n >\n <Popover.Content\n side=\"left\"\n anchor={\n anchorRect ? { getBoundingClientRect: () => anchorRect } : undefined\n }\n >\n <Popover.Title>\n Edit {rows.find((r) => r.id === selectedRow)?.name}\n </Popover.Title>\n <Popover.Description>\n The popover anchors to the selected row, not the icon button.\n </Popover.Description>\n <div className=\"mt-3\">\n <Popover.Close render={<Button size=\"sm\" variant=\"secondary\" />}>\n Close\n </Popover.Close>\n </div>\n </Popover.Content>\n </Popover>\n </div>"
3736
3767
  ],
3737
3768
  "colors": [
3738
3769
  "bg-kumo-base",
@@ -3879,7 +3910,6 @@
3879
3910
  "border-kumo-interact",
3880
3911
  "ring-kumo-danger",
3881
3912
  "ring-kumo-hairline",
3882
- "ring-kumo-line",
3883
3913
  "text-kumo-danger",
3884
3914
  "text-kumo-default",
3885
3915
  "text-kumo-subtle"
@@ -3962,6 +3992,18 @@
3962
3992
  "optional": true,
3963
3993
  "description": "Additional CSS classes merged via `cn()`."
3964
3994
  },
3995
+ "size": {
3996
+ "type": "enum",
3997
+ "optional": true,
3998
+ "description": "Size of the select trigger. Matches Input component sizes.",
3999
+ "values": [
4000
+ "xs",
4001
+ "sm",
4002
+ "base",
4003
+ "lg"
4004
+ ],
4005
+ "default": "base"
4006
+ },
3965
4007
  "label": {
3966
4008
  "type": "ReactNode",
3967
4009
  "optional": true,
@@ -4027,6 +4069,7 @@
4027
4069
  },
4028
4070
  "examples": [
4029
4071
  "<Select\n label=\"Favorite Fruit\"\n className=\"w-[200px]\"\n value={value}\n onValueChange={(v) => setValue(v ?? \"apple\")}\n items={{ apple: \"Apple\", banana: \"Banana\", cherry: \"Cherry\" }}\n />",
4072
+ "<div className=\"grid gap-4\">\n <div className=\"flex items-center gap-3\">\n <span className=\"w-10 text-sm text-kumo-subtle\">xs</span>\n <Select\n aria-label=\"Select size xs\"\n size=\"xs\"\n className=\"w-[200px]\"\n placeholder=\"Choose...\"\n items={{ a: \"Option A\", b: \"Option B\" }}\n />\n </div>\n <div className=\"flex items-center gap-3\">\n <span className=\"w-10 text-sm text-kumo-subtle\">sm</span>\n <Select\n aria-label=\"Select size sm\"\n size=\"sm\"\n className=\"w-[200px]\"\n placeholder=\"Choose...\"\n items={{ a: \"Option A\", b: \"Option B\" }}\n />\n </div>\n <div className=\"flex items-center gap-3\">\n <span className=\"w-10 text-sm text-kumo-subtle\">base</span>\n <Select\n aria-label=\"Select size base\"\n size=\"base\"\n className=\"w-[200px]\"\n placeholder=\"Choose...\"\n items={{ a: \"Option A\", b: \"Option B\" }}\n />\n </div>\n <div className=\"flex items-center gap-3\">\n <span className=\"w-10 text-sm text-kumo-subtle\">lg</span>\n <Select\n aria-label=\"Select size lg\"\n size=\"lg\"\n className=\"w-[200px]\"\n placeholder=\"Choose...\"\n items={{ a: \"Option A\", b: \"Option B\" }}\n />\n </div>\n </div>",
4030
4073
  "<Select\n aria-label=\"Select a fruit\"\n className=\"w-[200px]\"\n value={value}\n onValueChange={(v) => setValue(v ?? \"apple\")}\n items={{ apple: \"Apple\", banana: \"Banana\", cherry: \"Cherry\" }}\n />",
4031
4074
  "<Select\n label=\"Issue Type\"\n description=\"Choose the category that best describes your issue\"\n error={!value ? \"Please select an issue type\" : undefined}\n className=\"w-[280px]\"\n value={value}\n onValueChange={(v) => setValue(v as string | null)}\n items={{\n bug: \"Bug\",\n documentation: \"Documentation\",\n feature: \"Feature\",\n }}\n />",
4032
4075
  "<Select\n label=\"Category\"\n placeholder=\"Choose a category...\"\n className=\"w-[200px]\"\n value={value}\n onValueChange={(v) => setValue(v as string | null)}\n items={{\n bug: \"Bug\",\n documentation: \"Documentation\",\n feature: \"Feature\",\n }}\n />",
@@ -4037,20 +4080,22 @@
4037
4080
  "<Select\n label=\"Visible Columns\"\n className=\"w-[250px]\"\n multiple\n renderValue={(value) => {\n if (value.length > 3) {\n return (\n <span className=\"line-clamp-1\">\n {value.slice(0, 2).join(\", \") + ` and ${value.length - 2} more`}\n </span>\n );\n }\n return <span>{value.join(\", \")}</span>;\n }}\n value={value}\n onValueChange={(v) => setValue(v as string[])}\n >\n <Select.Option value=\"Name\">Name</Select.Option>\n <Select.Option value=\"Location\">Location</Select.Option>\n <Select.Option value=\"Size\">Size</Select.Option>\n <Select.Option value=\"Read\">Read</Select.Option>\n <Select.Option value=\"Write\">Write</Select.Option>\n <Select.Option value=\"CreatedAt\">Created At</Select.Option>\n </Select>",
4038
4081
  "<Select\n label=\"Compliance Frameworks\"\n className=\"w-[280px]\"\n multiple\n value={value}\n onValueChange={(v) => setValue(v as string[])}\n >\n <Select.Option value=\"European Union Privacy Regulation\">\n European Union Privacy Regulation\n </Select.Option>\n <Select.Option value=\"California Consumer Protection Act\">\n California Consumer Protection Act\n </Select.Option>\n <Select.Option value=\"Health Insurance Portability Act\">\n Health Insurance Portability Act\n </Select.Option>\n <Select.Option value=\"Payment Card Industry Standard\">\n Payment Card Industry Standard\n </Select.Option>\n </Select>",
4039
4082
  "<Select\n label=\"Issue Types\"\n className=\"w-[220px]\"\n multiple\n renderValue={(selected) => (\n <span className=\"flex items-center gap-2\">\n <span>Issue Types</span>\n {selected.length > 0 && (\n <Badge variant=\"neutral\">{selected.length}</Badge>\n )}\n </span>\n )}\n value={value}\n onValueChange={(v) => setValue(v as string[])}\n >\n {allOptions.map((option) => (\n <Select.Option key={option.value} value={option.value}>\n {option.label}\n </Select.Option>\n ))}\n </Select>",
4040
- "<Select\n label=\"Author\"\n description=\"Select the primary author for this document\"\n className=\"w-[200px]\"\n onValueChange={(v) => setValue(v as (typeof authors)[0] | null)}\n value={value}\n isItemEqualToValue={(item, value) => item?.id === value?.id}\n renderValue={(author) => {\n return author?.name ?? \"Select an author\";\n }}\n >\n {authors.map((author) => (\n <Select.Option key={author.id} value={author}>\n <div className=\"flex w-[300px] items-center justify-between gap-2\">\n <Text>{author.name}</Text>\n <Text variant=\"secondary\">{author.title}</Text>\n </div>\n </Select.Option>\n ))}\n </Select>",
4041
- "<Select\n label=\"Deployment Region\"\n placeholder=\"Choose a region...\"\n className=\"w-[250px]\"\n value={value}\n onValueChange={(v) => setValue(v as string | null)}\n >\n <Select.Option value=\"us-east\">US East</Select.Option>\n <Select.Option value=\"us-west\">US West</Select.Option>\n <Select.Option value=\"eu-west\" disabled>\n EU West\n </Select.Option>\n <Select.Option value=\"ap-south\" disabled>\n AP South\n </Select.Option>\n </Select>",
4083
+ "<Select\n label=\"Author\"\n description=\"Select the primary author for this document\"\n placeholder=\"Select an author\"\n className=\"w-[200px]\"\n onValueChange={(v) => setValue(v as (typeof authors)[0] | null)}\n value={value}\n isItemEqualToValue={(item, value) => item?.id === value?.id}\n renderValue={(author) => author.name}\n >\n {authors.map((author) => (\n <Select.Option key={author.id} value={author}>\n <div className=\"flex w-[300px] items-center justify-between gap-2\">\n <Text>{author.name}</Text>\n <Text variant=\"secondary\">{author.title}</Text>\n </div>\n </Select.Option>\n ))}\n </Select>",
4084
+ "<Select\n label=\"Deployment Region\"\n placeholder=\"Choose a region...\"\n className=\"w-[250px]\"\n value={value}\n onValueChange={(v) => setValue(v as Region | null)}\n isItemEqualToValue={(item, val) => item.value === val.value}\n >\n {regions.map((region) => (\n <Select.Option\n key={region.value}\n value={region}\n disabled={region.disabled}\n >\n {region.label}\n </Select.Option>\n ))}\n </Select>",
4042
4085
  "<Select\n label=\"Plan\"\n className=\"w-[200px]\"\n value={value}\n onValueChange={(v) => setValue(v as string | null)}\n items={{\n free: \"Free\",\n pro: \"Pro\",\n business: { label: \"Business\", disabled: true },\n enterprise: { label: \"Enterprise\", disabled: true },\n }}\n />",
4043
- "<Select\n label=\"Food\"\n placeholder=\"Pick a food...\"\n className=\"w-[220px]\"\n value={value}\n onValueChange={(v) => setValue(v as string | null)}\n >\n <Select.Group>\n <Select.GroupLabel>Fruits</Select.GroupLabel>\n <Select.Option value=\"apple\">Apple</Select.Option>\n <Select.Option value=\"banana\">Banana</Select.Option>\n <Select.Option value=\"cherry\">Cherry</Select.Option>\n </Select.Group>\n <Select.Separator />\n <Select.Group>\n <Select.GroupLabel>Vegetables</Select.GroupLabel>\n <Select.Option value=\"carrot\">Carrot</Select.Option>\n <Select.Option value=\"broccoli\">Broccoli</Select.Option>\n <Select.Option value=\"spinach\">Spinach</Select.Option>\n </Select.Group>\n </Select>",
4044
- "<Select\n label=\"Server Region\"\n placeholder=\"Select a region...\"\n className=\"w-[260px]\"\n value={value}\n onValueChange={(v) => setValue(v as string | null)}\n >\n <Select.Group>\n <Select.GroupLabel>Available</Select.GroupLabel>\n <Select.Option value=\"us-east-1\">US East (N. Virginia)</Select.Option>\n <Select.Option value=\"us-west-2\">US West (Oregon)</Select.Option>\n <Select.Option value=\"eu-west-1\">EU West (Ireland)</Select.Option>\n </Select.Group>\n <Select.Separator />\n <Select.Group>\n <Select.GroupLabel>Unavailable</Select.GroupLabel>\n <Select.Option value=\"ap-south-1\" disabled>\n AP South (Mumbai)\n </Select.Option>\n <Select.Option value=\"sa-east-1\" disabled>\n SA East (São Paulo)\n </Select.Option>\n </Select.Group>\n </Select>",
4045
- "<Select\n label=\"Long List Select\"\n description=\"Tests scrolling behavior with many options\"\n placeholder=\"Choose an option...\"\n className=\"w-[220px]\"\n value={value}\n onValueChange={(v) => setValue(v as string | null)}\n >\n {longListItems.map((item) => (\n <Select.Option key={item.value} value={item.value}>\n {item.label}\n </Select.Option>\n ))}\n </Select>"
4086
+ "<Select\n label=\"Food\"\n placeholder=\"Pick a food...\"\n className=\"w-[220px]\"\n value={value}\n onValueChange={(v) => setValue(v as Food | null)}\n isItemEqualToValue={(item, val) => item.value === val.value}\n >\n <Select.Group>\n <Select.GroupLabel>Fruits</Select.GroupLabel>\n {foods.fruits.map((food) => (\n <Select.Option key={food.value} value={food}>\n {food.label}\n </Select.Option>\n ))}\n </Select.Group>\n <Select.Separator />\n <Select.Group>\n <Select.GroupLabel>Vegetables</Select.GroupLabel>\n {foods.vegetables.map((food) => (\n <Select.Option key={food.value} value={food}>\n {food.label}\n </Select.Option>\n ))}\n </Select.Group>\n </Select>",
4087
+ "<Select\n label=\"Server Region\"\n placeholder=\"Select a region...\"\n className=\"w-[260px]\"\n value={value}\n onValueChange={(v) => setValue(v as ServerRegion | null)}\n isItemEqualToValue={(item, val) => item.value === val.value}\n >\n <Select.Group>\n <Select.GroupLabel>Available</Select.GroupLabel>\n {serverRegions.available.map((region) => (\n <Select.Option key={region.value} value={region}>\n {region.label}\n </Select.Option>\n ))}\n </Select.Group>\n <Select.Separator />\n <Select.Group>\n <Select.GroupLabel>Unavailable</Select.GroupLabel>\n {serverRegions.unavailable.map((region) => (\n <Select.Option key={region.value} value={region} disabled>\n {region.label}\n </Select.Option>\n ))}\n </Select.Group>\n </Select>",
4088
+ "<Select\n label=\"Long List Select\"\n description=\"Tests scrolling behavior with many options\"\n placeholder=\"Choose an option...\"\n className=\"w-[220px]\"\n value={value}\n onValueChange={(v) => setValue(v as LongListItem | null)}\n isItemEqualToValue={(item, val) => item.value === val.value}\n >\n {longListItems.map((item) => (\n <Select.Option key={item.value} value={item}>\n {item.label}\n </Select.Option>\n ))}\n </Select>"
4046
4089
  ],
4047
4090
  "colors": [
4048
4091
  "bg-kumo-base",
4049
- "bg-kumo-line",
4092
+ "bg-kumo-hairline",
4050
4093
  "bg-kumo-tint",
4051
4094
  "ring-kumo-hairline",
4095
+ "ring-kumo-line",
4052
4096
  "text-kumo-danger",
4053
4097
  "text-kumo-default",
4098
+ "text-kumo-placeholder",
4054
4099
  "text-kumo-subtle"
4055
4100
  ],
4056
4101
  "subComponents": {
@@ -4357,13 +4402,12 @@
4357
4402
  "colors": [
4358
4403
  "bg-kumo-base",
4359
4404
  "bg-kumo-brand",
4360
- "bg-kumo-line",
4405
+ "bg-kumo-hairline",
4361
4406
  "bg-kumo-overlay",
4362
4407
  "bg-kumo-recessed",
4363
4408
  "bg-kumo-tint",
4364
- "border-kumo-line",
4409
+ "border-kumo-hairline",
4365
4410
  "ring-kumo-hairline",
4366
- "ring-kumo-line",
4367
4411
  "text-kumo-default",
4368
4412
  "text-kumo-strong",
4369
4413
  "text-kumo-subtle"
@@ -4548,7 +4592,7 @@
4548
4592
  "Surface": {
4549
4593
  "name": "Surface",
4550
4594
  "type": "component",
4551
- "description": "Polymorphic container with consistent background, shadow, and border styling. Use the `render` prop to change the underlying element: ```tsx <Surface render={<section />} className=\"rounded-lg p-4\">Card content</Surface> ```",
4595
+ "description": "Surface component",
4552
4596
  "importPath": "@cloudflare/kumo",
4553
4597
  "category": "Layout",
4554
4598
  "props": {
@@ -4582,15 +4626,8 @@
4582
4626
  "optional": true
4583
4627
  }
4584
4628
  },
4585
- "examples": [
4586
- "<Surface className=\"rounded-lg p-6\">\n <Text size=\"lg\" bold>\n Surface Component\n </Text>\n <div className=\"mt-2\">\n <Text variant=\"secondary\">\n A container with consistent elevation and border styling.\n </Text>\n </div>\n </Surface>",
4587
- "<div className=\"flex flex-col gap-4\">\n <Surface render={<section />} className=\"rounded-lg p-4\">\n <Text bold>As section element</Text>\n </Surface>\n <Surface render={<article />} className=\"rounded-lg p-4\">\n <Text bold>As article element</Text>\n </Surface>\n <Surface render={<aside />} className=\"rounded-lg p-4\">\n <Text bold>As aside element</Text>\n </Surface>\n </div>",
4588
- "<Surface className=\"rounded-lg p-6\">\n <Text bold>Outer Surface</Text>\n <Surface className=\"mt-4 rounded-md bg-kumo-elevated p-4\">\n <Text variant=\"secondary\">Nested Surface</Text>\n </Surface>\n </Surface>"
4589
- ],
4590
- "colors": [
4591
- "bg-kumo-base",
4592
- "ring-kumo-line"
4593
- ]
4629
+ "examples": [],
4630
+ "colors": []
4594
4631
  },
4595
4632
  "Switch": {
4596
4633
  "name": "Switch",
@@ -4717,8 +4754,8 @@
4717
4754
  ],
4718
4755
  "colors": [
4719
4756
  "bg-kumo-base",
4720
- "border-kumo-line",
4721
- "ring-kumo-line",
4757
+ "border-kumo-hairline",
4758
+ "ring-kumo-hairline",
4722
4759
  "text-kumo-danger",
4723
4760
  "text-kumo-default",
4724
4761
  "text-kumo-subtle"
@@ -4827,13 +4864,14 @@
4827
4864
  }
4828
4865
  },
4829
4866
  "examples": [
4830
- "<LayerCard>\n <LayerCard.Primary className=\"p-0\">\n <Table>\n <Table.Header>\n <Table.Row>\n <Table.Head>Subject</Table.Head>\n <Table.Head>From</Table.Head>\n <Table.Head>Date</Table.Head>\n </Table.Row>\n </Table.Header>\n <Table.Body>\n {emailData.slice(0, 3).map((row) => (\n <Table.Row key={row.id}>\n <Table.Cell>{row.subject}</Table.Cell>\n <Table.Cell>{row.from}</Table.Cell>\n <Table.Cell>{row.date}</Table.Cell>\n </Table.Row>\n ))}\n </Table.Body>\n </Table>\n </LayerCard.Primary>\n </LayerCard>",
4831
- "<LayerCard>\n <LayerCard.Primary className=\"p-0\">\n <Table>\n <Table.Header>\n <Table.Row>\n <Table.CheckHead\n checked={selectedIds.size === rows.length}\n indeterminate={\n selectedIds.size > 0 && selectedIds.size < rows.length\n }\n onValueChange={toggleAll}\n aria-label=\"Select all rows\"\n />\n <Table.Head>Subject</Table.Head>\n <Table.Head>From</Table.Head>\n <Table.Head>Date</Table.Head>\n </Table.Row>\n </Table.Header>\n <Table.Body>\n {rows.map((row) => (\n <Table.Row key={row.id}>\n <Table.CheckCell\n checked={selectedIds.has(row.id)}\n onValueChange={() => toggleRow(row.id)}\n aria-label={`Select ${row.subject}`}\n />\n <Table.Cell>{row.subject}</Table.Cell>\n <Table.Cell>{row.from}</Table.Cell>\n <Table.Cell>{row.date}</Table.Cell>\n </Table.Row>\n ))}\n </Table.Body>\n </Table>\n </LayerCard.Primary>\n </LayerCard>",
4832
- "<LayerCard>\n <LayerCard.Primary className=\"p-0\">\n <Table>\n <Table.Header variant=\"compact\">\n <Table.Row>\n <Table.Head>Subject</Table.Head>\n <Table.Head>From</Table.Head>\n <Table.Head>Date</Table.Head>\n </Table.Row>\n </Table.Header>\n <Table.Body>\n {emailData.slice(0, 3).map((row) => (\n <Table.Row key={row.id}>\n <Table.Cell>{row.subject}</Table.Cell>\n <Table.Cell>{row.from}</Table.Cell>\n <Table.Cell>{row.date}</Table.Cell>\n </Table.Row>\n ))}\n </Table.Body>\n </Table>\n </LayerCard.Primary>\n </LayerCard>",
4833
- "<LayerCard>\n <LayerCard.Primary className=\"p-0\">\n <Table>\n <Table.Header>\n <Table.Row>\n <Table.CheckHead\n checked={selectedIds.size === rows.length}\n indeterminate={\n selectedIds.size > 0 && selectedIds.size < rows.length\n }\n onValueChange={toggleAll}\n aria-label=\"Select all rows\"\n />\n <Table.Head>Subject</Table.Head>\n <Table.Head>From</Table.Head>\n <Table.Head>Date</Table.Head>\n </Table.Row>\n </Table.Header>\n <Table.Body>\n {rows.map((row) => (\n <Table.Row\n key={row.id}\n variant={selectedIds.has(row.id) ? \"selected\" : \"default\"}\n >\n <Table.CheckCell\n checked={selectedIds.has(row.id)}\n onValueChange={() => toggleRow(row.id)}\n aria-label={`Select ${row.subject}`}\n />\n <Table.Cell>{row.subject}</Table.Cell>\n <Table.Cell>{row.from}</Table.Cell>\n <Table.Cell>{row.date}</Table.Cell>\n </Table.Row>\n ))}\n </Table.Body>\n </Table>\n </LayerCard.Primary>\n </LayerCard>",
4834
- "<LayerCard>\n <LayerCard.Primary className=\"p-0\">\n <Table layout=\"fixed\">\n <colgroup>\n <col />\n <col className=\"w-[150px]\" />\n <col className=\"w-[150px]\" />\n </colgroup>\n <Table.Header>\n <Table.Row>\n <Table.Head>Subject</Table.Head>\n <Table.Head>From</Table.Head>\n <Table.Head>Date</Table.Head>\n </Table.Row>\n </Table.Header>\n <Table.Body>\n {emailData.map((row) => (\n <Table.Row key={row.id}>\n <Table.Cell>{row.subject}</Table.Cell>\n <Table.Cell>{row.from}</Table.Cell>\n <Table.Cell>{row.date}</Table.Cell>\n </Table.Row>\n ))}\n </Table.Body>\n </Table>\n </LayerCard.Primary>\n </LayerCard>",
4835
- "<LayerCard>\n <LayerCard.Primary className=\"w-full max-w-md overflow-x-auto p-0\">\n <Table>\n <Table.Header>\n <Table.Row>\n <Table.Head>Subject</Table.Head>\n <Table.Head>From</Table.Head>\n <Table.Head>Date</Table.Head>\n <Table.Head>Tags</Table.Head>\n <Table.Head sticky=\"right\">\n <span className=\"sr-only\">Actions</span>\n </Table.Head>\n </Table.Row>\n </Table.Header>\n <Table.Body>\n {emailData.map((row) => (\n <Table.Row key={row.id}>\n <Table.Cell className=\"whitespace-nowrap\">\n {row.subject}\n </Table.Cell>\n <Table.Cell className=\"whitespace-nowrap\">\n {row.from}\n </Table.Cell>\n <Table.Cell className=\"whitespace-nowrap\">\n {row.date}\n </Table.Cell>\n <Table.Cell className=\"whitespace-nowrap\">\n {row.tags ? (\n <div className=\"inline-flex gap-1\">\n {row.tags.map((tag) => (\n <Badge key={tag}>{tag}</Badge>\n ))}\n </div>\n ) : (\n \"—\"\n )}\n </Table.Cell>\n <Table.Cell sticky=\"right\" className=\"text-right\">\n <DropdownMenu>\n <DropdownMenu.Trigger\n render={\n <Button\n variant=\"ghost\"\n size=\"sm\"\n shape=\"square\"\n aria-label=\"More options\"\n >\n <DotsThree weight=\"bold\" size={16} />\n </Button>\n }\n />\n <DropdownMenu.Content>\n <DropdownMenu.Item icon={Eye}>View</DropdownMenu.Item>\n <DropdownMenu.Item icon={PencilSimple}>\n Edit\n </DropdownMenu.Item>\n <DropdownMenu.Separator />\n <DropdownMenu.Item icon={Trash} variant=\"danger\">\n Delete\n </DropdownMenu.Item>\n </DropdownMenu.Content>\n </DropdownMenu>\n </Table.Cell>\n </Table.Row>\n ))}\n </Table.Body>\n </Table>\n </LayerCard.Primary>\n </LayerCard>",
4836
- "<LayerCard>\n <LayerCard.Primary className=\"w-full overflow-x-auto p-0\">\n <Table layout=\"fixed\">\n <colgroup>\n <col />{\" \"}\n {/* Checkbox column - width handled by Table.CheckHead/CheckCell */}\n <col />\n <col style={{ width: \"150px\" }} />\n <col style={{ width: \"120px\" }} />\n <col style={{ width: \"50px\" }} />\n </colgroup>\n <Table.Header>\n <Table.Row>\n <Table.CheckHead\n checked={selectedIds.size === emailData.length}\n indeterminate={\n selectedIds.size > 0 && selectedIds.size < emailData.length\n }\n onValueChange={toggleAll}\n aria-label=\"Select all rows\"\n />\n <Table.Head>Subject</Table.Head>\n <Table.Head>From</Table.Head>\n <Table.Head>Date</Table.Head>\n <Table.Head></Table.Head>\n </Table.Row>\n </Table.Header>\n <Table.Body>\n {emailData.map((row) => (\n <Table.Row\n key={row.id}\n variant={selectedIds.has(row.id) ? \"selected\" : \"default\"}\n >\n <Table.CheckCell\n checked={selectedIds.has(row.id)}\n onValueChange={() => toggleRow(row.id)}\n aria-label={`Select ${row.subject}`}\n />\n <Table.Cell>\n <div className=\"flex items-center gap-2\">\n <EnvelopeSimple size={16} />\n <span className=\"truncate\">{row.subject}</span>\n {row.tags && (\n <div className=\"ml-2 inline-flex gap-1\">\n {row.tags.map((tag) => (\n <Badge key={tag}>{tag}</Badge>\n ))}\n </div>\n )}\n </div>\n </Table.Cell>\n <Table.Cell>\n <span className=\"truncate\">{row.from}</span>\n </Table.Cell>\n <Table.Cell>\n <span className=\"truncate\">{row.date}</span>\n </Table.Cell>\n <Table.Cell className=\"text-right\">\n <DropdownMenu>\n <DropdownMenu.Trigger\n render={\n <Button\n variant=\"ghost\"\n size=\"sm\"\n shape=\"square\"\n aria-label=\"More options\"\n >\n <DotsThree weight=\"bold\" size={16} />\n </Button>\n }\n />\n <DropdownMenu.Content>\n <DropdownMenu.Item icon={Eye}>View</DropdownMenu.Item>\n <DropdownMenu.Item icon={PencilSimple}>\n Edit\n </DropdownMenu.Item>\n <DropdownMenu.Separator />\n <DropdownMenu.Item icon={Trash} variant=\"danger\">\n Delete\n </DropdownMenu.Item>\n </DropdownMenu.Content>\n </DropdownMenu>\n </Table.Cell>\n </Table.Row>\n ))}\n </Table.Body>\n </Table>\n </LayerCard.Primary>\n </LayerCard>"
4867
+ "<LayerCard className=\"p-0\">\n <Table>\n <Table.Header>\n <Table.Row>\n <Table.Head>Subject</Table.Head>\n <Table.Head>From</Table.Head>\n <Table.Head>Date</Table.Head>\n </Table.Row>\n </Table.Header>\n <Table.Body>\n {emailData.slice(0, 3).map((row) => (\n <Table.Row key={row.id}>\n <Table.Cell>{row.subject}</Table.Cell>\n <Table.Cell>{row.from}</Table.Cell>\n <Table.Cell>{row.date}</Table.Cell>\n </Table.Row>\n ))}\n </Table.Body>\n </Table>\n </LayerCard>",
4868
+ "<LayerCard className=\"p-0\">\n <Table>\n <Table.Header>\n <Table.Row>\n <Table.CheckHead\n checked={selectedIds.size === rows.length}\n indeterminate={\n selectedIds.size > 0 && selectedIds.size < rows.length\n }\n onValueChange={toggleAll}\n aria-label=\"Select all rows\"\n />\n <Table.Head>Subject</Table.Head>\n <Table.Head>From</Table.Head>\n <Table.Head>Date</Table.Head>\n </Table.Row>\n </Table.Header>\n <Table.Body>\n {rows.map((row) => (\n <Table.Row key={row.id}>\n <Table.CheckCell\n checked={selectedIds.has(row.id)}\n onValueChange={() => toggleRow(row.id)}\n aria-label={`Select ${row.subject}`}\n />\n <Table.Cell>{row.subject}</Table.Cell>\n <Table.Cell>{row.from}</Table.Cell>\n <Table.Cell>{row.date}</Table.Cell>\n </Table.Row>\n ))}\n </Table.Body>\n </Table>\n </LayerCard>",
4869
+ "<LayerCard className=\"p-0\">\n <Table>\n <Table.Header variant=\"compact\">\n <Table.Row>\n <Table.Head>Subject</Table.Head>\n <Table.Head>From</Table.Head>\n <Table.Head>Date</Table.Head>\n </Table.Row>\n </Table.Header>\n <Table.Body>\n {emailData.slice(0, 3).map((row) => (\n <Table.Row key={row.id}>\n <Table.Cell>{row.subject}</Table.Cell>\n <Table.Cell>{row.from}</Table.Cell>\n <Table.Cell>{row.date}</Table.Cell>\n </Table.Row>\n ))}\n </Table.Body>\n </Table>\n </LayerCard>",
4870
+ "<LayerCard className=\"p-0\">\n <Table>\n <Table.Header>\n <Table.Row>\n <Table.CheckHead\n checked={selectedIds.size === rows.length}\n indeterminate={\n selectedIds.size > 0 && selectedIds.size < rows.length\n }\n onValueChange={toggleAll}\n aria-label=\"Select all rows\"\n />\n <Table.Head>Subject</Table.Head>\n <Table.Head>From</Table.Head>\n <Table.Head>Date</Table.Head>\n </Table.Row>\n </Table.Header>\n <Table.Body>\n {rows.map((row) => (\n <Table.Row\n key={row.id}\n variant={selectedIds.has(row.id) ? \"selected\" : \"default\"}\n >\n <Table.CheckCell\n checked={selectedIds.has(row.id)}\n onValueChange={() => toggleRow(row.id)}\n aria-label={`Select ${row.subject}`}\n />\n <Table.Cell>{row.subject}</Table.Cell>\n <Table.Cell>{row.from}</Table.Cell>\n <Table.Cell>{row.date}</Table.Cell>\n </Table.Row>\n ))}\n </Table.Body>\n </Table>\n </LayerCard>",
4871
+ "<LayerCard className=\"p-0\">\n <Table layout=\"fixed\">\n <colgroup>\n <col />\n <col className=\"w-[150px]\" />\n <col className=\"w-[150px]\" />\n </colgroup>\n <Table.Header>\n <Table.Row>\n <Table.Head>Subject</Table.Head>\n <Table.Head>From</Table.Head>\n <Table.Head>Date</Table.Head>\n </Table.Row>\n </Table.Header>\n <Table.Body>\n {emailData.map((row) => (\n <Table.Row key={row.id}>\n <Table.Cell>{row.subject}</Table.Cell>\n <Table.Cell>{row.from}</Table.Cell>\n <Table.Cell>{row.date}</Table.Cell>\n </Table.Row>\n ))}\n </Table.Body>\n </Table>\n </LayerCard>",
4872
+ "<LayerCard className=\"w-full max-w-md overflow-x-auto p-0\">\n <Table>\n <Table.Header variant=\"compact\">\n <Table.Row>\n <Table.Head>Subject</Table.Head>\n <Table.Head>From</Table.Head>\n <Table.Head>Date</Table.Head>\n <Table.Head>Tags</Table.Head>\n <Table.Head sticky=\"right\">\n <span className=\"sr-only\">Actions</span>\n </Table.Head>\n </Table.Row>\n </Table.Header>\n <Table.Body>\n {emailData.map((row) => (\n <Table.Row key={row.id}>\n <Table.Cell className=\"whitespace-nowrap\">\n {row.subject}\n </Table.Cell>\n <Table.Cell className=\"whitespace-nowrap\">\n {row.from}\n </Table.Cell>\n <Table.Cell className=\"whitespace-nowrap\">\n {row.date}\n </Table.Cell>\n <Table.Cell className=\"whitespace-nowrap\">\n {row.tags ? (\n <div className=\"inline-flex gap-1\">\n {row.tags.map((tag) => (\n <Badge key={tag}>{tag}</Badge>\n ))}\n </div>\n ) : (\n \"—\"\n )}\n </Table.Cell>\n <Table.Cell sticky=\"right\" className=\"text-right\">\n <DropdownMenu>\n <DropdownMenu.Trigger\n render={\n <Button\n variant=\"ghost\"\n size=\"sm\"\n shape=\"square\"\n aria-label=\"More options\"\n >\n <DotsThree weight=\"bold\" size={16} />\n </Button>\n }\n />\n <DropdownMenu.Content>\n <DropdownMenu.Item icon={Eye}>View</DropdownMenu.Item>\n <DropdownMenu.Item icon={PencilSimple}>\n Edit\n </DropdownMenu.Item>\n <DropdownMenu.Separator />\n <DropdownMenu.Item icon={Trash} variant=\"danger\">\n Delete\n </DropdownMenu.Item>\n </DropdownMenu.Content>\n </DropdownMenu>\n </Table.Cell>\n </Table.Row>\n ))}\n </Table.Body>\n </Table>\n </LayerCard>",
4873
+ "<LayerCard className=\"w-full max-w-md overflow-x-auto p-0\">\n <Table>\n <Table.Header>\n <Table.Row>\n <Table.Head>Subject</Table.Head>\n <Table.Head>From</Table.Head>\n <Table.Head>Date</Table.Head>\n <Table.Head>Tags</Table.Head>\n <Table.Head sticky=\"right\">\n <span className=\"sr-only\">Actions</span>\n </Table.Head>\n </Table.Row>\n </Table.Header>\n <Table.Body>\n {emailData.map((row) => (\n <Table.Row key={row.id}>\n <Table.Cell className=\"whitespace-nowrap\">\n {row.subject}\n </Table.Cell>\n <Table.Cell className=\"whitespace-nowrap\">\n {row.from}\n </Table.Cell>\n <Table.Cell className=\"whitespace-nowrap\">\n {row.date}\n </Table.Cell>\n <Table.Cell className=\"whitespace-nowrap\">\n {row.tags ? (\n <div className=\"inline-flex gap-1\">\n {row.tags.map((tag) => (\n <Badge key={tag}>{tag}</Badge>\n ))}\n </div>\n ) : (\n \"—\"\n )}\n </Table.Cell>\n <Table.Cell sticky=\"right\" className=\"text-right\">\n <DropdownMenu>\n <DropdownMenu.Trigger\n render={\n <Button\n variant=\"ghost\"\n size=\"sm\"\n shape=\"square\"\n aria-label=\"More options\"\n >\n <DotsThree weight=\"bold\" size={16} />\n </Button>\n }\n />\n <DropdownMenu.Content>\n <DropdownMenu.Item icon={Eye}>View</DropdownMenu.Item>\n <DropdownMenu.Item icon={PencilSimple}>\n Edit\n </DropdownMenu.Item>\n <DropdownMenu.Separator />\n <DropdownMenu.Item icon={Trash} variant=\"danger\">\n Delete\n </DropdownMenu.Item>\n </DropdownMenu.Content>\n </DropdownMenu>\n </Table.Cell>\n </Table.Row>\n ))}\n </Table.Body>\n </Table>\n </LayerCard>",
4874
+ "<LayerCard className=\"w-full overflow-x-auto p-0\">\n <Table layout=\"fixed\">\n <colgroup>\n <col />{\" \"}\n {/* Checkbox column - width handled by Table.CheckHead/CheckCell */}\n <col />\n <col style={{ width: \"150px\" }} />\n <col style={{ width: \"120px\" }} />\n <col style={{ width: \"50px\" }} />\n </colgroup>\n <Table.Header>\n <Table.Row>\n <Table.CheckHead\n checked={selectedIds.size === emailData.length}\n indeterminate={\n selectedIds.size > 0 && selectedIds.size < emailData.length\n }\n onValueChange={toggleAll}\n aria-label=\"Select all rows\"\n />\n <Table.Head>Subject</Table.Head>\n <Table.Head>From</Table.Head>\n <Table.Head>Date</Table.Head>\n <Table.Head></Table.Head>\n </Table.Row>\n </Table.Header>\n <Table.Body>\n {emailData.map((row) => (\n <Table.Row\n key={row.id}\n variant={selectedIds.has(row.id) ? \"selected\" : \"default\"}\n >\n <Table.CheckCell\n checked={selectedIds.has(row.id)}\n onValueChange={() => toggleRow(row.id)}\n aria-label={`Select ${row.subject}`}\n />\n <Table.Cell>\n <div className=\"flex items-center gap-2\">\n <EnvelopeSimple size={16} />\n <span className=\"truncate\">{row.subject}</span>\n {row.tags && (\n <div className=\"ml-2 inline-flex gap-1\">\n {row.tags.map((tag) => (\n <Badge key={tag}>{tag}</Badge>\n ))}\n </div>\n )}\n </div>\n </Table.Cell>\n <Table.Cell>\n <span className=\"truncate\">{row.from}</span>\n </Table.Cell>\n <Table.Cell>\n <span className=\"truncate\">{row.date}</span>\n </Table.Cell>\n <Table.Cell className=\"text-right\">\n <DropdownMenu>\n <DropdownMenu.Trigger\n render={\n <Button\n variant=\"ghost\"\n size=\"sm\"\n shape=\"square\"\n aria-label=\"More options\"\n >\n <DotsThree weight=\"bold\" size={16} />\n </Button>\n }\n />\n <DropdownMenu.Content>\n <DropdownMenu.Item icon={Eye}>View</DropdownMenu.Item>\n <DropdownMenu.Item icon={PencilSimple}>\n Edit\n </DropdownMenu.Item>\n <DropdownMenu.Separator />\n <DropdownMenu.Item icon={Trash} variant=\"danger\">\n Delete\n </DropdownMenu.Item>\n </DropdownMenu.Content>\n </DropdownMenu>\n </Table.Cell>\n </Table.Row>\n ))}\n </Table.Body>\n </Table>\n </LayerCard>"
4837
4875
  ],
4838
4876
  "colors": [
4839
4877
  "bg-kumo-base",
@@ -4892,6 +4930,72 @@
4892
4930
  }
4893
4931
  }
4894
4932
  },
4933
+ "TableOfContents": {
4934
+ "name": "TableOfContents",
4935
+ "type": "component",
4936
+ "description": "TableOfContents — presentational compound component for section navigation. Purely visual; all interaction logic (scroll tracking, active state management) is left to the consumer.",
4937
+ "importPath": "@cloudflare/kumo",
4938
+ "category": "Other",
4939
+ "props": {
4940
+ "children": {
4941
+ "type": "ReactNode",
4942
+ "optional": true
4943
+ },
4944
+ "className": {
4945
+ "type": "string",
4946
+ "optional": true
4947
+ },
4948
+ "id": {
4949
+ "type": "string",
4950
+ "optional": true
4951
+ },
4952
+ "lang": {
4953
+ "type": "string",
4954
+ "optional": true
4955
+ },
4956
+ "title": {
4957
+ "type": "string",
4958
+ "optional": true
4959
+ }
4960
+ },
4961
+ "examples": [
4962
+ "<DemoWrapper>\n <TableOfContents>\n <TableOfContents.Title>On this page</TableOfContents.Title>\n <TableOfContents.List>\n {headings.map((heading) => (\n <TableOfContents.Item\n key={heading.text}\n active={heading.text === \"Usage\"}\n className=\"cursor-pointer\"\n >\n {heading.text}\n </TableOfContents.Item>\n ))}\n </TableOfContents.List>\n </TableOfContents>\n </DemoWrapper>",
4963
+ "<DemoWrapper>\n <TableOfContents>\n <TableOfContents.Title>On this page</TableOfContents.Title>\n <TableOfContents.List>\n {headings.map((heading) => (\n <TableOfContents.Item\n key={heading.text}\n active={heading.text === active}\n onClick={() => setActive(heading.text)}\n className=\"cursor-pointer\"\n >\n {heading.text}\n </TableOfContents.Item>\n ))}\n </TableOfContents.List>\n </TableOfContents>\n </DemoWrapper>",
4964
+ "<DemoWrapper>\n <TableOfContents>\n <TableOfContents.Title>On this page</TableOfContents.Title>\n <TableOfContents.List>\n {headings.map((heading) => (\n <TableOfContents.Item key={heading.text} className=\"cursor-pointer\">\n {heading.text}\n </TableOfContents.Item>\n ))}\n </TableOfContents.List>\n </TableOfContents>\n </DemoWrapper>",
4965
+ "<DemoWrapper>\n <TableOfContents>\n <TableOfContents.Title>On this page</TableOfContents.Title>\n <TableOfContents.List>\n <TableOfContents.Item active className=\"cursor-pointer\">\n Overview\n </TableOfContents.Item>\n <TableOfContents.Group label=\"Getting Started\">\n <TableOfContents.Item className=\"cursor-pointer\">\n Installation\n </TableOfContents.Item>\n <TableOfContents.Item className=\"cursor-pointer\">\n Configuration\n </TableOfContents.Item>\n </TableOfContents.Group>\n <TableOfContents.Group label=\"API\">\n <TableOfContents.Item className=\"cursor-pointer\">\n Props\n </TableOfContents.Item>\n <TableOfContents.Item className=\"cursor-pointer\">\n Events\n </TableOfContents.Item>\n </TableOfContents.Group>\n </TableOfContents.List>\n </TableOfContents>\n </DemoWrapper>",
4966
+ "<DemoWrapper>\n <TableOfContents>\n <TableOfContents.List>\n {headings.slice(0, 3).map((heading) => (\n <TableOfContents.Item\n key={heading.text}\n active={heading.text === \"Introduction\"}\n className=\"cursor-pointer\"\n >\n {heading.text}\n </TableOfContents.Item>\n ))}\n </TableOfContents.List>\n </TableOfContents>\n </DemoWrapper>",
4967
+ "<DemoWrapper>\n <div className=\"space-y-3\">\n <TableOfContents>\n <TableOfContents.List>\n {[\"Introduction\", \"Installation\", \"Usage\"].map((text) => (\n <TableOfContents.Item\n key={text}\n render={<button type=\"button\" />}\n onClick={() => setClicked(text)}\n active={text === \"Introduction\"}\n >\n {text}\n </TableOfContents.Item>\n ))}\n </TableOfContents.List>\n </TableOfContents>\n {clicked && (\n <p className=\"text-xs text-kumo-subtle\">Clicked: {clicked}</p>\n )}\n </div>\n </DemoWrapper>"
4968
+ ],
4969
+ "colors": [
4970
+ "bg-kumo-brand",
4971
+ "bg-kumo-line",
4972
+ "bg-kumo-tint",
4973
+ "text-kumo-default",
4974
+ "text-kumo-subtle"
4975
+ ],
4976
+ "subComponents": {
4977
+ "Title": {
4978
+ "name": "Title",
4979
+ "description": "Title sub-component",
4980
+ "props": {}
4981
+ },
4982
+ "List": {
4983
+ "name": "List",
4984
+ "description": "List sub-component",
4985
+ "props": {}
4986
+ },
4987
+ "Item": {
4988
+ "name": "Item",
4989
+ "description": "Item sub-component",
4990
+ "props": {}
4991
+ },
4992
+ "Group": {
4993
+ "name": "Group",
4994
+ "description": "Group sub-component",
4995
+ "props": {}
4996
+ }
4997
+ }
4998
+ },
4895
4999
  "Tabs": {
4896
5000
  "name": "Tabs",
4897
5001
  "type": "component",
@@ -5085,8 +5189,8 @@
5085
5189
  }
5086
5190
  },
5087
5191
  "examples": [
5088
- "<div className=\"grid w-full grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3\">\n <div className=\"flex flex-col justify-end gap-1 rounded-lg border border-kumo-line bg-kumo-base p-4\">\n <Text variant=\"heading1\">Heading 1</Text>\n <p className=\"font-mono text-xs text-kumo-subtle\">text-3xl (30px)</p>\n </div>\n <div className=\"flex flex-col justify-end gap-1 rounded-lg border border-kumo-line bg-kumo-base p-4\">\n <Text variant=\"heading2\">Heading 2</Text>\n <p className=\"font-mono text-xs text-kumo-subtle\">text-2xl (24px)</p>\n </div>\n <div className=\"flex flex-col justify-end gap-1 rounded-lg border border-kumo-line bg-kumo-base p-4\">\n <Text variant=\"heading3\">Heading 3</Text>\n <p className=\"font-mono text-xs text-kumo-subtle\">text-lg (16px)</p>\n </div>\n <div className=\"flex flex-col justify-end gap-1 rounded-lg border border-kumo-line bg-kumo-base p-4\">\n <Text>Body</Text>\n <p className=\"font-mono text-xs text-kumo-subtle\">text-base (14px)</p>\n </div>\n <div className=\"flex flex-col justify-end gap-1 rounded-lg border border-kumo-line bg-kumo-base p-4\">\n <Text bold>Body bold</Text>\n <p className=\"font-mono text-xs text-kumo-subtle\">text-base (14px)</p>\n </div>\n <div className=\"flex flex-col justify-end gap-1 rounded-lg border border-kumo-line bg-kumo-base p-4\">\n <Text size=\"lg\">Body lg</Text>\n <p className=\"font-mono text-xs text-kumo-subtle\">text-lg (16px)</p>\n </div>\n <div className=\"flex flex-col justify-end gap-1 rounded-lg border border-kumo-line bg-kumo-base p-4\">\n <Text size=\"sm\">Body sm</Text>\n <p className=\"font-mono text-xs text-kumo-subtle\">text-sm (13px)</p>\n </div>\n <div className=\"flex flex-col justify-end gap-1 rounded-lg border border-kumo-line bg-kumo-base p-4\">\n <Text size=\"xs\">Body xs</Text>\n <p className=\"font-mono text-xs text-kumo-subtle\">text-xs (12px)</p>\n </div>\n <div className=\"flex flex-col justify-end gap-1 rounded-lg border border-kumo-line bg-kumo-base p-4\">\n <Text variant=\"secondary\">Body secondary</Text>\n <p className=\"font-mono text-xs text-kumo-subtle\">text-base (14px)</p>\n </div>\n <div className=\"flex flex-col justify-end gap-1 rounded-lg border border-kumo-line bg-kumo-base p-4\">\n <Text variant=\"mono\">Monospace</Text>\n <p className=\"font-mono text-xs text-kumo-subtle\">text-sm (13px)</p>\n </div>\n <div className=\"flex flex-col justify-end gap-1 rounded-lg border border-kumo-line bg-kumo-base p-4\">\n <Text variant=\"mono\" size=\"lg\">\n Monospace lg\n </Text>\n <p className=\"font-mono text-xs text-kumo-subtle\">text-base (14px)</p>\n </div>\n <div className=\"flex flex-col justify-end gap-1 rounded-lg border border-kumo-line bg-kumo-base p-4\">\n <Text variant=\"mono-secondary\">Monospace secondary</Text>\n <p className=\"font-mono text-xs text-kumo-subtle\">text-sm (13px)</p>\n </div>\n <div className=\"flex flex-col justify-end gap-1 rounded-lg border border-kumo-line bg-kumo-base p-4\">\n <Text variant=\"success\">Success</Text>\n <p className=\"font-mono text-xs text-kumo-subtle\">text-base (14px)</p>\n </div>\n <div className=\"flex flex-col justify-end gap-1 rounded-lg border border-kumo-line bg-kumo-base p-4\">\n <Text variant=\"error\">Error</Text>\n <p className=\"font-mono text-xs text-kumo-subtle\">text-base (14px)</p>\n </div>\n </div>",
5089
- "<div className=\"w-64 rounded-lg border border-kumo-line bg-kumo-base p-4\">\n <Text truncate>\n This is a long piece of text that will be truncated with an ellipsis\n when it overflows its container.\n </Text>\n </div>"
5192
+ "<div className=\"grid w-full grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3\">\n <div className=\"flex flex-col justify-end gap-1 rounded-lg border border-kumo-hairline bg-kumo-base p-4\">\n <Text variant=\"heading1\">Heading 1</Text>\n <Text variant=\"mono-secondary\">text-3xl (30px)</Text>\n </div>\n <div className=\"flex flex-col justify-end gap-1 rounded-lg border border-kumo-hairline bg-kumo-base p-4\">\n <Text variant=\"heading2\">Heading 2</Text>\n <Text variant=\"mono-secondary\">text-2xl (24px)</Text>\n </div>\n <div className=\"flex flex-col justify-end gap-1 rounded-lg border border-kumo-hairline bg-kumo-base p-4\">\n <Text variant=\"heading3\">Heading 3</Text>\n <Text variant=\"mono-secondary\">text-lg (16px)</Text>\n </div>\n <div className=\"flex flex-col justify-end gap-1 rounded-lg border border-kumo-hairline bg-kumo-base p-4\">\n <Text>Body</Text>\n <Text variant=\"mono-secondary\">text-base (14px)</Text>\n </div>\n <div className=\"flex flex-col justify-end gap-1 rounded-lg border border-kumo-hairline bg-kumo-base p-4\">\n <Text bold>Body bold</Text>\n <Text variant=\"mono-secondary\">text-base (14px)</Text>\n </div>\n <div className=\"flex flex-col justify-end gap-1 rounded-lg border border-kumo-hairline bg-kumo-base p-4\">\n <Text size=\"lg\">Body lg</Text>\n <Text variant=\"mono-secondary\">text-lg (16px)</Text>\n </div>\n <div className=\"flex flex-col justify-end gap-1 rounded-lg border border-kumo-hairline bg-kumo-base p-4\">\n <Text size=\"sm\">Body sm</Text>\n <Text variant=\"mono-secondary\">text-sm (13px)</Text>\n </div>\n <div className=\"flex flex-col justify-end gap-1 rounded-lg border border-kumo-hairline bg-kumo-base p-4\">\n <Text size=\"xs\">Body xs</Text>\n <Text variant=\"mono-secondary\">text-xs (12px)</Text>\n </div>\n <div className=\"flex flex-col justify-end gap-1 rounded-lg border border-kumo-hairline bg-kumo-base p-4\">\n <Text variant=\"secondary\">Body secondary</Text>\n <Text variant=\"mono-secondary\">text-base (14px)</Text>\n </div>\n <div className=\"flex flex-col justify-end gap-1 rounded-lg border border-kumo-hairline bg-kumo-base p-4\">\n <Text variant=\"mono\">Monospace</Text>\n <Text variant=\"mono-secondary\">text-sm (13px)</Text>\n </div>\n <div className=\"flex flex-col justify-end gap-1 rounded-lg border border-kumo-hairline bg-kumo-base p-4\">\n <Text variant=\"mono\" size=\"lg\">\n Monospace lg\n </Text>\n <Text variant=\"mono-secondary\">text-base (14px)</Text>\n </div>\n <div className=\"flex flex-col justify-end gap-1 rounded-lg border border-kumo-hairline bg-kumo-base p-4\">\n <Text variant=\"mono-secondary\">Monospace secondary</Text>\n <Text variant=\"mono-secondary\">text-sm (13px)</Text>\n </div>\n <div className=\"flex flex-col justify-end gap-1 rounded-lg border border-kumo-hairline bg-kumo-base p-4\">\n <Text variant=\"success\">Success</Text>\n <Text variant=\"mono-secondary\">text-base (14px)</Text>\n </div>\n <div className=\"flex flex-col justify-end gap-1 rounded-lg border border-kumo-hairline bg-kumo-base p-4\">\n <Text variant=\"error\">Error</Text>\n <Text variant=\"mono-secondary\">text-base (14px)</Text>\n </div>\n </div>",
5193
+ "<div className=\"w-64 rounded-lg border border-kumo-hairline bg-kumo-base p-4\">\n <Text truncate>\n This is a long piece of text that will be truncated with an ellipsis\n when it overflows its container.\n </Text>\n </div>"
5090
5194
  ],
5091
5195
  "colors": [
5092
5196
  "text-kumo-danger",
@@ -5179,6 +5283,7 @@
5179
5283
  "ring-kumo-danger",
5180
5284
  "ring-kumo-hairline",
5181
5285
  "ring-kumo-info",
5286
+ "ring-kumo-line",
5182
5287
  "ring-kumo-success",
5183
5288
  "ring-kumo-warning",
5184
5289
  "text-kumo-danger",
@@ -5258,11 +5363,11 @@
5258
5363
  }
5259
5364
  },
5260
5365
  "examples": [
5261
- "<TooltipProvider>\n <Tooltip content=\"Add new item\" asChild>\n <Button shape=\"square\" icon={PlusIcon} aria-label=\"Add new item\" />\n </Tooltip>\n </TooltipProvider>",
5262
- "<TooltipProvider>\n <Tooltip content=\"Add\" asChild>\n <Button shape=\"square\" icon={PlusIcon} aria-label=\"Add\" />\n </Tooltip>\n </TooltipProvider>",
5263
- "<TooltipProvider>\n <div className=\"flex gap-2\">\n <Tooltip content=\"Add\" asChild>\n <Button shape=\"square\" icon={PlusIcon} aria-label=\"Add\" />\n </Tooltip>\n <Tooltip content=\"Change language\" asChild>\n <Button\n shape=\"square\"\n icon={TranslateIcon}\n aria-label=\"Change language\"\n />\n </Tooltip>\n </div>\n </TooltipProvider>",
5366
+ "<TooltipProvider>\n <Tooltip\n content=\"Add new item\"\n render={\n <Button shape=\"square\" icon={PlusIcon} aria-label=\"Add new item\" />\n }\n />\n </TooltipProvider>",
5367
+ "<TooltipProvider>\n <Tooltip\n content=\"Add\"\n render={<Button shape=\"square\" icon={PlusIcon} aria-label=\"Add\" />}\n />\n </TooltipProvider>",
5368
+ "<TooltipProvider>\n <div className=\"flex gap-2\">\n <Tooltip\n content=\"Add\"\n render={<Button shape=\"square\" icon={PlusIcon} aria-label=\"Add\" />}\n />\n <Tooltip\n content=\"Change language\"\n render={\n <Button\n shape=\"square\"\n icon={TranslateIcon}\n aria-label=\"Change language\"\n />\n }\n />\n </div>\n </TooltipProvider>",
5264
5369
  "<TooltipProvider>\n <Tooltip\n content=\"Click to learn more\"\n className=\"inline-flex items-center gap-1.5 rounded-full bg-kumo-brand px-3 py-1.5 text-sm font-medium text-white shadow-md transition-transform hover:scale-105 active:scale-95\"\n >\n <Info className=\"size-4\" />\n <span>Help</span>\n </Tooltip>\n </TooltipProvider>",
5265
- "<TooltipProvider>\n <div className=\"flex gap-4\">\n <Tooltip content=\"Opens after 1 second\" delay={1000} asChild>\n <Button variant=\"secondary\">1s open delay</Button>\n </Tooltip>\n <Tooltip\n content=\"Stays open 500ms after leaving\"\n closeDelay={500}\n asChild\n >\n <Button variant=\"secondary\">500ms close delay</Button>\n </Tooltip>\n <Tooltip\n content=\"Instant open, stays 1s\"\n delay={0}\n closeDelay={1000}\n asChild\n >\n <Button variant=\"secondary\">Instant + 1s close</Button>\n </Tooltip>\n </div>\n </TooltipProvider>"
5370
+ "<TooltipProvider>\n <div className=\"flex gap-4\">\n <Tooltip\n content=\"Opens after 1 second\"\n delay={1000}\n render={<Button variant=\"secondary\" />}\n >\n 1s open delay\n </Tooltip>\n <Tooltip\n content=\"Stays open 500ms after leaving\"\n closeDelay={500}\n render={<Button variant=\"secondary\" />}\n >\n 500ms close delay\n </Tooltip>\n <Tooltip\n content=\"Instant open, stays 1s\"\n delay={0}\n closeDelay={1000}\n render={<Button variant=\"secondary\" />}\n >\n Instant + 1s close\n </Tooltip>\n </div>\n </TooltipProvider>"
5266
5371
  ],
5267
5372
  "colors": [
5268
5373
  "bg-kumo-base",
@@ -5556,6 +5661,7 @@
5556
5661
  "SensitiveInput",
5557
5662
  "Sidebar",
5558
5663
  "Table",
5664
+ "TableOfContents",
5559
5665
  "DeleteResource"
5560
5666
  ],
5561
5667
  "Navigation": [
@@ -5615,6 +5721,7 @@
5615
5721
  "Surface",
5616
5722
  "Switch",
5617
5723
  "Table",
5724
+ "TableOfContents",
5618
5725
  "Tabs",
5619
5726
  "Text",
5620
5727
  "Toasty",
@@ -5656,6 +5763,7 @@
5656
5763
  "Surface",
5657
5764
  "Switch",
5658
5765
  "Table",
5766
+ "TableOfContents",
5659
5767
  "Tabs",
5660
5768
  "Text",
5661
5769
  "Toasty",