@cloudflare/kumo 1.18.0 → 2.0.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 (330) hide show
  1. package/CHANGELOG.md +329 -0
  2. package/ai/component-registry.json +907 -159
  3. package/ai/component-registry.md +1929 -598
  4. package/ai/schemas.ts +58 -14
  5. package/dist/.build-complete +1 -1
  6. package/dist/ai/schemas.d.ts +206 -27
  7. package/dist/ai/schemas.d.ts.map +1 -1
  8. package/dist/ai/schemas.js +2003 -1948
  9. package/dist/ai/schemas.js.map +1 -1
  10. package/dist/chunks/Legend-ibjxhfm9pn2vrb6f.js +430 -0
  11. package/dist/chunks/Legend-ibjxhfm9pn2vrb6f.js.map +1 -0
  12. package/dist/chunks/autocomplete-cs3fwy6lwzlyirpq.js +174 -0
  13. package/dist/chunks/autocomplete-cs3fwy6lwzlyirpq.js.map +1 -0
  14. package/dist/chunks/{breadcrumbs-k39s28qx05vbxxth.js → breadcrumbs-cxcwf2l1ki3ffg5d.js} +2 -2
  15. package/dist/chunks/{breadcrumbs-k39s28qx05vbxxth.js.map → breadcrumbs-cxcwf2l1ki3ffg5d.js.map} +1 -1
  16. package/dist/chunks/{button-cdxnqcgzwko8ooha.js → button-6by9ntsa3nj553mq.js} +18 -19
  17. package/dist/chunks/button-6by9ntsa3nj553mq.js.map +1 -0
  18. package/dist/chunks/checkbox-eren6w2csum1xghg.js +210 -0
  19. package/dist/chunks/checkbox-eren6w2csum1xghg.js.map +1 -0
  20. package/dist/chunks/{clipboard-text-vcbvmtne4zjk4b18.js → clipboard-text-f9q753udny1uyxr5.js} +47 -43
  21. package/dist/chunks/{clipboard-text-vcbvmtne4zjk4b18.js.map → clipboard-text-f9q753udny1uyxr5.js.map} +1 -1
  22. package/dist/chunks/{cloudflare-logo-bgts2jgsdh7sslw4.js → cloudflare-logo-pbavoe1wu8nr5c4n.js} +9 -9
  23. package/dist/chunks/{cloudflare-logo-bgts2jgsdh7sslw4.js.map → cloudflare-logo-pbavoe1wu8nr5c4n.js.map} +1 -1
  24. package/dist/chunks/collapsible-k8urhi16pg90jvxa.js +71 -0
  25. package/dist/chunks/collapsible-k8urhi16pg90jvxa.js.map +1 -0
  26. package/dist/chunks/{combobox-he2hd9e2ruknq5mp.js → combobox-n9qht9h9ag6kh5sn.js} +142 -118
  27. package/dist/chunks/combobox-n9qht9h9ag6kh5sn.js.map +1 -0
  28. package/dist/chunks/{command-palette-jc1w07jwakxvj23a.js → command-palette-gk9m34ymp2b3hfc5.js} +130 -130
  29. package/dist/chunks/command-palette-gk9m34ymp2b3hfc5.js.map +1 -0
  30. package/dist/chunks/{date-range-picker-j318zxjyqz4o3dak.js → date-range-picker-c9wnx9tbwohai7jy.js} +26 -26
  31. package/dist/chunks/{date-range-picker-j318zxjyqz4o3dak.js.map → date-range-picker-c9wnx9tbwohai7jy.js.map} +1 -1
  32. package/dist/chunks/{dialog-oqh8l3l3zutpibxx.js → dialog-94v7wiz7j3in6528.js} +25 -25
  33. package/dist/chunks/dialog-94v7wiz7j3in6528.js.map +1 -0
  34. package/dist/chunks/dropdown-zbax0zowy6m9zhmt.js +302 -0
  35. package/dist/chunks/dropdown-zbax0zowy6m9zhmt.js.map +1 -0
  36. package/dist/chunks/{empty-cj898km1r8xwuw44.js → empty-kpymw59thjf2ip8g.js} +9 -9
  37. package/dist/chunks/{empty-cj898km1r8xwuw44.js.map → empty-kpymw59thjf2ip8g.js.map} +1 -1
  38. package/dist/chunks/{field-krp6z6vfbkrvufz2.js → field-lnj619xpe8zjd26r.js} +7 -7
  39. package/dist/chunks/{field-krp6z6vfbkrvufz2.js.map → field-lnj619xpe8zjd26r.js.map} +1 -1
  40. package/dist/chunks/{grid-m9r71jxo2b8q1972.js → grid-hj1ylz16p7g5uelh.js} +2 -2
  41. package/dist/chunks/{grid-m9r71jxo2b8q1972.js.map → grid-hj1ylz16p7g5uelh.js.map} +1 -1
  42. package/dist/chunks/{input-area-no30c09udyjxshu5.js → input-area-h8xbqturegdfm1mi.js} +4 -4
  43. package/dist/chunks/{input-area-no30c09udyjxshu5.js.map → input-area-h8xbqturegdfm1mi.js.map} +1 -1
  44. package/dist/chunks/input-group-dh4pg8p20rh4mdi0.js +505 -0
  45. package/dist/chunks/input-group-dh4pg8p20rh4mdi0.js.map +1 -0
  46. package/dist/chunks/{input-h48k3uagzrgb98au.js → input-lpa5fc75tgrraafv.js} +45 -45
  47. package/dist/chunks/input-lpa5fc75tgrraafv.js.map +1 -0
  48. package/dist/chunks/label-be8m7qzlakzig2sl.js +68 -0
  49. package/dist/chunks/{label-latndvb1ngem7we8.js.map → label-be8m7qzlakzig2sl.js.map} +1 -1
  50. package/dist/chunks/layer-card-hvivdirwwnyq88wa.js +46 -0
  51. package/dist/chunks/layer-card-hvivdirwwnyq88wa.js.map +1 -0
  52. package/dist/chunks/{link-hn5ejal7nhh0o0b4.js → link-kt74pxkud4olmcer.js} +4 -4
  53. package/dist/chunks/{link-hn5ejal7nhh0o0b4.js.map → link-kt74pxkud4olmcer.js.map} +1 -1
  54. package/dist/chunks/menubar-hwev159bm4rw9ixk.js +96 -0
  55. package/dist/chunks/menubar-hwev159bm4rw9ixk.js.map +1 -0
  56. package/dist/chunks/{meter-gfa1hz9fhjnvx784.js → meter-bqetlujwg8gm2u7m.js} +2 -2
  57. package/dist/chunks/{meter-gfa1hz9fhjnvx784.js.map → meter-bqetlujwg8gm2u7m.js.map} +1 -1
  58. package/dist/chunks/pagination-ho8zesqfyp6ckmrl.js +266 -0
  59. package/dist/chunks/pagination-ho8zesqfyp6ckmrl.js.map +1 -0
  60. package/dist/chunks/{popover-h300w4vit0s2ayej.js → popover-iayd9ya5yhujz6ve.js} +69 -73
  61. package/dist/chunks/popover-iayd9ya5yhujz6ve.js.map +1 -0
  62. package/dist/chunks/{radio-jouttv89lbvhs55r.js → radio-datzh3pilz8ojak1.js} +87 -75
  63. package/dist/chunks/radio-datzh3pilz8ojak1.js.map +1 -0
  64. package/dist/chunks/select-kpfbib9l8xrrmzpz.js +215 -0
  65. package/dist/chunks/select-kpfbib9l8xrrmzpz.js.map +1 -0
  66. package/dist/chunks/{sensitive-input-hd4tpqkzifad1yca.js → sensitive-input-i1upqytzaw2pus8v.js} +42 -42
  67. package/dist/chunks/sensitive-input-i1upqytzaw2pus8v.js.map +1 -0
  68. package/dist/chunks/{sidebar-hljy3ssm8itc0ucx.js → sidebar-kh37grvfxto14ek6.js} +146 -147
  69. package/dist/chunks/sidebar-kh37grvfxto14ek6.js.map +1 -0
  70. package/dist/chunks/surface-o63tktyrifcjejyb.js +29 -0
  71. package/dist/chunks/surface-o63tktyrifcjejyb.js.map +1 -0
  72. package/dist/chunks/{switch-ihaydbzem62bey4p.js → switch-lclhiplr9zqf73tj.js} +89 -81
  73. package/dist/chunks/switch-lclhiplr9zqf73tj.js.map +1 -0
  74. package/dist/chunks/table-fyy8gl875yyevqs3.js +207 -0
  75. package/dist/chunks/table-fyy8gl875yyevqs3.js.map +1 -0
  76. package/dist/chunks/table-of-contents-fzyv7uhnnyr13dqu.js +102 -0
  77. package/dist/chunks/table-of-contents-fzyv7uhnnyr13dqu.js.map +1 -0
  78. package/dist/chunks/{tabs-e7eh7l3mpk3xgmwq.js → tabs-jywwt8ebjqjkux75.js} +21 -21
  79. package/dist/chunks/{tabs-e7eh7l3mpk3xgmwq.js.map → tabs-jywwt8ebjqjkux75.js.map} +1 -1
  80. package/dist/chunks/{text-nmyi1rkwdj37f30f.js → text-f7t467waymhb30sx.js} +8 -8
  81. package/dist/chunks/text-f7t467waymhb30sx.js.map +1 -0
  82. package/dist/chunks/{toast-bpz6iaq54u9jmuu8.js → toast-h573o0tc7tefivk2.js} +12 -12
  83. package/dist/chunks/{toast-bpz6iaq54u9jmuu8.js.map → toast-h573o0tc7tefivk2.js.map} +1 -1
  84. package/dist/chunks/{tooltip-belkznz8t8333h5f.js → tooltip-odudhkxe282wxinq.js} +38 -37
  85. package/dist/chunks/tooltip-odudhkxe282wxinq.js.map +1 -0
  86. package/dist/chunks/vendor-base-ui-ie71jahf0czyf58j.js +24638 -0
  87. package/dist/chunks/vendor-base-ui-ie71jahf0czyf58j.js.map +1 -0
  88. package/dist/chunks/vendor-floating-ui-dwag5e88viikh2zs.js +1311 -0
  89. package/dist/chunks/vendor-floating-ui-dwag5e88viikh2zs.js.map +1 -0
  90. package/dist/chunks/vendor-utils-ixnhxmehwihk5tr7.js +534 -0
  91. package/dist/chunks/vendor-utils-ixnhxmehwihk5tr7.js.map +1 -0
  92. package/dist/code.js +1 -1
  93. package/dist/components/autocomplete.js +9 -0
  94. package/dist/components/autocomplete.js.map +1 -0
  95. package/dist/components/breadcrumbs.js +1 -1
  96. package/dist/components/button.js +1 -1
  97. package/dist/components/chart.js +1 -1
  98. package/dist/components/checkbox.js +1 -1
  99. package/dist/components/clipboard-text.js +1 -1
  100. package/dist/components/cloudflare-logo.js +1 -1
  101. package/dist/components/collapsible.js +1 -1
  102. package/dist/components/combobox.js +1 -1
  103. package/dist/components/command-palette.js +1 -1
  104. package/dist/components/date-range-picker.js +1 -1
  105. package/dist/components/dialog.js +1 -1
  106. package/dist/components/dropdown.js +1 -1
  107. package/dist/components/empty.js +1 -1
  108. package/dist/components/field.js +1 -1
  109. package/dist/components/flow.js +2 -2
  110. package/dist/components/flow.js.map +1 -1
  111. package/dist/components/grid.js +1 -1
  112. package/dist/components/input-group.js +8 -0
  113. package/dist/components/input-group.js.map +1 -0
  114. package/dist/components/input.js +9 -7
  115. package/dist/components/label.js +1 -1
  116. package/dist/components/layer-card.js +1 -1
  117. package/dist/components/link.js +1 -1
  118. package/dist/components/menubar.js +1 -1
  119. package/dist/components/meter.js +1 -1
  120. package/dist/components/pagination.js +1 -1
  121. package/dist/components/popover.js +1 -1
  122. package/dist/components/radio.js +1 -1
  123. package/dist/components/select.js +1 -1
  124. package/dist/components/sensitive-input.js +1 -1
  125. package/dist/components/sidebar.js +1 -1
  126. package/dist/components/surface.js +1 -1
  127. package/dist/components/switch.js +1 -1
  128. package/dist/components/table-of-contents.js +8 -0
  129. package/dist/components/table-of-contents.js.map +1 -0
  130. package/dist/components/table.js +1 -1
  131. package/dist/components/tabs.js +1 -1
  132. package/dist/components/text.js +1 -1
  133. package/dist/components/toast.js +2 -2
  134. package/dist/components/tooltip.js +1 -1
  135. package/dist/index.js +148 -139
  136. package/dist/index.js.map +1 -1
  137. package/dist/primitives/accordion.js +1 -1
  138. package/dist/primitives/alert-dialog.js +1 -1
  139. package/dist/primitives/autocomplete.js +1 -1
  140. package/dist/primitives/avatar.js +1 -1
  141. package/dist/primitives/button.js +1 -1
  142. package/dist/primitives/checkbox-group.js +1 -1
  143. package/dist/primitives/checkbox.js +1 -1
  144. package/dist/primitives/collapsible.js +1 -1
  145. package/dist/primitives/combobox.js +1 -1
  146. package/dist/primitives/context-menu.js +1 -1
  147. package/dist/primitives/csp-provider.js +1 -1
  148. package/dist/primitives/dialog.js +1 -1
  149. package/dist/primitives/direction-provider.js +1 -1
  150. package/dist/primitives/drawer.js +2 -2
  151. package/dist/primitives/field.js +1 -1
  152. package/dist/primitives/fieldset.js +1 -1
  153. package/dist/primitives/form.js +1 -1
  154. package/dist/primitives/input.js +1 -1
  155. package/dist/primitives/menu.js +1 -1
  156. package/dist/primitives/menubar.js +1 -1
  157. package/dist/primitives/meter.js +1 -1
  158. package/dist/primitives/navigation-menu.js +1 -1
  159. package/dist/primitives/number-field.js +1 -1
  160. package/dist/primitives/otp-field.js +6 -0
  161. package/dist/primitives/otp-field.js.map +1 -0
  162. package/dist/primitives/popover.js +1 -1
  163. package/dist/primitives/preview-card.js +2 -2
  164. package/dist/primitives/progress.js +1 -1
  165. package/dist/primitives/radio-group.js +1 -1
  166. package/dist/primitives/radio.js +1 -1
  167. package/dist/primitives/scroll-area.js +1 -1
  168. package/dist/primitives/select.js +1 -1
  169. package/dist/primitives/separator.js +1 -1
  170. package/dist/primitives/slider.js +1 -1
  171. package/dist/primitives/switch.js +1 -1
  172. package/dist/primitives/tabs.js +1 -1
  173. package/dist/primitives/toast.js +1 -1
  174. package/dist/primitives/toggle-group.js +1 -1
  175. package/dist/primitives/toggle.js +1 -1
  176. package/dist/primitives/toolbar.js +1 -1
  177. package/dist/primitives/tooltip.js +1 -1
  178. package/dist/primitives.js +22 -21
  179. package/dist/scripts/theme-generator/config.d.ts.map +1 -1
  180. package/dist/scripts/theme-generator/config.js +13 -3
  181. package/dist/scripts/theme-generator/config.js.map +1 -1
  182. package/dist/src/components/autocomplete/autocomplete.d.ts +180 -0
  183. package/dist/src/components/autocomplete/autocomplete.d.ts.map +1 -0
  184. package/dist/src/components/autocomplete/index.d.ts +2 -0
  185. package/dist/src/components/autocomplete/index.d.ts.map +1 -0
  186. package/dist/src/components/button/button.d.ts +3 -3
  187. package/dist/src/components/button/button.d.ts.map +1 -1
  188. package/dist/src/components/chart/Color.d.ts +36 -52
  189. package/dist/src/components/chart/Color.d.ts.map +1 -1
  190. package/dist/src/components/chart/EChart.d.ts +18 -2
  191. package/dist/src/components/chart/EChart.d.ts.map +1 -1
  192. package/dist/src/components/chart/TimeseriesChart.d.ts.map +1 -1
  193. package/dist/src/components/chart/index.d.ts +1 -1
  194. package/dist/src/components/chart/index.d.ts.map +1 -1
  195. package/dist/src/components/checkbox/checkbox.d.ts +37 -14
  196. package/dist/src/components/checkbox/checkbox.d.ts.map +1 -1
  197. package/dist/src/components/checkbox/index.d.ts +1 -1
  198. package/dist/src/components/checkbox/index.d.ts.map +1 -1
  199. package/dist/src/components/clipboard-text/clipboard-text.d.ts.map +1 -1
  200. package/dist/src/components/collapsible/collapsible.d.ts +77 -40
  201. package/dist/src/components/collapsible/collapsible.d.ts.map +1 -1
  202. package/dist/src/components/collapsible/index.d.ts +1 -1
  203. package/dist/src/components/collapsible/index.d.ts.map +1 -1
  204. package/dist/src/components/combobox/combobox.d.ts +19 -3
  205. package/dist/src/components/combobox/combobox.d.ts.map +1 -1
  206. package/dist/src/components/command-palette/command-palette.d.ts +2 -11
  207. package/dist/src/components/command-palette/command-palette.d.ts.map +1 -1
  208. package/dist/src/components/command-palette/index.d.ts +1 -1
  209. package/dist/src/components/command-palette/index.d.ts.map +1 -1
  210. package/dist/src/components/command-palette/types.d.ts +13 -1
  211. package/dist/src/components/command-palette/types.d.ts.map +1 -1
  212. package/dist/src/components/dropdown/dropdown.d.ts.map +1 -1
  213. package/dist/src/components/input/index.d.ts +16 -1
  214. package/dist/src/components/input/index.d.ts.map +1 -1
  215. package/dist/src/components/input/input.d.ts +2 -2
  216. package/dist/src/components/input/input.d.ts.map +1 -1
  217. package/dist/src/components/input-group/context.d.ts +96 -0
  218. package/dist/src/components/input-group/context.d.ts.map +1 -0
  219. package/dist/src/components/input-group/index.d.ts +2 -0
  220. package/dist/src/components/input-group/index.d.ts.map +1 -0
  221. package/dist/src/components/input-group/input-group-addon.d.ts +15 -0
  222. package/dist/src/components/input-group/input-group-addon.d.ts.map +1 -0
  223. package/dist/src/components/input-group/input-group-button.d.ts +36 -0
  224. package/dist/src/components/input-group/input-group-button.d.ts.map +1 -0
  225. package/dist/src/components/input-group/input-group-input.d.ts +9 -0
  226. package/dist/src/components/input-group/input-group-input.d.ts.map +1 -0
  227. package/dist/src/components/input-group/input-group-suffix.d.ts +13 -0
  228. package/dist/src/components/input-group/input-group-suffix.d.ts.map +1 -0
  229. package/dist/src/components/input-group/input-group.d.ts +43 -0
  230. package/dist/src/components/input-group/input-group.d.ts.map +1 -0
  231. package/dist/src/components/label/label.d.ts.map +1 -1
  232. package/dist/src/components/layer-card/layer-card.d.ts +39 -5
  233. package/dist/src/components/layer-card/layer-card.d.ts.map +1 -1
  234. package/dist/src/components/menubar/menubar.d.ts.map +1 -1
  235. package/dist/src/components/pagination/pagination.d.ts +51 -1
  236. package/dist/src/components/pagination/pagination.d.ts.map +1 -1
  237. package/dist/src/components/popover/popover.d.ts +35 -8
  238. package/dist/src/components/popover/popover.d.ts.map +1 -1
  239. package/dist/src/components/radio/index.d.ts +1 -1
  240. package/dist/src/components/radio/index.d.ts.map +1 -1
  241. package/dist/src/components/radio/radio.d.ts +44 -8
  242. package/dist/src/components/radio/radio.d.ts.map +1 -1
  243. package/dist/src/components/select/select.d.ts +52 -8
  244. package/dist/src/components/select/select.d.ts.map +1 -1
  245. package/dist/src/components/sensitive-input/sensitive-input.d.ts +2 -2
  246. package/dist/src/components/sidebar/sidebar.d.ts +2 -2
  247. package/dist/src/components/sidebar/sidebar.d.ts.map +1 -1
  248. package/dist/src/components/surface/index.d.ts +3 -0
  249. package/dist/src/components/surface/index.d.ts.map +1 -1
  250. package/dist/src/components/surface/surface.d.ts +14 -10
  251. package/dist/src/components/surface/surface.d.ts.map +1 -1
  252. package/dist/src/components/switch/index.d.ts +1 -1
  253. package/dist/src/components/switch/index.d.ts.map +1 -1
  254. package/dist/src/components/switch/switch.d.ts +31 -3
  255. package/dist/src/components/switch/switch.d.ts.map +1 -1
  256. package/dist/src/components/table/table.d.ts +17 -2
  257. package/dist/src/components/table/table.d.ts.map +1 -1
  258. package/dist/src/components/table-of-contents/index.d.ts +2 -0
  259. package/dist/src/components/table-of-contents/index.d.ts.map +1 -0
  260. package/dist/src/components/table-of-contents/table-of-contents.d.ts +72 -0
  261. package/dist/src/components/table-of-contents/table-of-contents.d.ts.map +1 -0
  262. package/dist/src/components/text/text.d.ts +34 -6
  263. package/dist/src/components/text/text.d.ts.map +1 -1
  264. package/dist/src/components/text/text.type-spec.d.ts +44 -0
  265. package/dist/src/components/text/text.type-spec.d.ts.map +1 -0
  266. package/dist/src/components/toast/toast.d.ts +1 -1
  267. package/dist/src/components/toast/toast.d.ts.map +1 -1
  268. package/dist/src/components/tooltip/tooltip.d.ts +15 -6
  269. package/dist/src/components/tooltip/tooltip.d.ts.map +1 -1
  270. package/dist/src/index.d.ts +14 -8
  271. package/dist/src/index.d.ts.map +1 -1
  272. package/dist/src/primitives/index.d.ts +1 -0
  273. package/dist/src/primitives/index.d.ts.map +1 -1
  274. package/dist/src/primitives/otp-field.d.ts +13 -0
  275. package/dist/src/primitives/otp-field.d.ts.map +1 -0
  276. package/dist/styles/kumo-binding.css +19 -0
  277. package/dist/styles/kumo-standalone.css +1 -1
  278. package/dist/styles/kumo.css +2 -2
  279. package/dist/styles/theme-kumo.css +13 -6
  280. package/package.json +18 -2
  281. package/scripts/component-registry/discovery.ts +1 -0
  282. package/scripts/component-registry/index.test.ts +265 -0
  283. package/scripts/component-registry/index.ts +14 -0
  284. package/scripts/component-registry/metadata.ts +55 -7
  285. package/scripts/component-registry/sub-components.ts +81 -50
  286. package/scripts/component-registry/types.ts +2 -0
  287. package/scripts/theme-generator/config.ts +18 -6
  288. package/dist/chunks/Legend-o0ntojbaplmszwk0.js +0 -421
  289. package/dist/chunks/Legend-o0ntojbaplmszwk0.js.map +0 -1
  290. package/dist/chunks/button-cdxnqcgzwko8ooha.js.map +0 -1
  291. package/dist/chunks/checkbox-kt1uojk2f9e0d0h1.js +0 -211
  292. package/dist/chunks/checkbox-kt1uojk2f9e0d0h1.js.map +0 -1
  293. package/dist/chunks/collapsible-jhzee3ks51d3xowb.js +0 -58
  294. package/dist/chunks/collapsible-jhzee3ks51d3xowb.js.map +0 -1
  295. package/dist/chunks/combobox-he2hd9e2ruknq5mp.js.map +0 -1
  296. package/dist/chunks/command-palette-jc1w07jwakxvj23a.js.map +0 -1
  297. package/dist/chunks/dialog-oqh8l3l3zutpibxx.js.map +0 -1
  298. package/dist/chunks/dropdown-ncwhcd912vmone8k.js +0 -300
  299. package/dist/chunks/dropdown-ncwhcd912vmone8k.js.map +0 -1
  300. package/dist/chunks/input-group-lxdd09p60cf27pe1.js +0 -111
  301. package/dist/chunks/input-group-lxdd09p60cf27pe1.js.map +0 -1
  302. package/dist/chunks/input-h48k3uagzrgb98au.js.map +0 -1
  303. package/dist/chunks/label-latndvb1ngem7we8.js +0 -62
  304. package/dist/chunks/layer-card-l5yjvrxry1dhte57.js +0 -44
  305. package/dist/chunks/layer-card-l5yjvrxry1dhte57.js.map +0 -1
  306. package/dist/chunks/menubar-f1pilzooe5mue7c4.js +0 -92
  307. package/dist/chunks/menubar-f1pilzooe5mue7c4.js.map +0 -1
  308. package/dist/chunks/pagination-cu5lm6p5dxuycta4.js +0 -243
  309. package/dist/chunks/pagination-cu5lm6p5dxuycta4.js.map +0 -1
  310. package/dist/chunks/popover-h300w4vit0s2ayej.js.map +0 -1
  311. package/dist/chunks/radio-jouttv89lbvhs55r.js.map +0 -1
  312. package/dist/chunks/select-kva5ru5f673kah1m.js +0 -179
  313. package/dist/chunks/select-kva5ru5f673kah1m.js.map +0 -1
  314. package/dist/chunks/sensitive-input-hd4tpqkzifad1yca.js.map +0 -1
  315. package/dist/chunks/sidebar-hljy3ssm8itc0ucx.js.map +0 -1
  316. package/dist/chunks/surface-cilvbyhmyujz1bee.js +0 -36
  317. package/dist/chunks/surface-cilvbyhmyujz1bee.js.map +0 -1
  318. package/dist/chunks/switch-ihaydbzem62bey4p.js.map +0 -1
  319. package/dist/chunks/table-inweecadl3her7pd.js +0 -183
  320. package/dist/chunks/table-inweecadl3her7pd.js.map +0 -1
  321. package/dist/chunks/text-nmyi1rkwdj37f30f.js.map +0 -1
  322. package/dist/chunks/tooltip-belkznz8t8333h5f.js.map +0 -1
  323. package/dist/chunks/vendor-base-ui-k7bzesq81ie36nya.js +0 -22813
  324. package/dist/chunks/vendor-base-ui-k7bzesq81ie36nya.js.map +0 -1
  325. package/dist/chunks/vendor-floating-ui-gr9m6tsa1cpqwn99.js +0 -1286
  326. package/dist/chunks/vendor-floating-ui-gr9m6tsa1cpqwn99.js.map +0 -1
  327. package/dist/chunks/vendor-utils-fxk97j6xi1g42z2v.js +0 -740
  328. package/dist/chunks/vendor-utils-fxk97j6xi1g42z2v.js.map +0 -1
  329. package/dist/src/components/input/input-group.d.ts +0 -39
  330. package/dist/src/components/input/input-group.d.ts.map +0 -1
@@ -1,6 +1,171 @@
1
1
  {
2
2
  "version": "1.0.0",
3
3
  "components": {
4
+ "Autocomplete": {
5
+ "name": "Autocomplete",
6
+ "type": "component",
7
+ "description": "Autocomplete — free-form text input with an optional filtered suggestion list. Unlike Combobox, the input value is not restricted to items in the list. Use Combobox when the selected value must come from the list. Compound component: `Autocomplete` (Root), `.InputGroup`, `.Content`, `.Item`, `.GroupLabel`, `.Group`, `.Separator`, `.List`, `.Collection`. `InputGroup` renders the text input with Input component styling. Pass a `size` prop to `InputGroup` to match the Input component sizes.",
8
+ "importPath": "@cloudflare/kumo",
9
+ "category": "Other",
10
+ "props": {
11
+ "items": {
12
+ "type": "unknown[]",
13
+ "required": true,
14
+ "description": "Array of items to display in the dropdown"
15
+ },
16
+ "value": {
17
+ "type": "string | number | string[]",
18
+ "optional": true,
19
+ "description": "The controlled input value"
20
+ },
21
+ "open": {
22
+ "type": "boolean",
23
+ "optional": true,
24
+ "description": "Whether the popup is open (controlled)"
25
+ },
26
+ "children": {
27
+ "type": "ReactNode",
28
+ "optional": true,
29
+ "description": "Autocomplete content (input group, popup content)"
30
+ },
31
+ "className": {
32
+ "type": "string",
33
+ "optional": true,
34
+ "description": "Additional CSS classes"
35
+ },
36
+ "label": {
37
+ "type": "ReactNode",
38
+ "optional": true,
39
+ "description": "Label content (enables Field wrapper)"
40
+ },
41
+ "required": {
42
+ "type": "boolean",
43
+ "optional": true,
44
+ "description": "Whether the field is required"
45
+ },
46
+ "labelTooltip": {
47
+ "type": "ReactNode",
48
+ "optional": true,
49
+ "description": "Tooltip content to display next to the label"
50
+ },
51
+ "description": {
52
+ "type": "ReactNode",
53
+ "optional": true,
54
+ "description": "Helper text displayed below the field"
55
+ },
56
+ "error": {
57
+ "type": "string | object",
58
+ "optional": true,
59
+ "description": "Error message or validation error object"
60
+ }
61
+ },
62
+ "examples": [
63
+ "<Autocomplete items={fruits}>\n <Autocomplete.InputGroup placeholder=\"Search fruits…\" />\n <Autocomplete.Content>\n <Autocomplete.List>\n {(item: string) => (\n <Autocomplete.Item key={item} value={item}>\n {item}\n </Autocomplete.Item>\n )}\n </Autocomplete.List>\n </Autocomplete.Content>\n </Autocomplete>",
64
+ "<div className=\"w-80\">\n <Autocomplete\n items={countries}\n label=\"Country\"\n description=\"Start typing to filter countries\"\n filter={(item: Country, query: string) =>\n item.label.toLowerCase().includes(query.toLowerCase())\n }\n >\n <Autocomplete.InputGroup placeholder=\"Search countries…\" />\n <Autocomplete.Content>\n <Autocomplete.List>\n {(item: Country) => (\n <Autocomplete.Item key={item.code} value={item}>\n {item.label}\n </Autocomplete.Item>\n )}\n </Autocomplete.List>\n </Autocomplete.Content>\n </Autocomplete>\n </div>",
65
+ "<div className=\"w-80\">\n <Autocomplete\n items={countries}\n label=\"Country\"\n error={{ message: \"Please enter a valid country\", match: true }}\n filter={(item: Country, query: string) =>\n item.label.toLowerCase().includes(query.toLowerCase())\n }\n >\n <Autocomplete.InputGroup placeholder=\"Search countries…\" />\n <Autocomplete.Content>\n <Autocomplete.List>\n {(item: Country) => (\n <Autocomplete.Item key={item.code} value={item}>\n {item.label}\n </Autocomplete.Item>\n )}\n </Autocomplete.List>\n </Autocomplete.Content>\n </Autocomplete>\n </div>",
66
+ "<Autocomplete items={servers}>\n <Autocomplete.InputGroup placeholder=\"Select region…\" />\n <Autocomplete.Content>\n <Autocomplete.List>\n {(group: ServerGroup) => (\n <Autocomplete.Group key={group.value} items={group.items}>\n <Autocomplete.GroupLabel>{group.value}</Autocomplete.GroupLabel>\n <Autocomplete.Collection>\n {(item: ServerLocation) => (\n <Autocomplete.Item key={item.value} value={item}>\n {item.label}\n </Autocomplete.Item>\n )}\n </Autocomplete.Collection>\n </Autocomplete.Group>\n )}\n </Autocomplete.List>\n </Autocomplete.Content>\n </Autocomplete>",
67
+ "<div className=\"flex flex-wrap items-center gap-4\">\n <Autocomplete items={fruits.slice(0, 10)}>\n <Autocomplete.InputGroup size=\"xs\" placeholder=\"xs\" />\n <Autocomplete.Content>\n <Autocomplete.List>\n {(item: string) => (\n <Autocomplete.Item key={item} value={item}>\n {item}\n </Autocomplete.Item>\n )}\n </Autocomplete.List>\n </Autocomplete.Content>\n </Autocomplete>\n <Autocomplete items={fruits.slice(0, 10)}>\n <Autocomplete.InputGroup size=\"sm\" placeholder=\"sm\" />\n <Autocomplete.Content>\n <Autocomplete.List>\n {(item: string) => (\n <Autocomplete.Item key={item} value={item}>\n {item}\n </Autocomplete.Item>\n )}\n </Autocomplete.List>\n </Autocomplete.Content>\n </Autocomplete>\n <Autocomplete items={fruits.slice(0, 10)}>\n <Autocomplete.InputGroup size=\"base\" placeholder=\"base (default)\" />\n <Autocomplete.Content>\n <Autocomplete.List>\n {(item: string) => (\n <Autocomplete.Item key={item} value={item}>\n {item}\n </Autocomplete.Item>\n )}\n </Autocomplete.List>\n </Autocomplete.Content>\n </Autocomplete>\n <Autocomplete items={fruits.slice(0, 10)}>\n <Autocomplete.InputGroup size=\"lg\" placeholder=\"lg\" />\n <Autocomplete.Content>\n <Autocomplete.List>\n {(item: string) => (\n <Autocomplete.Item key={item} value={item}>\n {item}\n </Autocomplete.Item>\n )}\n </Autocomplete.List>\n </Autocomplete.Content>\n </Autocomplete>\n </div>",
68
+ "<div className=\"flex flex-col gap-3 w-80\">\n <Autocomplete\n items={fruits}\n value={value}\n onValueChange={(v) => setValue(v)}\n >\n <Autocomplete.InputGroup placeholder=\"Type a fruit…\" />\n <Autocomplete.Content>\n <Autocomplete.List>\n {(item: string) => (\n <Autocomplete.Item key={item} value={item}>\n {item}\n </Autocomplete.Item>\n )}\n </Autocomplete.List>\n </Autocomplete.Content>\n </Autocomplete>\n {value && (\n <p className=\"text-sm text-kumo-subtle\">\n Value: <span className=\"text-kumo-default font-medium\">{value}</span>\n </p>\n )}\n </div>"
69
+ ],
70
+ "colors": [
71
+ "bg-kumo-control",
72
+ "bg-kumo-line",
73
+ "bg-kumo-overlay",
74
+ "border-kumo-line",
75
+ "ring-kumo-line",
76
+ "text-kumo-default",
77
+ "text-kumo-strong"
78
+ ],
79
+ "subComponents": {
80
+ "InputGroup": {
81
+ "name": "InputGroup",
82
+ "description": "InputGroup sub-component",
83
+ "props": {
84
+ "className": {
85
+ "type": "string",
86
+ "optional": true
87
+ },
88
+ "size": {
89
+ "type": "KumoAutocompleteSize",
90
+ "optional": true
91
+ },
92
+ "placeholder": {
93
+ "type": "string",
94
+ "optional": true
95
+ }
96
+ }
97
+ },
98
+ "Content": {
99
+ "name": "Content",
100
+ "description": "Content sub-component",
101
+ "props": {
102
+ "children": {
103
+ "type": "ReactNode",
104
+ "optional": true
105
+ },
106
+ "className": {
107
+ "type": "string",
108
+ "optional": true
109
+ },
110
+ "align": {
111
+ "type": "AutocompleteBase.Positioner.Props[\"align\"]",
112
+ "optional": true
113
+ },
114
+ "alignOffset": {
115
+ "type": "AutocompleteBase.Positioner.Props[\"alignOffset\"]",
116
+ "optional": true
117
+ },
118
+ "side": {
119
+ "type": "AutocompleteBase.Positioner.Props[\"side\"]",
120
+ "optional": true
121
+ },
122
+ "sideOffset": {
123
+ "type": "AutocompleteBase.Positioner.Props[\"sideOffset\"]",
124
+ "optional": true
125
+ }
126
+ }
127
+ },
128
+ "Item": {
129
+ "name": "Item",
130
+ "description": "Item sub-component",
131
+ "props": {}
132
+ },
133
+ "GroupLabel": {
134
+ "name": "GroupLabel",
135
+ "description": "GroupLabel sub-component",
136
+ "props": {}
137
+ },
138
+ "Group": {
139
+ "name": "Group",
140
+ "description": "Group sub-component",
141
+ "props": {}
142
+ },
143
+ "Separator": {
144
+ "name": "Separator",
145
+ "description": "Separator sub-component",
146
+ "props": {}
147
+ },
148
+ "List": {
149
+ "name": "List",
150
+ "description": "List sub-component",
151
+ "props": {}
152
+ },
153
+ "Empty": {
154
+ "name": "Empty",
155
+ "description": "Empty sub-component (wraps AutocompleteBase)",
156
+ "props": {},
157
+ "isPassThrough": true,
158
+ "baseComponent": "AutocompleteBase.Empty"
159
+ },
160
+ "Collection": {
161
+ "name": "Collection",
162
+ "description": "Collection sub-component (wraps AutocompleteBase)",
163
+ "props": {},
164
+ "isPassThrough": true,
165
+ "baseComponent": "AutocompleteBase.Collection"
166
+ }
167
+ }
168
+ },
4
169
  "Badge": {
5
170
  "name": "Badge",
6
171
  "type": "component",
@@ -368,21 +533,20 @@
368
533
  "outline": "Bordered button with transparent background"
369
534
  },
370
535
  "classes": {
371
- "primary": "bg-kumo-brand !text-white hover:bg-kumo-brand-hover focus:bg-kumo-brand-hover disabled:bg-kumo-brand/50",
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",
536
+ "primary": "bg-kumo-brand !text-white hover:bg-kumo-brand-hover disabled:bg-kumo-brand/50",
537
+ "secondary": "bg-kumo-base !text-kumo-default ring 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
538
  "ghost": "text-kumo-default hover:bg-kumo-tint shadow-none bg-inherit",
374
539
  "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",
540
+ "secondary-destructive": "bg-kumo-base !text-kumo-danger ring 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
541
  "outline": "bg-transparent text-kumo-default ring ring-kumo-hairline"
377
542
  },
378
543
  "stateClasses": {
379
544
  "primary": {
380
545
  "hover": "hover:bg-kumo-brand-hover",
381
- "focus": "focus:bg-kumo-brand-hover",
382
546
  "disabled": "disabled:bg-kumo-brand/50"
383
547
  },
384
548
  "secondary": {
385
- "not-disabled": "not-disabled:hover:border-secondary! not-disabled:hover:bg-kumo-tint",
549
+ "not-disabled": "not-disabled:hover:bg-kumo-tint",
386
550
  "disabled": "disabled:bg-kumo-base/50 disabled:!text-kumo-default/70",
387
551
  "data-state": "data-[state=open]:bg-kumo-base"
388
552
  },
@@ -393,7 +557,7 @@
393
557
  "hover": "hover:bg-kumo-danger/70"
394
558
  },
395
559
  "secondary-destructive": {
396
- "not-disabled": "not-disabled:hover:border-secondary! not-disabled:hover:bg-kumo-base",
560
+ "not-disabled": "not-disabled:hover:bg-kumo-base",
397
561
  "disabled": "disabled:bg-kumo-base/50 disabled:!text-kumo-danger/70",
398
562
  "data-state": "data-[state=open]:bg-kumo-base"
399
563
  }
@@ -466,7 +630,8 @@
466
630
  "<Button variant=\"primary\" loading>\n Loading...\n </Button>",
467
631
  "<Button variant=\"secondary\" disabled>\n Disabled\n </Button>",
468
632
  "<Button variant=\"secondary\">Click me</Button>",
469
- "<div className=\"flex flex-wrap items-center gap-3\">\n <Button variant=\"secondary\" title=\"Create a new Worker\">\n Create Worker\n </Button>\n <Button\n variant=\"secondary\"\n shape=\"square\"\n icon={PlusIcon}\n aria-label=\"Add item\"\n title=\"Add item\"\n />\n </div>"
633
+ "<div className=\"flex flex-wrap items-center gap-3\">\n <Button variant=\"secondary\" title=\"Create a new Worker\">\n Create Worker\n </Button>\n <Button\n variant=\"secondary\"\n shape=\"square\"\n icon={PlusIcon}\n aria-label=\"Add item\"\n title=\"Add item\"\n />\n </div>",
634
+ "<div className=\"flex flex-wrap items-center gap-3\">\n <LinkButton href=\"/components/link\" variant=\"secondary\">\n Read Link docs\n </LinkButton>\n <LinkButton\n href=\"https://developers.cloudflare.com\"\n variant=\"ghost\"\n icon={ArrowSquareOutIcon}\n external\n >\n Cloudflare Docs\n </LinkButton>\n </div>"
470
635
  ],
471
636
  "colors": [
472
637
  "bg-kumo-base",
@@ -474,8 +639,9 @@
474
639
  "bg-kumo-brand-hover",
475
640
  "bg-kumo-danger",
476
641
  "bg-kumo-tint",
642
+ "ring-kumo-brand",
643
+ "ring-kumo-focus",
477
644
  "ring-kumo-hairline",
478
- "ring-kumo-line",
479
645
  "text-kumo-danger",
480
646
  "text-kumo-default",
481
647
  "text-kumo-subtle"
@@ -501,12 +667,12 @@
501
667
  "error": "Error state for validation failures"
502
668
  },
503
669
  "classes": {
504
- "default": "[&:focus-within>span]:ring-kumo-hairline [&:hover>span]:ring-kumo-hairline",
670
+ "default": "[&:focus-within>span]:ring-kumo-focus [&:hover>span]:ring-kumo-hairline",
505
671
  "error": "[&>span]:ring-kumo-danger"
506
672
  },
507
673
  "stateClasses": {
508
674
  "default": {
509
- "focus": "[&:focus-within>span]:ring-kumo-hairline",
675
+ "focus": "[&:focus-within>span]:ring-kumo-focus",
510
676
  "hover": "[&:hover>span]:ring-kumo-hairline"
511
677
  }
512
678
  },
@@ -556,10 +722,6 @@
556
722
  "type": "string",
557
723
  "optional": true,
558
724
  "description": "Additional class name"
559
- },
560
- "onValueChange": {
561
- "type": "(checked: boolean) => void",
562
- "description": "Callback when checkbox value changes"
563
725
  }
564
726
  },
565
727
  "examples": [
@@ -571,15 +733,18 @@
571
733
  "<Checkbox label=\"Disabled option\" disabled />",
572
734
  "<Checkbox label=\"Invalid option\" variant=\"error\" />",
573
735
  "<Checkbox.Group\n legend=\"Email preferences\"\n description=\"Choose how you'd like to receive updates\"\n value={preferences}\n onValueChange={setPreferences}\n >\n <Checkbox.Item value=\"email\" label=\"Email notifications\" />\n <Checkbox.Item value=\"sms\" label=\"SMS notifications\" />\n <Checkbox.Item value=\"push\" label=\"Push notifications\" />\n </Checkbox.Group>",
736
+ "<Checkbox.Group value={preferences} onValueChange={setPreferences}>\n <Checkbox.Legend className=\"sr-only\">\n Notification preferences\n </Checkbox.Legend>\n <Checkbox.Item value=\"email\" label=\"Email notifications\" />\n <Checkbox.Item value=\"sms\" label=\"SMS notifications\" />\n <Checkbox.Item value=\"push\" label=\"Push notifications\" />\n </Checkbox.Group>",
737
+ "<Checkbox.Group value={preferences} onValueChange={setPreferences}>\n <Checkbox.Legend className=\"text-sm font-normal text-kumo-subtle\">\n Notification preferences\n </Checkbox.Legend>\n <Checkbox.Item value=\"email\" label=\"Email notifications\" />\n <Checkbox.Item value=\"sms\" label=\"SMS notifications\" />\n <Checkbox.Item value=\"push\" label=\"Push notifications\" />\n </Checkbox.Group>",
574
738
  "<Checkbox.Group\n legend=\"Required preferences\"\n error=\"Please select at least one notification method\"\n value={[]}\n onValueChange={() => {}}\n >\n <Checkbox.Item value=\"email\" label=\"Email\" variant=\"error\" />\n <Checkbox.Item value=\"sms\" label=\"SMS\" variant=\"error\" />\n </Checkbox.Group>"
575
739
  ],
576
740
  "colors": [
577
741
  "bg-kumo-base",
578
742
  "bg-kumo-contrast",
743
+ "ring-kumo-brand",
579
744
  "ring-kumo-contrast",
580
745
  "ring-kumo-danger",
746
+ "ring-kumo-focus",
581
747
  "ring-kumo-hairline",
582
- "ring-kumo-line",
583
748
  "text-kumo-danger",
584
749
  "text-kumo-default",
585
750
  "text-kumo-inverse",
@@ -597,7 +762,7 @@
597
762
  "props": {
598
763
  "legend": {
599
764
  "type": "string",
600
- "required": true
765
+ "optional": true
601
766
  },
602
767
  "children": {
603
768
  "type": "ReactNode",
@@ -632,6 +797,20 @@
632
797
  "optional": true
633
798
  }
634
799
  }
800
+ },
801
+ "Legend": {
802
+ "name": "Legend",
803
+ "description": "Legend sub-component",
804
+ "props": {
805
+ "children": {
806
+ "type": "ReactNode",
807
+ "required": true
808
+ },
809
+ "className": {
810
+ "type": "string",
811
+ "optional": true
812
+ }
813
+ }
635
814
  }
636
815
  },
637
816
  "styling": {
@@ -744,6 +923,8 @@
744
923
  "bg-kumo-base",
745
924
  "border-kumo-line",
746
925
  "outline-kumo-fill",
926
+ "ring-kumo-brand",
927
+ "ring-kumo-focus",
747
928
  "text-kumo-default"
748
929
  ],
749
930
  "styling": {
@@ -1945,11 +2126,11 @@
1945
2126
  "<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
2127
  "<PoweredByCloudflare />",
1947
2128
  "<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>"
2129
+ "<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
2130
  ],
1950
2131
  "colors": [
1951
2132
  "bg-kumo-base",
1952
- "ring-kumo-line",
2133
+ "ring-kumo-hairline",
1953
2134
  "text-kumo-default"
1954
2135
  ]
1955
2136
  },
@@ -2042,28 +2223,14 @@
2042
2223
  "Collapsible": {
2043
2224
  "name": "Collapsible",
2044
2225
  "type": "component",
2045
- "description": "Collapsible component for showing/hiding content. Features: - Animated chevron indicator (rotates 180° when open) - Accessible with aria-expanded and aria-controls - Content panel with left border accent",
2226
+ "description": "Collapsible — a composable disclosure component for showing/hiding content. Built on Base UI's Collapsible with full composition support. ## Basic Usage ```tsx const [open, setOpen] = useState(false); <Collapsible.Root open={open} onOpenChange={setOpen}> <Collapsible.Trigger render={<Button variant=\"ghost\" />}> Show details </Collapsible.Trigger> <Collapsible.Panel className=\"mt-2\"> <Text>Hidden content revealed when expanded.</Text> </Collapsible.Panel> </Collapsible.Root> ``` ## With Default Styling Use `DefaultTrigger` and `DefaultPanel` for the classic Kumo style: ```tsx <Collapsible.Root> <Collapsible.DefaultTrigger>Show details</Collapsible.DefaultTrigger> <Collapsible.DefaultPanel> <Text>Content with border-left accent</Text> </Collapsible.DefaultPanel> </Collapsible.Root> ``` ## Controlled Accordion Pattern ```tsx const [activeIndex, setActiveIndex] = useState<number | null>(null); {items.map((item, i) => ( <Collapsible.Root key={i} open={activeIndex === i} onOpenChange={(open) => setActiveIndex(open ? i : null)} > <Collapsible.DefaultTrigger>{item.title}</Collapsible.DefaultTrigger> <Collapsible.DefaultPanel>{item.content}</Collapsible.DefaultPanel> </Collapsible.Root> ))} ```",
2046
2227
  "importPath": "@cloudflare/kumo",
2047
2228
  "category": "Display",
2048
2229
  "props": {
2049
- "children": {
2050
- "type": "ReactNode",
2051
- "optional": true
2052
- },
2053
- "label": {
2054
- "type": "string",
2055
- "required": true,
2056
- "description": "Text label displayed in the trigger button"
2057
- },
2058
- "open": {
2059
- "type": "boolean",
2060
- "optional": true,
2061
- "description": "Whether the collapsible content is visible"
2062
- },
2063
2230
  "className": {
2064
2231
  "type": "string",
2065
2232
  "optional": true,
2066
- "description": "Additional CSS classes for the content panel"
2233
+ "description": "Additional CSS classes"
2067
2234
  },
2068
2235
  "onOpenChange": {
2069
2236
  "type": "(open: boolean) => void",
@@ -2071,14 +2238,76 @@
2071
2238
  }
2072
2239
  },
2073
2240
  "examples": [
2074
- "<div className=\"w-full\">\n <Collapsible label=\"What is Kumo?\" open={isOpen} onOpenChange={setIsOpen}>\n Kumo is Cloudflare's new design system.\n </Collapsible>\n </div>",
2075
- "<div className=\"w-full\">\n <Collapsible label=\"What is Kumo?\" open={isOpen} onOpenChange={setIsOpen}>\n Kumo is Cloudflare's new design system.\n </Collapsible>\n </div>",
2076
- "<div className=\"w-full space-y-2\">\n <Collapsible label=\"What is Kumo?\" open={open1} onOpenChange={setOpen1}>\n Kumo is Cloudflare's new design system.\n </Collapsible>\n <Collapsible\n label=\"How do I use it?\"\n open={open2}\n onOpenChange={setOpen2}\n >\n Install the components and import them into your project.\n </Collapsible>\n <Collapsible\n label=\"Is it open source?\"\n open={open3}\n onOpenChange={setOpen3}\n >\n Check the repository for license information.\n </Collapsible>\n </div>"
2241
+ "<div className=\"w-full\">\n <Collapsible.Root open={isOpen} onOpenChange={setIsOpen}>\n <Collapsible.DefaultTrigger>What is Kumo?</Collapsible.DefaultTrigger>\n <Collapsible.DefaultPanel>\n <Text>Kumo is Cloudflare's new design system.</Text>\n </Collapsible.DefaultPanel>\n </Collapsible.Root>\n </div>",
2242
+ "<div className=\"w-full\">\n <Collapsible.Root open={isOpen} onOpenChange={setIsOpen}>\n <Collapsible.DefaultTrigger>What is Kumo?</Collapsible.DefaultTrigger>\n <Collapsible.DefaultPanel>\n <Text>Kumo is Cloudflare's new design system.</Text>\n </Collapsible.DefaultPanel>\n </Collapsible.Root>\n </div>",
2243
+ "<div className=\"w-full space-y-2\">\n <Collapsible.Root open={open1} onOpenChange={setOpen1}>\n <Collapsible.DefaultTrigger>What is Kumo?</Collapsible.DefaultTrigger>\n <Collapsible.DefaultPanel>\n <Text>Kumo is Cloudflare's new design system.</Text>\n </Collapsible.DefaultPanel>\n </Collapsible.Root>\n <Collapsible.Root open={open2} onOpenChange={setOpen2}>\n <Collapsible.DefaultTrigger>How do I use it?</Collapsible.DefaultTrigger>\n <Collapsible.DefaultPanel>\n <Text>Install the components and import them into your project.</Text>\n </Collapsible.DefaultPanel>\n </Collapsible.Root>\n <Collapsible.Root open={open3} onOpenChange={setOpen3}>\n <Collapsible.DefaultTrigger>Is it open source?</Collapsible.DefaultTrigger>\n <Collapsible.DefaultPanel>\n <Text>Check the repository for license information.</Text>\n </Collapsible.DefaultPanel>\n </Collapsible.Root>\n </div>",
2244
+ "<div className=\"w-full\">\n <Collapsible.Root open={isOpen} onOpenChange={setIsOpen}>\n <Collapsible.Trigger\n render={<Button variant=\"secondary\" size=\"sm\" />}\n >\n {isOpen ? \"Hide details\" : \"Show details\"}\n </Collapsible.Trigger>\n <Collapsible.Panel className=\"mt-3 rounded-lg bg-kumo-tint p-4\">\n <Text>\n This panel uses custom styling instead of the default border-left accent.\n </Text>\n </Collapsible.Panel>\n </Collapsible.Root>\n </div>",
2245
+ "<div className=\"w-full space-y-2\">\n {items.map((item, i) => (\n <Collapsible.Root\n key={i}\n open={activeIndex === i}\n onOpenChange={(open) => setActiveIndex(open ? i : null)}\n >\n <Collapsible.DefaultTrigger>{item.title}</Collapsible.DefaultTrigger>\n <Collapsible.DefaultPanel>\n <Text>{item.content}</Text>\n </Collapsible.DefaultPanel>\n </Collapsible.Root>\n ))}\n </div>"
2077
2246
  ],
2078
2247
  "colors": [
2079
2248
  "border-kumo-fill",
2080
2249
  "text-kumo-link"
2081
- ]
2250
+ ],
2251
+ "subComponents": {
2252
+ "Root": {
2253
+ "name": "Root",
2254
+ "description": "Root sub-component",
2255
+ "props": {
2256
+ "className": {
2257
+ "type": "string",
2258
+ "optional": true
2259
+ }
2260
+ }
2261
+ },
2262
+ "Trigger": {
2263
+ "name": "Trigger",
2264
+ "description": "Trigger sub-component",
2265
+ "props": {
2266
+ "className": {
2267
+ "type": "string",
2268
+ "optional": true
2269
+ }
2270
+ }
2271
+ },
2272
+ "Panel": {
2273
+ "name": "Panel",
2274
+ "description": "Panel sub-component",
2275
+ "props": {
2276
+ "className": {
2277
+ "type": "string",
2278
+ "optional": true
2279
+ }
2280
+ }
2281
+ },
2282
+ "DefaultTrigger": {
2283
+ "name": "DefaultTrigger",
2284
+ "description": "DefaultTrigger sub-component",
2285
+ "props": {
2286
+ "children": {
2287
+ "type": "ReactNode",
2288
+ "required": true
2289
+ },
2290
+ "className": {
2291
+ "type": "string",
2292
+ "optional": true
2293
+ }
2294
+ }
2295
+ },
2296
+ "DefaultPanel": {
2297
+ "name": "DefaultPanel",
2298
+ "description": "DefaultPanel sub-component",
2299
+ "props": {
2300
+ "children": {
2301
+ "type": "ReactNode",
2302
+ "required": true
2303
+ },
2304
+ "className": {
2305
+ "type": "string",
2306
+ "optional": true
2307
+ }
2308
+ }
2309
+ }
2310
+ }
2082
2311
  },
2083
2312
  "Combobox": {
2084
2313
  "name": "Combobox",
@@ -2178,6 +2407,7 @@
2178
2407
  "<div className=\"flex gap-2\">\n <Combobox\n value={value}\n onValueChange={setValue}\n items={bots}\n isItemEqualToValue={(bot: BotItem, selected: BotItem) =>\n bot.value === selected.value\n }\n multiple\n >\n <Combobox.TriggerMultipleWithInput\n className=\"w-[400px]\"\n placeholder=\"Select bots\"\n renderItem={(selected: BotItem) => (\n <Combobox.Chip key={selected.value}>{selected.label}</Combobox.Chip>\n )}\n inputSide=\"right\"\n />\n <Combobox.Content className=\"max-h-[200px] min-w-auto overflow-y-auto\">\n <Combobox.Empty />\n <Combobox.List>\n {(item: BotItem) => (\n <Combobox.Item key={item.value} value={item}>\n <div className=\"flex gap-2\">\n <Text>{item.label}</Text>\n <Text variant=\"secondary\">{item.author}</Text>\n </div>\n </Combobox.Item>\n )}\n </Combobox.List>\n </Combobox.Content>\n </Combobox>\n <Button variant=\"primary\">Submit</Button>\n </div>",
2179
2408
  "<div className=\"w-80\">\n <Combobox\n items={databases}\n value={value}\n onValueChange={setValue}\n label=\"Database\"\n description=\"Select your preferred database\"\n >\n <Combobox.TriggerInput placeholder=\"Select database\" />\n <Combobox.Content>\n <Combobox.Empty />\n <Combobox.List>\n {(item: DatabaseItem) => (\n <Combobox.Item key={item.value} value={item}>\n {item.label}\n </Combobox.Item>\n )}\n </Combobox.List>\n </Combobox.Content>\n </Combobox>\n </div>",
2180
2409
  "<div className=\"flex flex-wrap gap-4 items-start\">\n <Combobox value=\"Apple\" items={fruits} disabled>\n <Combobox.TriggerInput\n className=\"w-[200px]\"\n placeholder=\"Select fruit\"\n />\n <Combobox.Content>\n <Combobox.Empty />\n <Combobox.List>\n {(item: string) => (\n <Combobox.Item key={item} value={item}>\n {item}\n </Combobox.Item>\n )}\n </Combobox.List>\n </Combobox.Content>\n </Combobox>\n\n <Combobox value={languages[0]} items={languages} disabled>\n <Combobox.TriggerValue className=\"w-[200px]\" />\n <Combobox.Content>\n <Combobox.Input placeholder=\"Search\" />\n <Combobox.Empty />\n <Combobox.List>\n {(item: Language) => (\n <Combobox.Item key={item.value} value={item}>\n {item.emoji} {item.label}\n </Combobox.Item>\n )}\n </Combobox.List>\n </Combobox.Content>\n </Combobox>\n </div>",
2410
+ "<div className=\"w-80\">\n <Combobox value={value} onValueChange={setValue} items={items}>\n <Combobox.TriggerInput placeholder=\"Select database\" />\n <Combobox.Content>\n <Combobox.Empty />\n <Combobox.List>\n {(item: DatabaseItemWithDisabled) => (\n <Combobox.Item\n key={item.value}\n value={item}\n disabled={item.disabled}\n >\n <span>\n {item.label}\n {item.reason && (\n <Text variant=\"secondary\" size=\"xs\" as=\"span\">\n {\" — \"}\n {item.reason}\n </Text>\n )}\n </span>\n </Combobox.Item>\n )}\n </Combobox.List>\n </Combobox.Content>\n </Combobox>\n </div>",
2181
2411
  "<div className=\"w-80\">\n <Combobox\n items={databases}\n value={value}\n onValueChange={setValue}\n label=\"Database\"\n error={{ message: \"Please select a database\", match: true }}\n >\n <Combobox.TriggerInput placeholder=\"Select database\" />\n <Combobox.Content>\n <Combobox.Empty />\n <Combobox.List>\n {(item: DatabaseItem) => (\n <Combobox.Item key={item.value} value={item}>\n {item.label}\n </Combobox.Item>\n )}\n </Combobox.List>\n </Combobox.Content>\n </Combobox>\n </div>",
2182
2412
  "<div className=\"flex flex-wrap items-center gap-4\">\n <Combobox\n size=\"sm\"\n value={smValue}\n onValueChange={(v) => setSmValue(v as string | null)}\n items={fruits.slice(0, 8)}\n >\n <Combobox.TriggerInput placeholder=\"Small (sm)\" />\n <Combobox.Content>\n <Combobox.Empty />\n <Combobox.List>\n {(item: string) => (\n <Combobox.Item key={item} value={item}>\n {item}\n </Combobox.Item>\n )}\n </Combobox.List>\n </Combobox.Content>\n </Combobox>\n <Combobox\n size=\"base\"\n value={baseValue}\n onValueChange={(v) => setBaseValue(v as string | null)}\n items={fruits.slice(0, 8)}\n >\n <Combobox.TriggerInput placeholder=\"Base (default)\" />\n <Combobox.Content>\n <Combobox.Empty />\n <Combobox.List>\n {(item: string) => (\n <Combobox.Item key={item} value={item}>\n {item}\n </Combobox.Item>\n )}\n </Combobox.List>\n </Combobox.Content>\n </Combobox>\n </div>",
2183
2413
  "<div className=\"flex flex-wrap items-center gap-4\">\n <Combobox\n size=\"sm\"\n value={smValue}\n onValueChange={(v) => setSmValue(v as Language)}\n items={languages}\n >\n <Combobox.TriggerValue className=\"w-[160px]\" />\n <Combobox.Content>\n <Combobox.Input placeholder=\"Search\" />\n <Combobox.Empty />\n <Combobox.List>\n {(item: Language) => (\n <Combobox.Item key={item.value} value={item}>\n {item.emoji} {item.label}\n </Combobox.Item>\n )}\n </Combobox.List>\n </Combobox.Content>\n </Combobox>\n <Combobox\n size=\"base\"\n value={baseValue}\n onValueChange={(v) => setBaseValue(v as Language)}\n items={languages}\n >\n <Combobox.TriggerValue className=\"w-[180px]\" />\n <Combobox.Content>\n <Combobox.Input placeholder=\"Search\" />\n <Combobox.Empty />\n <Combobox.List>\n {(item: Language) => (\n <Combobox.Item key={item.value} value={item}>\n {item.emoji} {item.label}\n </Combobox.Item>\n )}\n </Combobox.List>\n </Combobox.Content>\n </Combobox>\n </div>"
@@ -2187,7 +2417,8 @@
2187
2417
  "bg-kumo-fill-hover",
2188
2418
  "bg-kumo-overlay",
2189
2419
  "bg-kumo-tint",
2190
- "border-kumo-line",
2420
+ "border-kumo-hairline",
2421
+ "ring-kumo-hairline",
2191
2422
  "ring-kumo-line",
2192
2423
  "text-kumo-default",
2193
2424
  "text-kumo-strong",
@@ -2316,17 +2547,19 @@
2316
2547
  }
2317
2548
  },
2318
2549
  "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>",
2550
+ "<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
2551
  "<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
2552
  "<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>"
2553
+ "<div className=\"flex flex-col items-start gap-4\">\n <Button onClick={() => setOpen(true)}>\n Open Palette (No Autocomplete)\n </Button>\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) => {\n console.log(\"Selected:\", item.title);\n setOpen(false);\n setSearch(\"\");\n }}\n getSelectableItems={getSelectableItems}\n >\n <CommandPalette.Input\n placeholder=\"Search commands...\"\n autoComplete=\"off\"\n autoCorrect=\"off\"\n autoCapitalize=\"none\"\n spellCheck={false}\n data-1p-ignore=\"true\"\n data-lpignore=\"true\"\n />\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={() => {\n setOpen(false);\n setSearch(\"\");\n }}\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.Root>\n </div>",
2554
+ "<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
2555
  ],
2324
2556
  "colors": [
2325
2557
  "bg-kumo-base",
2326
2558
  "bg-kumo-elevated",
2327
2559
  "bg-kumo-overlay",
2328
2560
  "bg-kumo-warning",
2329
- "ring-kumo-line",
2561
+ "ring-kumo-brand",
2562
+ "ring-kumo-hairline",
2330
2563
  "text-kumo-default",
2331
2564
  "text-kumo-strong",
2332
2565
  "text-kumo-subtle"
@@ -2349,13 +2582,13 @@
2349
2582
  }
2350
2583
  },
2351
2584
  "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>",
2585
+ "<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
2586
  "<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
2587
  "<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
2588
  "<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>",
2589
+ "<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>",
2590
+ "<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>",
2591
+ "<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
2592
  "<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
2593
  ],
2361
2594
  "colors": [
@@ -2434,6 +2667,7 @@
2434
2667
  "bg-kumo-fill",
2435
2668
  "bg-kumo-interact",
2436
2669
  "bg-kumo-overlay",
2670
+ "ring-kumo-focus",
2437
2671
  "text-kumo-default",
2438
2672
  "text-kumo-inverse",
2439
2673
  "text-kumo-strong",
@@ -2542,6 +2776,7 @@
2542
2776
  "colors": [
2543
2777
  "bg-kumo-base",
2544
2778
  "bg-kumo-recessed",
2779
+ "ring-kumo-line",
2545
2780
  "text-kumo-default"
2546
2781
  ],
2547
2782
  "subComponents": {
@@ -2672,9 +2907,11 @@
2672
2907
  "colors": [
2673
2908
  "bg-kumo-control",
2674
2909
  "bg-kumo-danger",
2675
- "bg-kumo-line",
2910
+ "bg-kumo-hairline",
2676
2911
  "bg-kumo-overlay",
2677
2912
  "bg-kumo-tint",
2913
+ "ring-kumo-brand",
2914
+ "ring-kumo-focus",
2678
2915
  "ring-kumo-line",
2679
2916
  "text-kumo-danger",
2680
2917
  "text-kumo-default"
@@ -3004,7 +3241,7 @@
3004
3241
  "<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
3242
  ],
3006
3243
  "colors": [
3007
- "border-kumo-line"
3244
+ "border-kumo-hairline"
3008
3245
  ]
3009
3246
  },
3010
3247
  "Input": {
@@ -3071,15 +3308,15 @@
3071
3308
  "error": "Error state for validation failures"
3072
3309
  },
3073
3310
  "classes": {
3074
- "default": "focus:ring-kumo-hairline",
3075
- "error": "!ring-kumo-danger focus:ring-kumo-danger"
3311
+ "default": "focus:ring-kumo-focus/50 focus:ring-[1.5px]",
3312
+ "error": "!ring-kumo-danger focus:ring-kumo-danger/50 focus:ring-[1.5px]"
3076
3313
  },
3077
3314
  "stateClasses": {
3078
3315
  "default": {
3079
- "focus": "focus:ring-kumo-hairline"
3316
+ "focus": "focus:ring-kumo-focus/50 focus:ring-[1.5px]"
3080
3317
  },
3081
3318
  "error": {
3082
- "focus": "focus:ring-kumo-danger"
3319
+ "focus": "focus:ring-kumo-danger/50 focus:ring-[1.5px]"
3083
3320
  }
3084
3321
  },
3085
3322
  "default": "default"
@@ -3096,12 +3333,14 @@
3096
3333
  "<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
3334
  "<Input\n label=\"Phone Number\"\n required={false}\n placeholder=\"+1 (555) 000-0000\"\n />",
3098
3335
  "<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 />"
3336
+ "<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 />",
3337
+ "<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 />",
3338
+ "<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
3339
  ],
3101
3340
  "colors": [
3102
3341
  "bg-kumo-control",
3103
3342
  "ring-kumo-danger",
3104
- "ring-kumo-hairline",
3343
+ "ring-kumo-focus",
3105
3344
  "ring-kumo-line",
3106
3345
  "text-kumo-default",
3107
3346
  "text-kumo-subtle"
@@ -3157,31 +3396,197 @@
3157
3396
  }
3158
3397
  }
3159
3398
  },
3160
- "Label": {
3161
- "name": "Label",
3399
+ "InputGroup": {
3400
+ "name": "InputGroup",
3162
3401
  "type": "component",
3163
- "description": "Label component for form fields. Provides a standardized way to display labels with optional indicators: - Optional indicator: gray \"(optional)\" text when `showOptional={true}` - Tooltip: info icon with hover tooltip for additional context",
3402
+ "description": "InputGroup component",
3164
3403
  "importPath": "@cloudflare/kumo",
3165
- "category": "Other",
3404
+ "category": "Input",
3166
3405
  "props": {
3167
- "children": {
3406
+ "label": {
3168
3407
  "type": "ReactNode",
3169
3408
  "optional": true,
3170
3409
  "description": "The label content — can be a string or any React node."
3171
3410
  },
3172
- "showOptional": {
3411
+ "description": {
3412
+ "type": "ReactNode",
3413
+ "optional": true,
3414
+ "description": "Helper text displayed below the control (hidden when `error` is present)."
3415
+ },
3416
+ "error": {
3417
+ "type": "object",
3418
+ "optional": true,
3419
+ "description": "Validation error with a message and a browser `ValidityState` match key."
3420
+ },
3421
+ "required": {
3173
3422
  "type": "boolean",
3174
3423
  "optional": true,
3175
- "description": "When `true`, shows gray \"(optional)\" text after the label."
3424
+ "description": "When explicitly `false`, shows gray \"(optional)\" text after the label. When `true` or `undefined`, no indicator is shown."
3176
3425
  },
3177
- "tooltip": {
3426
+ "labelTooltip": {
3178
3427
  "type": "ReactNode",
3179
3428
  "optional": true,
3180
3429
  "description": "Tooltip content displayed next to the label via an info icon."
3181
3430
  },
3431
+ "children": {
3432
+ "type": "ReactNode",
3433
+ "optional": true
3434
+ },
3182
3435
  "className": {
3183
3436
  "type": "string",
3184
- "optional": true,
3437
+ "optional": true
3438
+ },
3439
+ "id": {
3440
+ "type": "string",
3441
+ "optional": true
3442
+ },
3443
+ "lang": {
3444
+ "type": "string",
3445
+ "optional": true
3446
+ },
3447
+ "title": {
3448
+ "type": "string",
3449
+ "optional": true
3450
+ },
3451
+ "size": {
3452
+ "type": "enum",
3453
+ "optional": true,
3454
+ "values": [
3455
+ "xs",
3456
+ "sm",
3457
+ "base",
3458
+ "lg"
3459
+ ],
3460
+ "descriptions": {
3461
+ "xs": "Extra small size.",
3462
+ "sm": "Small size.",
3463
+ "base": "Default size.",
3464
+ "lg": "Large size."
3465
+ },
3466
+ "classes": {
3467
+ "xs": "h-6 text-xs",
3468
+ "sm": "h-7 text-xs",
3469
+ "base": "h-9 text-base",
3470
+ "lg": "h-11 text-base"
3471
+ },
3472
+ "default": "base"
3473
+ },
3474
+ "disabled": {
3475
+ "type": "boolean",
3476
+ "optional": true
3477
+ }
3478
+ },
3479
+ "examples": [
3480
+ "<div className=\"w-full max-w-2xs\">\n <InputGroup>\n <InputGroup.Input\n maxLength={20}\n onChange={handleChange}\n value={value}\n />\n <InputGroup.Suffix>.workers.dev</InputGroup.Suffix>\n {status !== \"idle\" && (\n <InputGroup.Addon align=\"end\">\n {status === \"loading\" ? (\n <Loader />\n ) : (\n <CheckCircleIcon weight=\"duotone\" className=\"text-kumo-success\" />\n )}\n </InputGroup.Addon>\n )}\n </InputGroup>\n </div>",
3481
+ "<InputGroup className=\"w-full max-w-3xs\">\n <InputGroup.Addon>\n <LinkIcon />\n </InputGroup.Addon>\n <InputGroup.Input placeholder=\"Paste a link...\" aria-label=\"Link\" />\n </InputGroup>",
3482
+ "<div className=\"flex flex-col gap-4\">\n <InputGroup className=\"w-full max-w-3xs\">\n <InputGroup.Addon>@</InputGroup.Addon>\n <InputGroup.Input placeholder=\"username\" aria-label=\"Username\" />\n </InputGroup>\n\n <InputGroup className=\"w-full max-w-3xs\">\n <InputGroup.Input placeholder=\"email\" aria-label=\"Email\" />\n <InputGroup.Addon align=\"end\">@example.com</InputGroup.Addon>\n </InputGroup>\n\n <InputGroup className=\"w-full max-w-3xs\">\n <InputGroup.Addon>/api/</InputGroup.Addon>\n <InputGroup.Input placeholder=\"endpoint\" aria-label=\"API path\" />\n <InputGroup.Addon align=\"end\">.json</InputGroup.Addon>\n </InputGroup>\n </div>",
3483
+ "<div className=\"flex flex-col gap-4\">\n <InputGroup className=\"w-full max-w-3xs\">\n <InputGroup.Input\n type={show ? \"text\" : \"password\"}\n defaultValue=\"password\"\n aria-label=\"Password\"\n />\n <InputGroup.Addon align=\"end\">\n <InputGroup.Button\n className=\"text-kumo-subtle\"\n icon={show ? EyeSlashIcon : EyeIcon}\n aria-label={show ? \"Hide password\" : \"Show password\"}\n onClick={() => setShow(!show)}\n />\n </InputGroup.Addon>\n </InputGroup>\n\n <InputGroup className=\"w-full max-w-3xs\">\n <InputGroup.Addon>\n <MagnifyingGlassIcon />\n </InputGroup.Addon>\n <InputGroup.Input\n value={searchValue}\n placeholder=\"Search\"\n aria-label=\"Search\"\n onChange={(e) => setSearchValue(e.target.value)}\n />\n {searchValue && (\n <InputGroup.Addon align=\"end\" className=\"pr-1\">\n <InputGroup.Button\n aria-label=\"Clear search\"\n onClick={() => setSearchValue(\"\")}\n >\n <XIcon />\n </InputGroup.Button>\n </InputGroup.Addon>\n )}\n <InputGroup.Button variant=\"secondary\" onClick={() => {}}>\n Search\n </InputGroup.Button>\n </InputGroup>\n </div>",
3484
+ "<InputGroup className=\"w-full max-w-2xs\">\n <InputGroup.Addon>\n <MagnifyingGlassIcon />\n </InputGroup.Addon>\n <InputGroup.Input\n placeholder=\"Search with query language...\"\n aria-label=\"Search\"\n />\n <InputGroup.Addon align=\"end\">\n <InputGroup.Button\n className=\"text-kumo-subtle\"\n icon={QuestionIcon}\n tooltip=\"Query language help\"\n onClick={() => {}}\n />\n </InputGroup.Addon>\n </InputGroup>",
3485
+ "<InputGroup className=\"w-full max-w-3xs\">\n <InputGroup.Addon>\n <MagnifyingGlassIcon />\n </InputGroup.Addon>\n <InputGroup.Input placeholder=\"Search...\" aria-label=\"Search\" />\n <InputGroup.Addon align=\"end\">\n <kbd className=\"bg-none! border-none!\">⌘K</kbd>\n </InputGroup.Addon>\n </InputGroup>",
3486
+ "<InputGroup className=\"w-full max-w-3xs\">\n <InputGroup.Input defaultValue=\"kumo\" aria-label=\"kumo\" />\n <InputGroup.Addon align=\"end\">\n <Loader />\n </InputGroup.Addon>\n </InputGroup>",
3487
+ "<div className=\"flex w-full max-w-2xs flex-col gap-4\">\n <InputGroup label=\"Subdomain\">\n <InputGroup.Input\n aria-label=\"Subdomain\"\n defaultValue=\"kumo\"\n maxLength={20}\n />\n <InputGroup.Suffix>.workers.dev</InputGroup.Suffix>\n <InputGroup.Addon align=\"end\">\n <CheckCircleIcon weight=\"duotone\" className=\"text-kumo-success\" />\n </InputGroup.Addon>\n </InputGroup>\n\n <InputGroup\n label=\"Subdomain\"\n error={{ message: \"This subdomain is unavailable\", match: true }}\n >\n <InputGroup.Input\n aria-label=\"Subdomain\"\n defaultValue=\"kumo\"\n maxLength={20}\n />\n <InputGroup.Suffix>.workers.dev</InputGroup.Suffix>\n <InputGroup.Addon align=\"end\">\n <XCircleIcon weight=\"duotone\" className=\"text-kumo-danger\" />\n </InputGroup.Addon>\n </InputGroup>\n </div>",
3488
+ "<div className=\"flex w-full max-w-3xs flex-col gap-4\">\n <InputGroup size=\"xs\" label=\"Extra Small\">\n <InputGroup.Addon>\n <MagnifyingGlassIcon />\n </InputGroup.Addon>\n <InputGroup.Input placeholder=\"Extra small input\" />\n <InputGroup.Addon align=\"end\">\n <InputGroup.Button\n className=\"text-kumo-subtle\"\n icon={QuestionIcon}\n shape=\"square\"\n aria-label=\"Help\"\n />\n </InputGroup.Addon>\n </InputGroup>\n\n <InputGroup size=\"sm\" label=\"Small\">\n <InputGroup.Addon>\n <MagnifyingGlassIcon />\n </InputGroup.Addon>\n <InputGroup.Input placeholder=\"Small input\" />\n <InputGroup.Addon align=\"end\">\n <InputGroup.Button\n className=\"text-kumo-subtle\"\n icon={QuestionIcon}\n shape=\"square\"\n aria-label=\"Help\"\n />\n </InputGroup.Addon>\n </InputGroup>\n\n <InputGroup label=\"Base (default)\">\n <InputGroup.Addon>\n <MagnifyingGlassIcon />\n </InputGroup.Addon>\n <InputGroup.Input placeholder=\"Base input\" />\n <InputGroup.Addon align=\"end\">\n <InputGroup.Button\n className=\"text-kumo-subtle\"\n icon={QuestionIcon}\n shape=\"square\"\n aria-label=\"Help\"\n />\n </InputGroup.Addon>\n </InputGroup>\n\n <InputGroup size=\"lg\" label=\"Large\">\n <InputGroup.Addon>\n <MagnifyingGlassIcon />\n </InputGroup.Addon>\n <InputGroup.Input placeholder=\"Large input\" />\n <InputGroup.Addon align=\"end\">\n <InputGroup.Button\n className=\"text-kumo-subtle\"\n icon={QuestionIcon}\n shape=\"square\"\n aria-label=\"Help\"\n />\n </InputGroup.Addon>\n </InputGroup>\n </div>",
3489
+ "<div className=\"flex w-full max-w-3xs flex-col gap-4\">\n <InputGroup\n label=\"Error State\"\n error={{ message: \"Please enter a valid email address\", match: true }}\n >\n <InputGroup.Input type=\"email\" defaultValue=\"invalid-email\" />\n <InputGroup.Addon align=\"end\">@example.com</InputGroup.Addon>\n </InputGroup>\n\n <InputGroup label=\"Disabled\" disabled>\n <InputGroup.Addon>\n <MagnifyingGlassIcon />\n </InputGroup.Addon>\n <InputGroup.Input placeholder=\"Search...\" />\n </InputGroup>\n\n <InputGroup label=\"Optional Field\" required={false}>\n <InputGroup.Addon>$</InputGroup.Addon>\n <InputGroup.Input placeholder=\"0.00\" />\n </InputGroup>\n\n <InputGroup\n label=\"With Description\"\n description=\"Must be at least 8 characters\"\n labelTooltip=\"Your password is stored securely\"\n >\n <InputGroup.Input\n type={show ? \"text\" : \"password\"}\n placeholder=\"Password\"\n />\n <InputGroup.Addon align=\"end\">\n <InputGroup.Button\n className=\"text-kumo-subtle\"\n icon={show ? EyeSlashIcon : EyeIcon}\n aria-label={show ? \"Hide password\" : \"Show password\"}\n onClick={() => setShow(!show)}\n />\n </InputGroup.Addon>\n </InputGroup>\n </div>"
3490
+ ],
3491
+ "colors": [
3492
+ "border-kumo-line",
3493
+ "ring-kumo-danger",
3494
+ "ring-kumo-focus",
3495
+ "ring-kumo-line"
3496
+ ],
3497
+ "subComponents": {
3498
+ "Input": {
3499
+ "name": "Input",
3500
+ "description": "Input sub-component",
3501
+ "props": {}
3502
+ },
3503
+ "Button": {
3504
+ "name": "Button",
3505
+ "description": "Button sub-component",
3506
+ "props": {
3507
+ "tooltip": {
3508
+ "type": "ReactNode",
3509
+ "description": "When provided, wraps the button in a Tooltip. Automatically sets aria-label from a string value."
3510
+ },
3511
+ "tooltipSide": {
3512
+ "type": "\"top\" | \"right\" | \"bottom\" | \"left\"",
3513
+ "description": "Preferred side for the tooltip popup.",
3514
+ "default": "\"bottom\""
3515
+ },
3516
+ "variant": {
3517
+ "type": "\"primary\" | \"secondary\" | \"ghost\" | \"destructive\" | \"secondary-destructive\" | \"outline\"",
3518
+ "description": "Button visual style. Defaults to ghost.",
3519
+ "default": "\"ghost\""
3520
+ },
3521
+ "size": {
3522
+ "type": "\"xs\" | \"sm\" | \"base\" | \"lg\"",
3523
+ "description": "Button size.",
3524
+ "default": "\"sm\""
3525
+ }
3526
+ }
3527
+ },
3528
+ "Addon": {
3529
+ "name": "Addon",
3530
+ "description": "Addon sub-component",
3531
+ "props": {
3532
+ "align": {
3533
+ "type": "\"start\" | \"end\"",
3534
+ "description": "Position relative to the input.",
3535
+ "default": "\"start\""
3536
+ },
3537
+ "className": {
3538
+ "type": "string",
3539
+ "description": "Additional CSS classes."
3540
+ }
3541
+ }
3542
+ },
3543
+ "Suffix": {
3544
+ "name": "Suffix",
3545
+ "description": "Suffix sub-component",
3546
+ "props": {
3547
+ "className": {
3548
+ "type": "string",
3549
+ "description": "Additional CSS classes."
3550
+ }
3551
+ }
3552
+ },
3553
+ "Label": {
3554
+ "name": "Label",
3555
+ "description": "Label sub-component",
3556
+ "props": {}
3557
+ },
3558
+ "Description": {
3559
+ "name": "Description",
3560
+ "description": "Description sub-component",
3561
+ "props": {}
3562
+ }
3563
+ }
3564
+ },
3565
+ "Label": {
3566
+ "name": "Label",
3567
+ "type": "component",
3568
+ "description": "Label component for form fields. Provides a standardized way to display labels with optional indicators: - Optional indicator: gray \"(optional)\" text when `showOptional={true}` - Tooltip: info icon with hover tooltip for additional context",
3569
+ "importPath": "@cloudflare/kumo",
3570
+ "category": "Other",
3571
+ "props": {
3572
+ "children": {
3573
+ "type": "ReactNode",
3574
+ "optional": true,
3575
+ "description": "The label content — can be a string or any React node."
3576
+ },
3577
+ "showOptional": {
3578
+ "type": "boolean",
3579
+ "optional": true,
3580
+ "description": "When `true`, shows gray \"(optional)\" text after the label."
3581
+ },
3582
+ "tooltip": {
3583
+ "type": "ReactNode",
3584
+ "optional": true,
3585
+ "description": "Tooltip content displayed next to the label via an info icon."
3586
+ },
3587
+ "className": {
3588
+ "type": "string",
3589
+ "optional": true,
3185
3590
  "description": "Additional CSS classes merged via `cn()`."
3186
3591
  },
3187
3592
  "htmlFor": {
@@ -3215,25 +3620,43 @@
3215
3620
  "importPath": "@cloudflare/kumo",
3216
3621
  "category": "Display",
3217
3622
  "props": {
3623
+ "render": {
3624
+ "type": "ReactNode",
3625
+ "optional": true,
3626
+ "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."
3627
+ },
3218
3628
  "children": {
3219
3629
  "type": "ReactNode",
3220
3630
  "optional": true
3221
3631
  },
3222
3632
  "className": {
3223
3633
  "type": "string",
3224
- "optional": true,
3225
- "description": "Additional CSS classes merged via `cn()`."
3634
+ "optional": true
3635
+ },
3636
+ "id": {
3637
+ "type": "string",
3638
+ "optional": true
3639
+ },
3640
+ "lang": {
3641
+ "type": "string",
3642
+ "optional": true
3643
+ },
3644
+ "title": {
3645
+ "type": "string",
3646
+ "optional": true
3226
3647
  }
3227
3648
  },
3228
3649
  "examples": [
3229
3650
  "<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
3651
  "<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>",
3652
+ "<LayerCard className=\"w-[250px] p-4\">\n <p className=\"text-sm text-kumo-subtle\">Quick start guide for new users</p>\n </LayerCard>",
3231
3653
  "<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
3654
  ],
3233
3655
  "colors": [
3234
3656
  "bg-kumo-base",
3235
3657
  "bg-kumo-elevated",
3236
3658
  "ring-kumo-fill",
3659
+ "ring-kumo-hairline",
3237
3660
  "ring-kumo-line",
3238
3661
  "text-kumo-strong"
3239
3662
  ],
@@ -3368,7 +3791,7 @@
3368
3791
  "render": {
3369
3792
  "type": "ReactNode",
3370
3793
  "optional": true,
3371
- "description": "Allows you to replace the components 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."
3794
+ "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."
3372
3795
  }
3373
3796
  },
3374
3797
  "examples": [
@@ -3462,8 +3885,10 @@
3462
3885
  "colors": [
3463
3886
  "bg-kumo-base",
3464
3887
  "bg-kumo-recessed",
3465
- "border-kumo-fill",
3466
- "border-kumo-recessed"
3888
+ "border-kumo-recessed",
3889
+ "ring-kumo-brand",
3890
+ "ring-kumo-focus",
3891
+ "ring-kumo-line"
3467
3892
  ],
3468
3893
  "styling": {
3469
3894
  "container": {
@@ -3570,6 +3995,11 @@
3570
3995
  "optional": true,
3571
3996
  "description": "Additional CSS classes for the container"
3572
3997
  },
3998
+ "labels": {
3999
+ "type": "PaginationLabels",
4000
+ "optional": true,
4001
+ "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"
4002
+ },
3573
4003
  "children": {
3574
4004
  "type": "ReactNode",
3575
4005
  "optional": true,
@@ -3604,11 +4034,12 @@
3604
4034
  "<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
4035
  "<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
4036
  "<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>"
4037
+ "<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>",
4038
+ "<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
4039
  ],
3609
4040
  "colors": [
3610
- "border-kumo-line",
3611
- "ring-kumo-line",
4041
+ "border-kumo-hairline",
4042
+ "ring-kumo-hairline",
3612
4043
  "text-kumo-strong"
3613
4044
  ],
3614
4045
  "subComponents": {
@@ -3650,6 +4081,10 @@
3650
4081
  "type": "number[]",
3651
4082
  "optional": true
3652
4083
  },
4084
+ "page": {
4085
+ "type": "\"",
4086
+ "required": true
4087
+ },
3653
4088
  "label": {
3654
4089
  "type": "ReactNode",
3655
4090
  "optional": true
@@ -3727,12 +4162,13 @@
3727
4162
  }
3728
4163
  },
3729
4164
  "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>"
4165
+ "<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>",
4166
+ "<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>",
4167
+ "<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>",
4168
+ "<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>",
4169
+ "<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>",
4170
+ "<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>",
4171
+ "<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
4172
  ],
3737
4173
  "colors": [
3738
4174
  "bg-kumo-base",
@@ -3774,19 +4210,19 @@
3774
4210
  "Radio": {
3775
4211
  "name": "Radio",
3776
4212
  "type": "component",
3777
- "description": "Radio — radio button group for single-select choices. Compound component: `Radio.Group` (with built-in Fieldset) and `Radio.Item`. Built on `@base-ui/react/radio-group` + `@base-ui/react/radio`.",
4213
+ "description": "Radio — radio button group for single-select choices. Compound component: `Radio.Group` (with built-in Fieldset), `Radio.Item`, and `Radio.Legend`. Built on `@base-ui/react/radio-group` + `@base-ui/react/radio`.",
3778
4214
  "importPath": "@cloudflare/kumo",
3779
4215
  "category": "Input",
3780
4216
  "props": {
3781
4217
  "legend": {
3782
4218
  "type": "string",
3783
- "required": true,
3784
- "description": "Legend text for the group (required for accessibility)"
4219
+ "optional": true,
4220
+ "description": "Legend text for the group (required for accessibility). For more control over legend styling, omit this prop and use `<Radio.Legend>` as a child instead."
3785
4221
  },
3786
4222
  "children": {
3787
4223
  "type": "ReactNode",
3788
4224
  "optional": true,
3789
- "description": "Child Radio.Item components"
4225
+ "description": "Child Radio.Item components (and optionally a Radio.Legend)"
3790
4226
  },
3791
4227
  "orientation": {
3792
4228
  "type": "enum",
@@ -3842,7 +4278,7 @@
3842
4278
  "controlPosition": {
3843
4279
  "type": "enum",
3844
4280
  "optional": true,
3845
- "description": "Position of radio control relative to label: \"start\" (default) puts radio before label, \"end\" puts label before radio. Note: In card appearance, the control is always positioned at the end.",
4281
+ "description": "Position of radio control relative to label: \"start\" puts radio before label, \"end\" puts label before radio. Defaults to \"start\" for default appearance and \"end\" for card appearance.",
3846
4282
  "values": [
3847
4283
  "start",
3848
4284
  "end"
@@ -3868,6 +4304,10 @@
3868
4304
  "<div className=\"grid grid-cols-2 gap-6\">\n <Radio.Group legend=\"Disabled group\" disabled defaultValue=\"a\">\n <Radio.Item label=\"Option A\" value=\"a\" />\n <Radio.Item label=\"Option B\" value=\"b\" />\n </Radio.Group>\n <Radio.Group legend=\"Individual disabled\" defaultValue=\"available\">\n <Radio.Item label=\"Available\" value=\"available\" />\n <Radio.Item label=\"Unavailable\" value=\"unavailable\" disabled />\n </Radio.Group>\n <Radio.Group\n legend=\"Disabled card group\"\n appearance=\"card\"\n disabled\n defaultValue=\"a\"\n >\n <Radio.Item\n label=\"Option A\"\n description=\"This option is disabled.\"\n value=\"a\"\n />\n <Radio.Item\n label=\"Option B\"\n description=\"This option is disabled.\"\n value=\"b\"\n />\n </Radio.Group>\n <Radio.Group\n legend=\"Individual disabled card\"\n appearance=\"card\"\n defaultValue=\"available\"\n >\n <Radio.Item\n label=\"Available\"\n description=\"This option can be selected.\"\n value=\"available\"\n />\n <Radio.Item\n label=\"Unavailable\"\n description=\"This option is not available.\"\n value=\"unavailable\"\n disabled\n />\n </Radio.Group>\n </div>",
3869
4305
  "<Radio.Group legend=\"Preferences\" controlPosition=\"end\" defaultValue=\"a\">\n <Radio.Item label=\"Label before radio\" value=\"a\" />\n <Radio.Item label=\"Another option\" value=\"b\" />\n </Radio.Group>",
3870
4306
  "<Radio.Group\n legend=\"Choose a plan\"\n appearance=\"card\"\n value={value}\n onValueChange={setValue}\n >\n <Radio.Item\n label=\"Free\"\n description=\"For personal or hobby projects that aren't business-critical.\"\n value=\"free\"\n />\n <Radio.Item\n label=\"Pro\"\n description=\"For professional websites that aren't business-critical.\"\n value=\"pro\"\n />\n <Radio.Item\n label=\"Business\"\n description=\"For small businesses operating online.\"\n value=\"business\"\n />\n <Radio.Item\n label=\"Contract\"\n description=\"For mission-critical applications that are core to your business.\"\n value=\"contract\"\n />\n </Radio.Group>",
4307
+ "<Radio.Group defaultValue=\"all\" value={value} onValueChange={setValue}>\n <Radio.Legend className=\"sr-only\">Paths</Radio.Legend>\n <Radio.Item label=\"Allow all paths\" value=\"all\" />\n <Radio.Item label=\"Restrict to specific paths\" value=\"specific\" />\n </Radio.Group>",
4308
+ "<Radio.Group value={value} onValueChange={setValue}>\n <Radio.Legend className=\"text-sm font-normal text-kumo-subtle\">\n Notification preference\n </Radio.Legend>\n <Radio.Item label=\"Email\" value=\"email\" />\n <Radio.Item label=\"SMS\" value=\"sms\" />\n <Radio.Item label=\"Push notification\" value=\"push\" />\n </Radio.Group>",
4309
+ "<Radio.Group\n legend=\"Choose a plan\"\n appearance=\"card\"\n controlPosition=\"start\"\n value={value}\n onValueChange={setValue}\n >\n <Radio.Item\n label=\"Free\"\n description=\"For personal or hobby projects that aren't business-critical.\"\n value=\"free\"\n />\n <Radio.Item\n label=\"Pro\"\n description=\"For professional websites that aren't business-critical.\"\n value=\"pro\"\n />\n </Radio.Group>",
4310
+ "<Radio.Group\n legend=\"Choose a plan\"\n appearance=\"card\"\n value={value}\n onValueChange={setValue}\n >\n <Radio.Item\n label={\n <span className=\"flex items-center gap-2\">\n Free\n <Badge variant=\"neutral\">$0</Badge>\n </span>\n }\n description=\"For personal or hobby projects.\"\n value=\"free\"\n />\n <Radio.Item\n label={\n <span className=\"flex items-center gap-2\">\n Pro\n <Badge variant=\"primary\">Popular</Badge>\n </span>\n }\n description=\"For professional websites.\"\n value=\"pro\"\n />\n </Radio.Group>",
3871
4311
  "<Radio.Group\n legend=\"Choose a plan\"\n appearance=\"card\"\n orientation=\"horizontal\"\n value={value}\n onValueChange={setValue}\n >\n <Radio.Item\n label=\"Free\"\n description=\"For personal or hobby projects that aren't business-critical.\"\n value=\"free\"\n />\n <Radio.Item\n label=\"Pro\"\n description=\"For professional websites that aren't business-critical.\"\n value=\"pro\"\n />\n <Radio.Item\n label=\"Business\"\n description=\"For small businesses operating online.\"\n value=\"business\"\n />\n <Radio.Item\n label=\"Contract\"\n description=\"For mission-critical applications that are core to your business.\"\n value=\"contract\"\n />\n </Radio.Group>"
3872
4312
  ],
3873
4313
  "colors": [
@@ -3877,7 +4317,9 @@
3877
4317
  "border-kumo-danger",
3878
4318
  "border-kumo-hairline",
3879
4319
  "border-kumo-interact",
4320
+ "ring-kumo-brand",
3880
4321
  "ring-kumo-danger",
4322
+ "ring-kumo-focus",
3881
4323
  "ring-kumo-hairline",
3882
4324
  "ring-kumo-line",
3883
4325
  "text-kumo-danger",
@@ -3896,7 +4338,7 @@
3896
4338
  "props": {
3897
4339
  "legend": {
3898
4340
  "type": "string",
3899
- "required": true
4341
+ "optional": true
3900
4342
  },
3901
4343
  "children": {
3902
4344
  "type": "ReactNode",
@@ -3927,11 +4369,7 @@
3927
4369
  "optional": true
3928
4370
  },
3929
4371
  "label": {
3930
- "type": "\"start\" (default) puts radio before label",
3931
- "required": true
3932
- },
3933
- "Note": {
3934
- "type": "In card appearance",
4372
+ "type": "\"start\" puts radio before label",
3935
4373
  "required": true
3936
4374
  },
3937
4375
  "controlPosition": {
@@ -3947,6 +4385,20 @@
3947
4385
  "optional": true
3948
4386
  }
3949
4387
  }
4388
+ },
4389
+ "Legend": {
4390
+ "name": "Legend",
4391
+ "description": "Legend sub-component",
4392
+ "props": {
4393
+ "children": {
4394
+ "type": "ReactNode",
4395
+ "required": true
4396
+ },
4397
+ "className": {
4398
+ "type": "string",
4399
+ "optional": true
4400
+ }
4401
+ }
3950
4402
  }
3951
4403
  }
3952
4404
  },
@@ -3962,6 +4414,18 @@
3962
4414
  "optional": true,
3963
4415
  "description": "Additional CSS classes merged via `cn()`."
3964
4416
  },
4417
+ "size": {
4418
+ "type": "enum",
4419
+ "optional": true,
4420
+ "description": "Size of the select trigger. Matches Input component sizes.",
4421
+ "values": [
4422
+ "xs",
4423
+ "sm",
4424
+ "base",
4425
+ "lg"
4426
+ ],
4427
+ "default": "base"
4428
+ },
3965
4429
  "label": {
3966
4430
  "type": "ReactNode",
3967
4431
  "optional": true,
@@ -4027,6 +4491,7 @@
4027
4491
  },
4028
4492
  "examples": [
4029
4493
  "<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 />",
4494
+ "<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
4495
  "<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
4496
  "<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
4497
  "<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 +4502,25 @@
4037
4502
  "<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
4503
  "<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
4504
  "<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>",
4505
+ "<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>",
4506
+ "<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
4507
  "<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>"
4508
+ "<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>",
4509
+ "<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>",
4510
+ "<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
4511
  ],
4047
4512
  "colors": [
4048
4513
  "bg-kumo-base",
4049
- "bg-kumo-line",
4514
+ "bg-kumo-elevated",
4515
+ "bg-kumo-hairline",
4050
4516
  "bg-kumo-tint",
4051
- "ring-kumo-hairline",
4517
+ "border-kumo-line",
4518
+ "ring-kumo-brand",
4519
+ "ring-kumo-focus",
4520
+ "ring-kumo-line",
4052
4521
  "text-kumo-danger",
4053
4522
  "text-kumo-default",
4523
+ "text-kumo-placeholder",
4054
4524
  "text-kumo-subtle"
4055
4525
  ],
4056
4526
  "subComponents": {
@@ -4080,7 +4550,7 @@
4080
4550
  "height": 36,
4081
4551
  "paddingX": 12,
4082
4552
  "borderRadius": 8,
4083
- "background": "color-secondary",
4553
+ "background": "bg-kumo-elevated",
4084
4554
  "text": "text-color-surface",
4085
4555
  "ring": "color-border",
4086
4556
  "fontSize": 16,
@@ -4105,8 +4575,8 @@
4105
4575
  }
4106
4576
  },
4107
4577
  "popup": {
4108
- "background": "color-secondary",
4109
- "ring": "color-border",
4578
+ "background": "bg-kumo-elevated",
4579
+ "ring": "border-kumo-line",
4110
4580
  "borderRadius": 8,
4111
4581
  "padding": 6
4112
4582
  },
@@ -4247,8 +4717,9 @@
4247
4717
  "colors": [
4248
4718
  "bg-kumo-brand",
4249
4719
  "bg-kumo-control",
4250
- "outline-kumo-hairline",
4251
- "ring-kumo-hairline",
4720
+ "outline-kumo-focus",
4721
+ "ring-kumo-brand",
4722
+ "ring-kumo-focus",
4252
4723
  "text-kumo-default",
4253
4724
  "text-kumo-subtle"
4254
4725
  ]
@@ -4357,13 +4828,13 @@
4357
4828
  "colors": [
4358
4829
  "bg-kumo-base",
4359
4830
  "bg-kumo-brand",
4360
- "bg-kumo-line",
4831
+ "bg-kumo-hairline",
4361
4832
  "bg-kumo-overlay",
4362
4833
  "bg-kumo-recessed",
4363
4834
  "bg-kumo-tint",
4364
- "border-kumo-line",
4835
+ "border-kumo-hairline",
4836
+ "ring-kumo-brand",
4365
4837
  "ring-kumo-hairline",
4366
- "ring-kumo-line",
4367
4838
  "text-kumo-default",
4368
4839
  "text-kumo-strong",
4369
4840
  "text-kumo-subtle"
@@ -4422,82 +4893,222 @@
4422
4893
  "Header": {
4423
4894
  "name": "Header",
4424
4895
  "description": "Header sub-component",
4425
- "props": {}
4896
+ "props": {
4897
+ "collapsible": {
4898
+ "type": "boolean",
4899
+ "optional": true
4900
+ },
4901
+ "defaultOpen": {
4902
+ "type": "boolean",
4903
+ "optional": true
4904
+ },
4905
+ "open": {
4906
+ "type": "boolean",
4907
+ "optional": true
4908
+ }
4909
+ }
4426
4910
  },
4427
4911
  "Content": {
4428
4912
  "name": "Content",
4429
4913
  "description": "Content sub-component",
4430
- "props": {}
4914
+ "props": {
4915
+ "collapsible": {
4916
+ "type": "boolean",
4917
+ "optional": true
4918
+ },
4919
+ "defaultOpen": {
4920
+ "type": "boolean",
4921
+ "optional": true
4922
+ },
4923
+ "open": {
4924
+ "type": "boolean",
4925
+ "optional": true
4926
+ }
4927
+ }
4431
4928
  },
4432
4929
  "Footer": {
4433
4930
  "name": "Footer",
4434
4931
  "description": "Footer sub-component",
4435
- "props": {}
4932
+ "props": {
4933
+ "collapsible": {
4934
+ "type": "boolean",
4935
+ "optional": true
4936
+ },
4937
+ "defaultOpen": {
4938
+ "type": "boolean",
4939
+ "optional": true
4940
+ },
4941
+ "open": {
4942
+ "type": "boolean",
4943
+ "optional": true
4944
+ }
4945
+ }
4436
4946
  },
4437
4947
  "Group": {
4438
4948
  "name": "Group",
4439
4949
  "description": "Group sub-component",
4440
- "props": {}
4950
+ "props": {
4951
+ "collapsible": {
4952
+ "type": "boolean",
4953
+ "optional": true
4954
+ },
4955
+ "defaultOpen": {
4956
+ "type": "boolean",
4957
+ "optional": true
4958
+ },
4959
+ "open": {
4960
+ "type": "boolean",
4961
+ "optional": true
4962
+ }
4963
+ }
4441
4964
  },
4442
4965
  "GroupLabel": {
4443
4966
  "name": "GroupLabel",
4444
4967
  "description": "GroupLabel sub-component",
4445
- "props": {}
4968
+ "props": {
4969
+ "icon": {
4970
+ "type": "React.ComponentType<{ className?: string",
4971
+ "optional": true
4972
+ }
4973
+ }
4446
4974
  },
4447
4975
  "GroupContent": {
4448
4976
  "name": "GroupContent",
4449
4977
  "description": "GroupContent sub-component",
4450
- "props": {}
4978
+ "props": {
4979
+ "icon": {
4980
+ "type": "React.ComponentType<{ className?: string",
4981
+ "optional": true
4982
+ }
4983
+ }
4451
4984
  },
4452
4985
  "Menu": {
4453
4986
  "name": "Menu",
4454
4987
  "description": "Menu sub-component",
4455
- "props": {}
4988
+ "props": {
4989
+ "icon": {
4990
+ "type": "React.ComponentType<{ className?: string",
4991
+ "optional": true
4992
+ }
4993
+ }
4456
4994
  },
4457
4995
  "MenuItem": {
4458
4996
  "name": "MenuItem",
4459
4997
  "description": "MenuItem sub-component",
4460
- "props": {}
4998
+ "props": {
4999
+ "icon": {
5000
+ "type": "React.ComponentType<{ className?: string",
5001
+ "optional": true
5002
+ }
5003
+ }
4461
5004
  },
4462
5005
  "MenuButton": {
4463
5006
  "name": "MenuButton",
4464
5007
  "description": "MenuButton sub-component",
4465
- "props": {}
5008
+ "props": {
5009
+ "icon": {
5010
+ "type": "React.ComponentType<{ className?: string",
5011
+ "optional": true
5012
+ }
5013
+ }
4466
5014
  },
4467
5015
  "MenuAction": {
4468
5016
  "name": "MenuAction",
4469
5017
  "description": "MenuAction sub-component",
4470
- "props": {}
5018
+ "props": {
5019
+ "active": {
5020
+ "type": "boolean",
5021
+ "optional": true
5022
+ },
5023
+ "href": {
5024
+ "type": "string",
5025
+ "optional": true
5026
+ }
5027
+ }
4471
5028
  },
4472
5029
  "MenuBadge": {
4473
5030
  "name": "MenuBadge",
4474
5031
  "description": "MenuBadge sub-component",
4475
- "props": {}
5032
+ "props": {
5033
+ "active": {
5034
+ "type": "boolean",
5035
+ "optional": true
5036
+ },
5037
+ "href": {
5038
+ "type": "string",
5039
+ "optional": true
5040
+ }
5041
+ }
4476
5042
  },
4477
5043
  "MenuSub": {
4478
5044
  "name": "MenuSub",
4479
5045
  "description": "MenuSub sub-component",
4480
- "props": {}
5046
+ "props": {
5047
+ "active": {
5048
+ "type": "boolean",
5049
+ "optional": true
5050
+ },
5051
+ "href": {
5052
+ "type": "string",
5053
+ "optional": true
5054
+ }
5055
+ }
4481
5056
  },
4482
5057
  "MenuSubItem": {
4483
5058
  "name": "MenuSubItem",
4484
5059
  "description": "MenuSubItem sub-component",
4485
- "props": {}
5060
+ "props": {
5061
+ "active": {
5062
+ "type": "boolean",
5063
+ "optional": true
5064
+ },
5065
+ "href": {
5066
+ "type": "string",
5067
+ "optional": true
5068
+ }
5069
+ }
4486
5070
  },
4487
5071
  "MenuSubButton": {
4488
5072
  "name": "MenuSubButton",
4489
5073
  "description": "MenuSubButton sub-component",
4490
- "props": {}
5074
+ "props": {
5075
+ "active": {
5076
+ "type": "boolean",
5077
+ "optional": true
5078
+ },
5079
+ "href": {
5080
+ "type": "string",
5081
+ "optional": true
5082
+ }
5083
+ }
4491
5084
  },
4492
5085
  "Separator": {
4493
5086
  "name": "Separator",
4494
5087
  "description": "Separator sub-component",
4495
- "props": {}
5088
+ "props": {
5089
+ "placeholder": {
5090
+ "type": "string",
5091
+ "optional": true
5092
+ },
5093
+ "shortcut": {
5094
+ "type": "string",
5095
+ "optional": true
5096
+ }
5097
+ }
4496
5098
  },
4497
5099
  "Input": {
4498
5100
  "name": "Input",
4499
5101
  "description": "Input sub-component",
4500
- "props": {}
5102
+ "props": {
5103
+ "placeholder": {
5104
+ "type": "string",
5105
+ "optional": true
5106
+ },
5107
+ "shortcut": {
5108
+ "type": "string",
5109
+ "optional": true
5110
+ }
5111
+ }
4501
5112
  },
4502
5113
  "Trigger": {
4503
5114
  "name": "Trigger",
@@ -4517,7 +5128,12 @@
4517
5128
  "MenuChevron": {
4518
5129
  "name": "MenuChevron",
4519
5130
  "description": "MenuChevron sub-component",
4520
- "props": {}
5131
+ "props": {
5132
+ "className": {
5133
+ "type": "string",
5134
+ "optional": true
5135
+ }
5136
+ }
4521
5137
  },
4522
5138
  "Collapsible": {
4523
5139
  "name": "Collapsible",
@@ -4548,7 +5164,7 @@
4548
5164
  "Surface": {
4549
5165
  "name": "Surface",
4550
5166
  "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> ```",
5167
+ "description": "Surface component",
4552
5168
  "importPath": "@cloudflare/kumo",
4553
5169
  "category": "Layout",
4554
5170
  "props": {
@@ -4559,7 +5175,7 @@
4559
5175
  "render": {
4560
5176
  "type": "ReactNode",
4561
5177
  "optional": true,
4562
- "description": "Allows you to replace the components 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."
5178
+ "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."
4563
5179
  },
4564
5180
  "children": {
4565
5181
  "type": "ReactNode",
@@ -4582,15 +5198,8 @@
4582
5198
  "optional": true
4583
5199
  }
4584
5200
  },
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
- ]
5201
+ "examples": [],
5202
+ "colors": []
4594
5203
  },
4595
5204
  "Switch": {
4596
5205
  "name": "Switch",
@@ -4713,12 +5322,16 @@
4713
5322
  "<div className=\"flex flex-col gap-4\">\n <Switch\n label=\"Neutral off\"\n variant=\"neutral\"\n checked={false}\n onCheckedChange={() => {}}\n />\n <Switch\n label=\"Neutral on\"\n variant=\"neutral\"\n checked={true}\n onCheckedChange={() => {}}\n />\n <Switch\n label=\"Neutral disabled\"\n variant=\"neutral\"\n checked={false}\n disabled\n />\n </div>",
4714
5323
  "<div className=\"grid grid-cols-2 gap-x-8 gap-y-4\">\n <Switch label=\"Default off\" checked={false} onCheckedChange={() => {}} />\n <Switch label=\"Default on\" checked={true} onCheckedChange={() => {}} />\n <Switch\n label=\"Neutral off\"\n variant=\"neutral\"\n checked={false}\n onCheckedChange={() => {}}\n />\n <Switch\n label=\"Neutral on\"\n variant=\"neutral\"\n checked={true}\n onCheckedChange={() => {}}\n />\n </div>",
4715
5324
  "<Switch\n id=\"my-custom-switch\"\n label=\"Custom ID\"\n checked={checked}\n onCheckedChange={setChecked}\n />",
5325
+ "<Switch.Group legend=\"Notification settings\">\n <Switch.Item label=\"Email notifications\" />\n <Switch.Item label=\"SMS notifications\" />\n <Switch.Item label=\"Push notifications\" />\n </Switch.Group>",
5326
+ "<Switch.Group>\n <Switch.Legend className=\"sr-only\">Notification settings</Switch.Legend>\n <Switch.Item label=\"Email notifications\" />\n <Switch.Item label=\"SMS notifications\" />\n <Switch.Item label=\"Push notifications\" />\n </Switch.Group>",
5327
+ "<Switch.Group>\n <Switch.Legend className=\"text-sm font-normal text-kumo-subtle\">\n Notification settings\n </Switch.Legend>\n <Switch.Item label=\"Email notifications\" />\n <Switch.Item label=\"SMS notifications\" />\n <Switch.Item label=\"Push notifications\" />\n </Switch.Group>",
4716
5328
  "<div className=\"flex flex-col gap-4\">\n <Switch\n label=\"Small\"\n size=\"sm\"\n checked={true}\n onCheckedChange={() => {}}\n />\n <Switch\n label=\"Base (default)\"\n size=\"base\"\n checked={true}\n onCheckedChange={() => {}}\n />\n <Switch\n label=\"Large\"\n size=\"lg\"\n checked={true}\n onCheckedChange={() => {}}\n />\n </div>"
4717
5329
  ],
4718
5330
  "colors": [
4719
5331
  "bg-kumo-base",
4720
- "border-kumo-line",
4721
- "ring-kumo-line",
5332
+ "ring-kumo-brand",
5333
+ "ring-kumo-focus",
5334
+ "ring-kumo-hairline",
4722
5335
  "text-kumo-danger",
4723
5336
  "text-kumo-default",
4724
5337
  "text-kumo-subtle"
@@ -4735,7 +5348,7 @@
4735
5348
  "props": {
4736
5349
  "legend": {
4737
5350
  "type": "string",
4738
- "required": true
5351
+ "optional": true
4739
5352
  },
4740
5353
  "children": {
4741
5354
  "type": "ReactNode",
@@ -4762,6 +5375,20 @@
4762
5375
  "optional": true
4763
5376
  }
4764
5377
  }
5378
+ },
5379
+ "Legend": {
5380
+ "name": "Legend",
5381
+ "description": "Legend sub-component",
5382
+ "props": {
5383
+ "children": {
5384
+ "type": "ReactNode",
5385
+ "required": true
5386
+ },
5387
+ "className": {
5388
+ "type": "string",
5389
+ "optional": true
5390
+ }
5391
+ }
4765
5392
  }
4766
5393
  }
4767
5394
  },
@@ -4827,13 +5454,14 @@
4827
5454
  }
4828
5455
  },
4829
5456
  "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>"
5457
+ "<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>",
5458
+ "<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 onCheckedChange={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 onCheckedChange={() => 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>",
5459
+ "<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>",
5460
+ "<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 onCheckedChange={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 onCheckedChange={() => 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>",
5461
+ "<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>",
5462
+ "<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>",
5463
+ "<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>",
5464
+ "<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 onCheckedChange={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 onCheckedChange={() => 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
5465
  ],
4838
5466
  "colors": [
4839
5467
  "bg-kumo-base",
@@ -4841,6 +5469,7 @@
4841
5469
  "bg-kumo-hairline",
4842
5470
  "bg-kumo-tint",
4843
5471
  "border-kumo-fill",
5472
+ "ring-kumo-brand",
4844
5473
  "text-kumo-default",
4845
5474
  "text-kumo-strong"
4846
5475
  ],
@@ -4892,6 +5521,90 @@
4892
5521
  }
4893
5522
  }
4894
5523
  },
5524
+ "TableOfContents": {
5525
+ "name": "TableOfContents",
5526
+ "type": "component",
5527
+ "description": "TableOfContents — presentational compound component for section navigation. Purely visual; all interaction logic (scroll tracking, active state management) is left to the consumer.",
5528
+ "importPath": "@cloudflare/kumo",
5529
+ "category": "Other",
5530
+ "props": {
5531
+ "children": {
5532
+ "type": "ReactNode",
5533
+ "optional": true
5534
+ },
5535
+ "className": {
5536
+ "type": "string",
5537
+ "optional": true
5538
+ },
5539
+ "id": {
5540
+ "type": "string",
5541
+ "optional": true
5542
+ },
5543
+ "lang": {
5544
+ "type": "string",
5545
+ "optional": true
5546
+ },
5547
+ "title": {
5548
+ "type": "string",
5549
+ "optional": true
5550
+ }
5551
+ },
5552
+ "examples": [
5553
+ "<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>",
5554
+ "<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>",
5555
+ "<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>",
5556
+ "<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=\"Examples\" href=\"#examples-demo\">\n <TableOfContents.Item className=\"cursor-pointer\">\n Basic example\n </TableOfContents.Item>\n <TableOfContents.Item className=\"cursor-pointer\">\n Advanced example\n </TableOfContents.Item>\n </TableOfContents.Group>\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\" href=\"#api-demo\">\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>",
5557
+ "<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>",
5558
+ "<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>"
5559
+ ],
5560
+ "colors": [
5561
+ "border-kumo-brand",
5562
+ "border-kumo-hairline",
5563
+ "border-kumo-line",
5564
+ "text-kumo-default",
5565
+ "text-kumo-subtle"
5566
+ ],
5567
+ "subComponents": {
5568
+ "Title": {
5569
+ "name": "Title",
5570
+ "description": "Title sub-component",
5571
+ "props": {}
5572
+ },
5573
+ "List": {
5574
+ "name": "List",
5575
+ "description": "List sub-component",
5576
+ "props": {}
5577
+ },
5578
+ "Item": {
5579
+ "name": "Item",
5580
+ "description": "Item sub-component",
5581
+ "props": {
5582
+ "active": {
5583
+ "type": "boolean",
5584
+ "optional": true
5585
+ }
5586
+ }
5587
+ },
5588
+ "Group": {
5589
+ "name": "Group",
5590
+ "description": "Group sub-component",
5591
+ "props": {
5592
+ "label": {
5593
+ "type": "string",
5594
+ "required": true
5595
+ },
5596
+ "href": {
5597
+ "type": "string",
5598
+ "optional": true
5599
+ },
5600
+ "active": {
5601
+ "type": "boolean",
5602
+ "optional": true
5603
+ }
5604
+ }
5605
+ }
5606
+ }
5607
+ },
4895
5608
  "Tabs": {
4896
5609
  "name": "Tabs",
4897
5610
  "type": "component",
@@ -4963,6 +5676,8 @@
4963
5676
  "bg-kumo-recessed",
4964
5677
  "bg-kumo-tint",
4965
5678
  "border-kumo-hairline",
5679
+ "ring-kumo-brand",
5680
+ "ring-kumo-focus",
4966
5681
  "ring-kumo-hairline",
4967
5682
  "ring-kumo-line",
4968
5683
  "text-kumo-default",
@@ -5074,9 +5789,32 @@
5074
5789
  "description": "Whether to truncate overflowing text with an ellipsis. Adds `truncate min-w-0` classes."
5075
5790
  },
5076
5791
  "as": {
5077
- "type": "React.ElementType",
5792
+ "type": "enum",
5078
5793
  "optional": true,
5079
- "description": "The HTML element type to render as (e.g. `\"span\"`, `\"p\"`, `\"h1\"`). Auto-selected based on variant if omitted."
5794
+ "description": "The HTML element to render. Accepts headings (`\"h1\"`–`\"h6\"`), block text (`\"p\"`, `\"pre\"`), inline text (`\"span\"`, `\"code\"`, `\"em\"`, `\"strong\"`, `\"small\"`, `\"abbr\"`, `\"time\"`), form-related (`\"label\"`, `\"legend\"`), list/definition (`\"dt\"`, `\"dd\"`, `\"li\"`), and `\"figcaption\"`.\n\n- **Required** for heading variants (`\"heading1\"`, `\"heading2\"`, `\"heading3\"`) — pick the element that reflects this text's place in the document outline, or `\"span\"` for decorative heading-styled text that is not a section heading.\n- **Optional** for body variants (defaults to `\"p\"`) and monospace variants (defaults to `\"span\"`).",
5795
+ "values": [
5796
+ "h1",
5797
+ "h2",
5798
+ "h3",
5799
+ "h4",
5800
+ "h5",
5801
+ "h6",
5802
+ "p",
5803
+ "span",
5804
+ "label",
5805
+ "dt",
5806
+ "dd",
5807
+ "li",
5808
+ "figcaption",
5809
+ "legend",
5810
+ "pre",
5811
+ "code",
5812
+ "em",
5813
+ "strong",
5814
+ "small",
5815
+ "abbr",
5816
+ "time"
5817
+ ]
5080
5818
  },
5081
5819
  "children": {
5082
5820
  "type": "ReactNode",
@@ -5085,8 +5823,8 @@
5085
5823
  }
5086
5824
  },
5087
5825
  "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>"
5826
+ "<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\" as=\"h1\">\n Heading 1\n </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\" as=\"h2\">\n Heading 2\n </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\" as=\"h3\">\n Heading 3\n </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>",
5827
+ "<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
5828
  ],
5091
5829
  "colors": [
5092
5830
  "text-kumo-danger",
@@ -5179,6 +5917,7 @@
5179
5917
  "ring-kumo-danger",
5180
5918
  "ring-kumo-hairline",
5181
5919
  "ring-kumo-info",
5920
+ "ring-kumo-line",
5182
5921
  "ring-kumo-success",
5183
5922
  "ring-kumo-warning",
5184
5923
  "text-kumo-danger",
@@ -5258,11 +5997,11 @@
5258
5997
  }
5259
5998
  },
5260
5999
  "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>",
6000
+ "<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>",
6001
+ "<TooltipProvider>\n <Tooltip\n content=\"Add\"\n render={<Button shape=\"square\" icon={PlusIcon} aria-label=\"Add\" />}\n />\n </TooltipProvider>",
6002
+ "<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
6003
  "<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>"
6004
+ "<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
6005
  ],
5267
6006
  "colors": [
5268
6007
  "bg-kumo-base",
@@ -5519,6 +6258,18 @@
5519
6258
  },
5520
6259
  "search": {
5521
6260
  "byCategory": {
6261
+ "Other": [
6262
+ "Autocomplete",
6263
+ "CloudflareLogo",
6264
+ "DatePicker",
6265
+ "Label",
6266
+ "Link",
6267
+ "SensitiveInput",
6268
+ "Sidebar",
6269
+ "Table",
6270
+ "TableOfContents",
6271
+ "DeleteResource"
6272
+ ],
5522
6273
  "Display": [
5523
6274
  "Badge",
5524
6275
  "Breadcrumbs",
@@ -5544,20 +6295,11 @@
5544
6295
  "DateRangePicker",
5545
6296
  "Field",
5546
6297
  "Input",
6298
+ "InputGroup",
5547
6299
  "Radio",
5548
6300
  "Select",
5549
6301
  "Switch"
5550
6302
  ],
5551
- "Other": [
5552
- "CloudflareLogo",
5553
- "DatePicker",
5554
- "Label",
5555
- "Link",
5556
- "SensitiveInput",
5557
- "Sidebar",
5558
- "Table",
5559
- "DeleteResource"
5560
- ],
5561
6303
  "Navigation": [
5562
6304
  "CommandPalette",
5563
6305
  "MenuBar",
@@ -5578,6 +6320,7 @@
5578
6320
  ]
5579
6321
  },
5580
6322
  "byName": [
6323
+ "Autocomplete",
5581
6324
  "Badge",
5582
6325
  "Banner",
5583
6326
  "Breadcrumbs",
@@ -5598,6 +6341,7 @@
5598
6341
  "Field",
5599
6342
  "Grid",
5600
6343
  "Input",
6344
+ "InputGroup",
5601
6345
  "Label",
5602
6346
  "LayerCard",
5603
6347
  "Link",
@@ -5615,6 +6359,7 @@
5615
6359
  "Surface",
5616
6360
  "Switch",
5617
6361
  "Table",
6362
+ "TableOfContents",
5618
6363
  "Tabs",
5619
6364
  "Text",
5620
6365
  "Toasty",
@@ -5622,6 +6367,7 @@
5622
6367
  ],
5623
6368
  "byType": {
5624
6369
  "component": [
6370
+ "Autocomplete",
5625
6371
  "Badge",
5626
6372
  "Banner",
5627
6373
  "Breadcrumbs",
@@ -5641,6 +6387,7 @@
5641
6387
  "Field",
5642
6388
  "Grid",
5643
6389
  "Input",
6390
+ "InputGroup",
5644
6391
  "Label",
5645
6392
  "LayerCard",
5646
6393
  "Link",
@@ -5656,6 +6403,7 @@
5656
6403
  "Surface",
5657
6404
  "Switch",
5658
6405
  "Table",
6406
+ "TableOfContents",
5659
6407
  "Tabs",
5660
6408
  "Text",
5661
6409
  "Toasty",