@cloudflare/kumo 1.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 (560) hide show
  1. package/CHANGELOG.md +510 -0
  2. package/LICENSE +21 -0
  3. package/README.md +521 -0
  4. package/ai/component-registry.json +3754 -0
  5. package/ai/component-registry.md +4022 -0
  6. package/ai/schemas.ts +594 -0
  7. package/dist/badge-Dc99vsfo.js +51 -0
  8. package/dist/badge-Dc99vsfo.js.map +1 -0
  9. package/dist/banner-4fkH6Sbt.js +51 -0
  10. package/dist/banner-4fkH6Sbt.js.map +1 -0
  11. package/dist/breadcrumbs-B5SY2CWj.js +132 -0
  12. package/dist/breadcrumbs-B5SY2CWj.js.map +1 -0
  13. package/dist/button-E2-hZMZE.js +191 -0
  14. package/dist/button-E2-hZMZE.js.map +1 -0
  15. package/dist/catalog.js +229 -0
  16. package/dist/catalog.js.map +1 -0
  17. package/dist/checkbox-BexIU_lZ.js +224 -0
  18. package/dist/checkbox-BexIU_lZ.js.map +1 -0
  19. package/dist/clipboard-text-BFHWMjmr.js +108 -0
  20. package/dist/clipboard-text-BFHWMjmr.js.map +1 -0
  21. package/dist/cn-Bhsu1vx2.js +26 -0
  22. package/dist/cn-Bhsu1vx2.js.map +1 -0
  23. package/dist/code-T2wPDiM0.js +60 -0
  24. package/dist/code-T2wPDiM0.js.map +1 -0
  25. package/dist/collapsible-OBNkTO48.js +56 -0
  26. package/dist/collapsible-OBNkTO48.js.map +1 -0
  27. package/dist/combobox-Dld0kS0U.js +228 -0
  28. package/dist/combobox-Dld0kS0U.js.map +1 -0
  29. package/dist/command-line/cli.js +764 -0
  30. package/dist/command-line/commands/add.js +220 -0
  31. package/dist/command-line/commands/blocks.js +61 -0
  32. package/dist/command-line/commands/doc.js +167 -0
  33. package/dist/command-line/commands/init.js +95 -0
  34. package/dist/command-line/commands/ls.js +53 -0
  35. package/dist/command-palette-BgQ680BG.js +393 -0
  36. package/dist/command-palette-BgQ680BG.js.map +1 -0
  37. package/dist/components/badge.js +7 -0
  38. package/dist/components/badge.js.map +1 -0
  39. package/dist/components/banner.js +7 -0
  40. package/dist/components/banner.js.map +1 -0
  41. package/dist/components/breadcrumbs.js +9 -0
  42. package/dist/components/breadcrumbs.js.map +1 -0
  43. package/dist/components/button.js +9 -0
  44. package/dist/components/button.js.map +1 -0
  45. package/dist/components/checkbox.js +8 -0
  46. package/dist/components/checkbox.js.map +1 -0
  47. package/dist/components/clipboard-text.js +6 -0
  48. package/dist/components/clipboard-text.js.map +1 -0
  49. package/dist/components/code.js +7 -0
  50. package/dist/components/code.js.map +1 -0
  51. package/dist/components/collapsible.js +6 -0
  52. package/dist/components/collapsible.js.map +1 -0
  53. package/dist/components/combobox.js +6 -0
  54. package/dist/components/combobox.js.map +1 -0
  55. package/dist/components/command-palette.js +8 -0
  56. package/dist/components/command-palette.js.map +1 -0
  57. package/dist/components/date-range-picker.js +6 -0
  58. package/dist/components/date-range-picker.js.map +1 -0
  59. package/dist/components/dialog.js +11 -0
  60. package/dist/components/dialog.js.map +1 -0
  61. package/dist/components/dropdown.js +6 -0
  62. package/dist/components/dropdown.js.map +1 -0
  63. package/dist/components/empty.js +9 -0
  64. package/dist/components/empty.js.map +1 -0
  65. package/dist/components/field.js +9 -0
  66. package/dist/components/field.js.map +1 -0
  67. package/dist/components/grid.js +11 -0
  68. package/dist/components/grid.js.map +1 -0
  69. package/dist/components/input.js +11 -0
  70. package/dist/components/input.js.map +1 -0
  71. package/dist/components/label.js +10 -0
  72. package/dist/components/label.js.map +1 -0
  73. package/dist/components/layer-card.js +6 -0
  74. package/dist/components/layer-card.js.map +1 -0
  75. package/dist/components/link.js +9 -0
  76. package/dist/components/link.js.map +1 -0
  77. package/dist/components/loader.js +8 -0
  78. package/dist/components/loader.js.map +1 -0
  79. package/dist/components/menubar.js +7 -0
  80. package/dist/components/menubar.js.map +1 -0
  81. package/dist/components/meter.js +6 -0
  82. package/dist/components/meter.js.map +1 -0
  83. package/dist/components/pagination.js +6 -0
  84. package/dist/components/pagination.js.map +1 -0
  85. package/dist/components/popover.js +14 -0
  86. package/dist/components/popover.js.map +1 -0
  87. package/dist/components/radio.js +10 -0
  88. package/dist/components/radio.js.map +1 -0
  89. package/dist/components/select.js +6 -0
  90. package/dist/components/select.js.map +1 -0
  91. package/dist/components/sensitive-input.js +8 -0
  92. package/dist/components/sensitive-input.js.map +1 -0
  93. package/dist/components/surface.js +6 -0
  94. package/dist/components/surface.js.map +1 -0
  95. package/dist/components/switch.js +8 -0
  96. package/dist/components/switch.js.map +1 -0
  97. package/dist/components/table.js +8 -0
  98. package/dist/components/table.js.map +1 -0
  99. package/dist/components/tabs.js +6 -0
  100. package/dist/components/tabs.js.map +1 -0
  101. package/dist/components/text.js +6 -0
  102. package/dist/components/text.js.map +1 -0
  103. package/dist/components/toast.js +8 -0
  104. package/dist/components/toast.js.map +1 -0
  105. package/dist/components/tooltip.js +7 -0
  106. package/dist/components/tooltip.js.map +1 -0
  107. package/dist/date-range-picker-CbKEQ9pi.js +408 -0
  108. package/dist/date-range-picker-CbKEQ9pi.js.map +1 -0
  109. package/dist/dialog-B1TaN0oR.js +77 -0
  110. package/dist/dialog-B1TaN0oR.js.map +1 -0
  111. package/dist/dropdown-D0rhYKeG.js +263 -0
  112. package/dist/dropdown-D0rhYKeG.js.map +1 -0
  113. package/dist/empty-DzCqjea-.js +93 -0
  114. package/dist/empty-DzCqjea-.js.map +1 -0
  115. package/dist/field-V3J0Ql_V.js +71 -0
  116. package/dist/field-V3J0Ql_V.js.map +1 -0
  117. package/dist/grid-DKajRHh8.js +127 -0
  118. package/dist/grid-DKajRHh8.js.map +1 -0
  119. package/dist/index.js +125 -0
  120. package/dist/index.js.map +1 -0
  121. package/dist/input-Dqvc2AB_.js +109 -0
  122. package/dist/input-Dqvc2AB_.js.map +1 -0
  123. package/dist/input-area-B9qajxvZ.js +57 -0
  124. package/dist/input-area-B9qajxvZ.js.map +1 -0
  125. package/dist/input-group-Bl6tgD5-.js +111 -0
  126. package/dist/input-group-Bl6tgD5-.js.map +1 -0
  127. package/dist/label-87HQArUG.js +50 -0
  128. package/dist/label-87HQArUG.js.map +1 -0
  129. package/dist/layer-card-C8j5Hkkj.js +44 -0
  130. package/dist/layer-card-C8j5Hkkj.js.map +1 -0
  131. package/dist/link-6TIZ4JIw.js +73 -0
  132. package/dist/link-6TIZ4JIw.js.map +1 -0
  133. package/dist/link-provider-DPBGo-0n.js +22 -0
  134. package/dist/link-provider-DPBGo-0n.js.map +1 -0
  135. package/dist/loader-DHGMYlC6.js +105 -0
  136. package/dist/loader-DHGMYlC6.js.map +1 -0
  137. package/dist/menubar-DLwLRFB1.js +92 -0
  138. package/dist/menubar-DLwLRFB1.js.map +1 -0
  139. package/dist/meter-DKUuvXxS.js +51 -0
  140. package/dist/meter-DKUuvXxS.js.map +1 -0
  141. package/dist/pagination-C4HQqodz.js +99 -0
  142. package/dist/pagination-C4HQqodz.js.map +1 -0
  143. package/dist/popover-DhdIqrP7.js +178 -0
  144. package/dist/popover-DhdIqrP7.js.map +1 -0
  145. package/dist/primitives/accordion.js +6 -0
  146. package/dist/primitives/accordion.js.map +1 -0
  147. package/dist/primitives/alert-dialog.js +6 -0
  148. package/dist/primitives/alert-dialog.js.map +1 -0
  149. package/dist/primitives/autocomplete.js +6 -0
  150. package/dist/primitives/autocomplete.js.map +1 -0
  151. package/dist/primitives/avatar.js +6 -0
  152. package/dist/primitives/avatar.js.map +1 -0
  153. package/dist/primitives/button.js +6 -0
  154. package/dist/primitives/button.js.map +1 -0
  155. package/dist/primitives/checkbox-group.js +6 -0
  156. package/dist/primitives/checkbox-group.js.map +1 -0
  157. package/dist/primitives/checkbox.js +6 -0
  158. package/dist/primitives/checkbox.js.map +1 -0
  159. package/dist/primitives/collapsible.js +6 -0
  160. package/dist/primitives/collapsible.js.map +1 -0
  161. package/dist/primitives/combobox.js +6 -0
  162. package/dist/primitives/combobox.js.map +1 -0
  163. package/dist/primitives/context-menu.js +6 -0
  164. package/dist/primitives/context-menu.js.map +1 -0
  165. package/dist/primitives/dialog.js +6 -0
  166. package/dist/primitives/dialog.js.map +1 -0
  167. package/dist/primitives/direction-provider.js +7 -0
  168. package/dist/primitives/direction-provider.js.map +1 -0
  169. package/dist/primitives/field.js +6 -0
  170. package/dist/primitives/field.js.map +1 -0
  171. package/dist/primitives/fieldset.js +6 -0
  172. package/dist/primitives/fieldset.js.map +1 -0
  173. package/dist/primitives/form.js +6 -0
  174. package/dist/primitives/form.js.map +1 -0
  175. package/dist/primitives/input.js +6 -0
  176. package/dist/primitives/input.js.map +1 -0
  177. package/dist/primitives/menu.js +6 -0
  178. package/dist/primitives/menu.js.map +1 -0
  179. package/dist/primitives/menubar.js +6 -0
  180. package/dist/primitives/menubar.js.map +1 -0
  181. package/dist/primitives/meter.js +6 -0
  182. package/dist/primitives/meter.js.map +1 -0
  183. package/dist/primitives/navigation-menu.js +6 -0
  184. package/dist/primitives/navigation-menu.js.map +1 -0
  185. package/dist/primitives/number-field.js +6 -0
  186. package/dist/primitives/number-field.js.map +1 -0
  187. package/dist/primitives/popover.js +6 -0
  188. package/dist/primitives/popover.js.map +1 -0
  189. package/dist/primitives/preview-card.js +6 -0
  190. package/dist/primitives/preview-card.js.map +1 -0
  191. package/dist/primitives/progress.js +6 -0
  192. package/dist/primitives/progress.js.map +1 -0
  193. package/dist/primitives/radio-group.js +6 -0
  194. package/dist/primitives/radio-group.js.map +1 -0
  195. package/dist/primitives/radio.js +6 -0
  196. package/dist/primitives/radio.js.map +1 -0
  197. package/dist/primitives/scroll-area.js +6 -0
  198. package/dist/primitives/scroll-area.js.map +1 -0
  199. package/dist/primitives/select.js +6 -0
  200. package/dist/primitives/select.js.map +1 -0
  201. package/dist/primitives/separator.js +6 -0
  202. package/dist/primitives/separator.js.map +1 -0
  203. package/dist/primitives/slider.js +6 -0
  204. package/dist/primitives/slider.js.map +1 -0
  205. package/dist/primitives/switch.js +6 -0
  206. package/dist/primitives/switch.js.map +1 -0
  207. package/dist/primitives/tabs.js +6 -0
  208. package/dist/primitives/tabs.js.map +1 -0
  209. package/dist/primitives/toast.js +6 -0
  210. package/dist/primitives/toast.js.map +1 -0
  211. package/dist/primitives/toggle-group.js +6 -0
  212. package/dist/primitives/toggle-group.js.map +1 -0
  213. package/dist/primitives/toggle.js +6 -0
  214. package/dist/primitives/toggle.js.map +1 -0
  215. package/dist/primitives/toolbar.js +6 -0
  216. package/dist/primitives/toolbar.js.map +1 -0
  217. package/dist/primitives/tooltip.js +6 -0
  218. package/dist/primitives/tooltip.js.map +1 -0
  219. package/dist/primitives.js +43 -0
  220. package/dist/primitives.js.map +1 -0
  221. package/dist/radio-BVAG7hNp.js +125 -0
  222. package/dist/radio-BVAG7hNp.js.map +1 -0
  223. package/dist/registry.js +2 -0
  224. package/dist/registry.js.map +1 -0
  225. package/dist/schemas-BSdA0fz-.js +3210 -0
  226. package/dist/schemas-BSdA0fz-.js.map +1 -0
  227. package/dist/select-B5Vb3zou.js +122 -0
  228. package/dist/select-B5Vb3zou.js.map +1 -0
  229. package/dist/sensitive-input-D5HCV04N.js +258 -0
  230. package/dist/sensitive-input-D5HCV04N.js.map +1 -0
  231. package/dist/skeleton-line-CtpS1u1J.js +28 -0
  232. package/dist/skeleton-line-CtpS1u1J.js.map +1 -0
  233. package/dist/src/blocks/page-header/index.d.ts +2 -0
  234. package/dist/src/blocks/page-header/index.d.ts.map +1 -0
  235. package/dist/src/blocks/page-header/page-header.d.ts +38 -0
  236. package/dist/src/blocks/page-header/page-header.d.ts.map +1 -0
  237. package/dist/src/blocks/resource-list/index.d.ts +2 -0
  238. package/dist/src/blocks/resource-list/index.d.ts.map +1 -0
  239. package/dist/src/blocks/resource-list/resource-list.d.ts +18 -0
  240. package/dist/src/blocks/resource-list/resource-list.d.ts.map +1 -0
  241. package/dist/src/catalog/catalog.d.ts +75 -0
  242. package/dist/src/catalog/catalog.d.ts.map +1 -0
  243. package/dist/src/catalog/data.d.ts +44 -0
  244. package/dist/src/catalog/data.d.ts.map +1 -0
  245. package/dist/src/catalog/index.d.ts +39 -0
  246. package/dist/src/catalog/index.d.ts.map +1 -0
  247. package/dist/src/catalog/types.d.ts +226 -0
  248. package/dist/src/catalog/types.d.ts.map +1 -0
  249. package/dist/src/catalog/visibility.d.ts +37 -0
  250. package/dist/src/catalog/visibility.d.ts.map +1 -0
  251. package/dist/src/command-line/build-cli.d.ts +7 -0
  252. package/dist/src/command-line/build-cli.d.ts.map +1 -0
  253. package/dist/src/command-line/cli.d.ts +13 -0
  254. package/dist/src/command-line/cli.d.ts.map +1 -0
  255. package/dist/src/command-line/commands/add.d.ts +10 -0
  256. package/dist/src/command-line/commands/add.d.ts.map +1 -0
  257. package/dist/src/command-line/commands/blocks.d.ts +10 -0
  258. package/dist/src/command-line/commands/blocks.d.ts.map +1 -0
  259. package/dist/src/command-line/commands/doc.d.ts +14 -0
  260. package/dist/src/command-line/commands/doc.d.ts.map +1 -0
  261. package/dist/src/command-line/commands/init.d.ts +18 -0
  262. package/dist/src/command-line/commands/init.d.ts.map +1 -0
  263. package/dist/src/command-line/commands/ls.d.ts +10 -0
  264. package/dist/src/command-line/commands/ls.d.ts.map +1 -0
  265. package/dist/src/command-line/commands/migrate.d.ts +10 -0
  266. package/dist/src/command-line/commands/migrate.d.ts.map +1 -0
  267. package/dist/src/command-line/utils/config.d.ts +42 -0
  268. package/dist/src/command-line/utils/config.d.ts.map +1 -0
  269. package/dist/src/command-line/utils/transformer.d.ts +17 -0
  270. package/dist/src/command-line/utils/transformer.d.ts.map +1 -0
  271. package/dist/src/components/badge/badge.d.ts +46 -0
  272. package/dist/src/components/badge/badge.d.ts.map +1 -0
  273. package/dist/src/components/badge/index.d.ts +2 -0
  274. package/dist/src/components/badge/index.d.ts.map +1 -0
  275. package/dist/src/components/banner/banner.d.ts +45 -0
  276. package/dist/src/components/banner/banner.d.ts.map +1 -0
  277. package/dist/src/components/banner/index.d.ts +2 -0
  278. package/dist/src/components/banner/index.d.ts.map +1 -0
  279. package/dist/src/components/breadcrumbs/breadcrumbs.d.ts +43 -0
  280. package/dist/src/components/breadcrumbs/breadcrumbs.d.ts.map +1 -0
  281. package/dist/src/components/breadcrumbs/index.d.ts +2 -0
  282. package/dist/src/components/breadcrumbs/index.d.ts.map +1 -0
  283. package/dist/src/components/button/button.d.ts +118 -0
  284. package/dist/src/components/button/button.d.ts.map +1 -0
  285. package/dist/src/components/button/index.d.ts +2 -0
  286. package/dist/src/components/button/index.d.ts.map +1 -0
  287. package/dist/src/components/checkbox/checkbox.d.ts +167 -0
  288. package/dist/src/components/checkbox/checkbox.d.ts.map +1 -0
  289. package/dist/src/components/checkbox/index.d.ts +2 -0
  290. package/dist/src/components/checkbox/index.d.ts.map +1 -0
  291. package/dist/src/components/clipboard-text/clipboard-text.d.ts +38 -0
  292. package/dist/src/components/clipboard-text/clipboard-text.d.ts.map +1 -0
  293. package/dist/src/components/clipboard-text/index.d.ts +2 -0
  294. package/dist/src/components/clipboard-text/index.d.ts.map +1 -0
  295. package/dist/src/components/code/code.d.ts +138 -0
  296. package/dist/src/components/code/code.d.ts.map +1 -0
  297. package/dist/src/components/code/index.d.ts +4 -0
  298. package/dist/src/components/code/index.d.ts.map +1 -0
  299. package/dist/src/components/collapsible/collapsible.d.ts +62 -0
  300. package/dist/src/components/collapsible/collapsible.d.ts.map +1 -0
  301. package/dist/src/components/collapsible/index.d.ts +2 -0
  302. package/dist/src/components/collapsible/index.d.ts.map +1 -0
  303. package/dist/src/components/combobox/combobox.d.ts +124 -0
  304. package/dist/src/components/combobox/combobox.d.ts.map +1 -0
  305. package/dist/src/components/combobox/index.d.ts +2 -0
  306. package/dist/src/components/combobox/index.d.ts.map +1 -0
  307. package/dist/src/components/command-palette/command-palette.d.ts +225 -0
  308. package/dist/src/components/command-palette/command-palette.d.ts.map +1 -0
  309. package/dist/src/components/command-palette/index.d.ts +3 -0
  310. package/dist/src/components/command-palette/index.d.ts.map +1 -0
  311. package/dist/src/components/command-palette/types.d.ts +149 -0
  312. package/dist/src/components/command-palette/types.d.ts.map +1 -0
  313. package/dist/src/components/date-range-picker/date-range-picker.d.ts +65 -0
  314. package/dist/src/components/date-range-picker/date-range-picker.d.ts.map +1 -0
  315. package/dist/src/components/date-range-picker/index.d.ts +2 -0
  316. package/dist/src/components/date-range-picker/index.d.ts.map +1 -0
  317. package/dist/src/components/dialog/dialog.d.ts +121 -0
  318. package/dist/src/components/dialog/dialog.d.ts.map +1 -0
  319. package/dist/src/components/dialog/index.d.ts +2 -0
  320. package/dist/src/components/dialog/index.d.ts.map +1 -0
  321. package/dist/src/components/dropdown/dropdown.d.ts +58 -0
  322. package/dist/src/components/dropdown/dropdown.d.ts.map +1 -0
  323. package/dist/src/components/dropdown/index.d.ts +2 -0
  324. package/dist/src/components/dropdown/index.d.ts.map +1 -0
  325. package/dist/src/components/empty/empty.d.ts +34 -0
  326. package/dist/src/components/empty/empty.d.ts.map +1 -0
  327. package/dist/src/components/empty/index.d.ts +2 -0
  328. package/dist/src/components/empty/index.d.ts.map +1 -0
  329. package/dist/src/components/field/field.d.ts +38 -0
  330. package/dist/src/components/field/field.d.ts.map +1 -0
  331. package/dist/src/components/field/index.d.ts +2 -0
  332. package/dist/src/components/field/index.d.ts.map +1 -0
  333. package/dist/src/components/grid/grid.d.ts +107 -0
  334. package/dist/src/components/grid/grid.d.ts.map +1 -0
  335. package/dist/src/components/grid/index.d.ts +2 -0
  336. package/dist/src/components/grid/index.d.ts.map +1 -0
  337. package/dist/src/components/input/index.d.ts +4 -0
  338. package/dist/src/components/input/index.d.ts.map +1 -0
  339. package/dist/src/components/input/input-area.d.ts +46 -0
  340. package/dist/src/components/input/input-area.d.ts.map +1 -0
  341. package/dist/src/components/input/input-group.d.ts +39 -0
  342. package/dist/src/components/input/input-group.d.ts.map +1 -0
  343. package/dist/src/components/input/input.d.ts +157 -0
  344. package/dist/src/components/input/input.d.ts.map +1 -0
  345. package/dist/src/components/label/index.d.ts +2 -0
  346. package/dist/src/components/label/index.d.ts.map +1 -0
  347. package/dist/src/components/label/label.d.ts +54 -0
  348. package/dist/src/components/label/label.d.ts.map +1 -0
  349. package/dist/src/components/layer-card/index.d.ts +2 -0
  350. package/dist/src/components/layer-card/index.d.ts.map +1 -0
  351. package/dist/src/components/layer-card/layer-card.d.ts +16 -0
  352. package/dist/src/components/layer-card/layer-card.d.ts.map +1 -0
  353. package/dist/src/components/link/index.d.ts +2 -0
  354. package/dist/src/components/link/index.d.ts.map +1 -0
  355. package/dist/src/components/link/link.d.ts +35 -0
  356. package/dist/src/components/link/link.d.ts.map +1 -0
  357. package/dist/src/components/loader/index.d.ts +3 -0
  358. package/dist/src/components/loader/index.d.ts.map +1 -0
  359. package/dist/src/components/loader/loader.d.ts +30 -0
  360. package/dist/src/components/loader/loader.d.ts.map +1 -0
  361. package/dist/src/components/loader/skeleton-line.d.ts +10 -0
  362. package/dist/src/components/loader/skeleton-line.d.ts.map +1 -0
  363. package/dist/src/components/menubar/index.d.ts +3 -0
  364. package/dist/src/components/menubar/index.d.ts.map +1 -0
  365. package/dist/src/components/menubar/menubar.d.ts +22 -0
  366. package/dist/src/components/menubar/menubar.d.ts.map +1 -0
  367. package/dist/src/components/menubar/use-menu-navigation.d.ts +8 -0
  368. package/dist/src/components/menubar/use-menu-navigation.d.ts.map +1 -0
  369. package/dist/src/components/meter/index.d.ts +2 -0
  370. package/dist/src/components/meter/index.d.ts.map +1 -0
  371. package/dist/src/components/meter/meter.d.ts +18 -0
  372. package/dist/src/components/meter/meter.d.ts.map +1 -0
  373. package/dist/src/components/pagination/index.d.ts +2 -0
  374. package/dist/src/components/pagination/index.d.ts.map +1 -0
  375. package/dist/src/components/pagination/pagination.d.ts +28 -0
  376. package/dist/src/components/pagination/pagination.d.ts.map +1 -0
  377. package/dist/src/components/popover/index.d.ts +3 -0
  378. package/dist/src/components/popover/index.d.ts.map +1 -0
  379. package/dist/src/components/popover/popover.d.ts +110 -0
  380. package/dist/src/components/popover/popover.d.ts.map +1 -0
  381. package/dist/src/components/radio/index.d.ts +2 -0
  382. package/dist/src/components/radio/index.d.ts.map +1 -0
  383. package/dist/src/components/radio/radio.d.ts +141 -0
  384. package/dist/src/components/radio/radio.d.ts.map +1 -0
  385. package/dist/src/components/select/index.d.ts +2 -0
  386. package/dist/src/components/select/index.d.ts.map +1 -0
  387. package/dist/src/components/select/select.d.ts +128 -0
  388. package/dist/src/components/select/select.d.ts.map +1 -0
  389. package/dist/src/components/sensitive-input/index.d.ts +2 -0
  390. package/dist/src/components/sensitive-input/index.d.ts.map +1 -0
  391. package/dist/src/components/sensitive-input/sensitive-input.d.ts +70 -0
  392. package/dist/src/components/sensitive-input/sensitive-input.d.ts.map +1 -0
  393. package/dist/src/components/surface/index.d.ts +2 -0
  394. package/dist/src/components/surface/index.d.ts.map +1 -0
  395. package/dist/src/components/surface/surface.d.ts +48 -0
  396. package/dist/src/components/surface/surface.d.ts.map +1 -0
  397. package/dist/src/components/switch/index.d.ts +2 -0
  398. package/dist/src/components/switch/index.d.ts.map +1 -0
  399. package/dist/src/components/switch/switch.d.ts +155 -0
  400. package/dist/src/components/switch/switch.d.ts.map +1 -0
  401. package/dist/src/components/table/index.d.ts +2 -0
  402. package/dist/src/components/table/index.d.ts.map +1 -0
  403. package/dist/src/components/table/table.d.ts +54 -0
  404. package/dist/src/components/table/table.d.ts.map +1 -0
  405. package/dist/src/components/tabs/index.d.ts +3 -0
  406. package/dist/src/components/tabs/index.d.ts.map +1 -0
  407. package/dist/src/components/tabs/tabs.d.ts +64 -0
  408. package/dist/src/components/tabs/tabs.d.ts.map +1 -0
  409. package/dist/src/components/text/index.d.ts +2 -0
  410. package/dist/src/components/text/index.d.ts.map +1 -0
  411. package/dist/src/components/text/text.d.ts +153 -0
  412. package/dist/src/components/text/text.d.ts.map +1 -0
  413. package/dist/src/components/toast/index.d.ts +3 -0
  414. package/dist/src/components/toast/index.d.ts.map +1 -0
  415. package/dist/src/components/toast/toast.d.ts +66 -0
  416. package/dist/src/components/toast/toast.d.ts.map +1 -0
  417. package/dist/src/components/tooltip/index.d.ts +2 -0
  418. package/dist/src/components/tooltip/index.d.ts.map +1 -0
  419. package/dist/src/components/tooltip/tooltip.d.ts +43 -0
  420. package/dist/src/components/tooltip/tooltip.d.ts.map +1 -0
  421. package/dist/src/index.d.ts +39 -0
  422. package/dist/src/index.d.ts.map +1 -0
  423. package/dist/src/primitives/accordion.d.ts +13 -0
  424. package/dist/src/primitives/accordion.d.ts.map +1 -0
  425. package/dist/src/primitives/alert-dialog.d.ts +13 -0
  426. package/dist/src/primitives/alert-dialog.d.ts.map +1 -0
  427. package/dist/src/primitives/autocomplete.d.ts +13 -0
  428. package/dist/src/primitives/autocomplete.d.ts.map +1 -0
  429. package/dist/src/primitives/avatar.d.ts +13 -0
  430. package/dist/src/primitives/avatar.d.ts.map +1 -0
  431. package/dist/src/primitives/button.d.ts +13 -0
  432. package/dist/src/primitives/button.d.ts.map +1 -0
  433. package/dist/src/primitives/checkbox-group.d.ts +13 -0
  434. package/dist/src/primitives/checkbox-group.d.ts.map +1 -0
  435. package/dist/src/primitives/checkbox.d.ts +13 -0
  436. package/dist/src/primitives/checkbox.d.ts.map +1 -0
  437. package/dist/src/primitives/collapsible.d.ts +13 -0
  438. package/dist/src/primitives/collapsible.d.ts.map +1 -0
  439. package/dist/src/primitives/combobox.d.ts +13 -0
  440. package/dist/src/primitives/combobox.d.ts.map +1 -0
  441. package/dist/src/primitives/context-menu.d.ts +13 -0
  442. package/dist/src/primitives/context-menu.d.ts.map +1 -0
  443. package/dist/src/primitives/dialog.d.ts +13 -0
  444. package/dist/src/primitives/dialog.d.ts.map +1 -0
  445. package/dist/src/primitives/direction-provider.d.ts +13 -0
  446. package/dist/src/primitives/direction-provider.d.ts.map +1 -0
  447. package/dist/src/primitives/field.d.ts +13 -0
  448. package/dist/src/primitives/field.d.ts.map +1 -0
  449. package/dist/src/primitives/fieldset.d.ts +13 -0
  450. package/dist/src/primitives/fieldset.d.ts.map +1 -0
  451. package/dist/src/primitives/form.d.ts +13 -0
  452. package/dist/src/primitives/form.d.ts.map +1 -0
  453. package/dist/src/primitives/index.d.ts +52 -0
  454. package/dist/src/primitives/index.d.ts.map +1 -0
  455. package/dist/src/primitives/input.d.ts +13 -0
  456. package/dist/src/primitives/input.d.ts.map +1 -0
  457. package/dist/src/primitives/menu.d.ts +13 -0
  458. package/dist/src/primitives/menu.d.ts.map +1 -0
  459. package/dist/src/primitives/menubar.d.ts +13 -0
  460. package/dist/src/primitives/menubar.d.ts.map +1 -0
  461. package/dist/src/primitives/meter.d.ts +13 -0
  462. package/dist/src/primitives/meter.d.ts.map +1 -0
  463. package/dist/src/primitives/navigation-menu.d.ts +13 -0
  464. package/dist/src/primitives/navigation-menu.d.ts.map +1 -0
  465. package/dist/src/primitives/number-field.d.ts +13 -0
  466. package/dist/src/primitives/number-field.d.ts.map +1 -0
  467. package/dist/src/primitives/popover.d.ts +13 -0
  468. package/dist/src/primitives/popover.d.ts.map +1 -0
  469. package/dist/src/primitives/preview-card.d.ts +13 -0
  470. package/dist/src/primitives/preview-card.d.ts.map +1 -0
  471. package/dist/src/primitives/progress.d.ts +13 -0
  472. package/dist/src/primitives/progress.d.ts.map +1 -0
  473. package/dist/src/primitives/radio-group.d.ts +13 -0
  474. package/dist/src/primitives/radio-group.d.ts.map +1 -0
  475. package/dist/src/primitives/radio.d.ts +13 -0
  476. package/dist/src/primitives/radio.d.ts.map +1 -0
  477. package/dist/src/primitives/scroll-area.d.ts +13 -0
  478. package/dist/src/primitives/scroll-area.d.ts.map +1 -0
  479. package/dist/src/primitives/select.d.ts +13 -0
  480. package/dist/src/primitives/select.d.ts.map +1 -0
  481. package/dist/src/primitives/separator.d.ts +13 -0
  482. package/dist/src/primitives/separator.d.ts.map +1 -0
  483. package/dist/src/primitives/slider.d.ts +13 -0
  484. package/dist/src/primitives/slider.d.ts.map +1 -0
  485. package/dist/src/primitives/switch.d.ts +13 -0
  486. package/dist/src/primitives/switch.d.ts.map +1 -0
  487. package/dist/src/primitives/tabs.d.ts +13 -0
  488. package/dist/src/primitives/tabs.d.ts.map +1 -0
  489. package/dist/src/primitives/toast.d.ts +13 -0
  490. package/dist/src/primitives/toast.d.ts.map +1 -0
  491. package/dist/src/primitives/toggle-group.d.ts +13 -0
  492. package/dist/src/primitives/toggle-group.d.ts.map +1 -0
  493. package/dist/src/primitives/toggle.d.ts +13 -0
  494. package/dist/src/primitives/toggle.d.ts.map +1 -0
  495. package/dist/src/primitives/toolbar.d.ts +13 -0
  496. package/dist/src/primitives/toolbar.d.ts.map +1 -0
  497. package/dist/src/primitives/tooltip.d.ts +13 -0
  498. package/dist/src/primitives/tooltip.d.ts.map +1 -0
  499. package/dist/src/registry/index.d.ts +8 -0
  500. package/dist/src/registry/index.d.ts.map +1 -0
  501. package/dist/src/registry/types.d.ts +191 -0
  502. package/dist/src/registry/types.d.ts.map +1 -0
  503. package/dist/src/utils/cn.d.ts +4 -0
  504. package/dist/src/utils/cn.d.ts.map +1 -0
  505. package/dist/src/utils/index.d.ts +3 -0
  506. package/dist/src/utils/index.d.ts.map +1 -0
  507. package/dist/src/utils/link-provider.d.ts +12 -0
  508. package/dist/src/utils/link-provider.d.ts.map +1 -0
  509. package/dist/src/utils/prop-examples.d.ts +36 -0
  510. package/dist/src/utils/prop-examples.d.ts.map +1 -0
  511. package/dist/styles/kumo-binding.css +190 -0
  512. package/dist/styles/kumo-standalone.css +2 -0
  513. package/dist/styles/kumo.css +55 -0
  514. package/dist/styles/theme-fedramp.css +20 -0
  515. package/dist/styles/theme-kumo.css +186 -0
  516. package/dist/surface-BIC6CXiz.js +21 -0
  517. package/dist/surface-BIC6CXiz.js.map +1 -0
  518. package/dist/switch-D4duMhJ0.js +257 -0
  519. package/dist/switch-D4duMhJ0.js.map +1 -0
  520. package/dist/table-KuvHGpL8.js +153 -0
  521. package/dist/table-KuvHGpL8.js.map +1 -0
  522. package/dist/tabs-lQup-IbT.js +85 -0
  523. package/dist/tabs-lQup-IbT.js.map +1 -0
  524. package/dist/text-BEhqwMfe.js +97 -0
  525. package/dist/text-BEhqwMfe.js.map +1 -0
  526. package/dist/toast-8YyyQuqZ.js +69 -0
  527. package/dist/toast-8YyyQuqZ.js.map +1 -0
  528. package/dist/tooltip-DJWsDTWJ.js +85 -0
  529. package/dist/tooltip-DJWsDTWJ.js.map +1 -0
  530. package/dist/utils.js +10 -0
  531. package/dist/utils.js.map +1 -0
  532. package/dist/vendor-base-ui-DWIDNgE1.js +20446 -0
  533. package/dist/vendor-base-ui-DWIDNgE1.js.map +1 -0
  534. package/dist/vendor-floating-ui-BgbEw62H.js +1286 -0
  535. package/dist/vendor-floating-ui-BgbEw62H.js.map +1 -0
  536. package/dist/vendor-styling-BQbxAbdS.js +2775 -0
  537. package/dist/vendor-styling-BQbxAbdS.js.map +1 -0
  538. package/dist/vendor-utils-DD8jNJwD.js +741 -0
  539. package/dist/vendor-utils-DD8jNJwD.js.map +1 -0
  540. package/package.json +444 -0
  541. package/scripts/component-registry/cache.ts +123 -0
  542. package/scripts/component-registry/discovery.ts +469 -0
  543. package/scripts/component-registry/example-cleanup.ts +168 -0
  544. package/scripts/component-registry/index.test.ts +680 -0
  545. package/scripts/component-registry/index.ts +874 -0
  546. package/scripts/component-registry/markdown-generator.ts +222 -0
  547. package/scripts/component-registry/metadata.ts +643 -0
  548. package/scripts/component-registry/props-filter.ts +310 -0
  549. package/scripts/component-registry/schema-generator.ts +326 -0
  550. package/scripts/component-registry/sub-components.ts +349 -0
  551. package/scripts/component-registry/types.ts +156 -0
  552. package/scripts/component-registry/utils.ts +280 -0
  553. package/scripts/component-registry/variant-parser.ts +261 -0
  554. package/scripts/css-build.ts +55 -0
  555. package/scripts/generate-primitives.ts +178 -0
  556. package/scripts/theme-generator/config.ts +392 -0
  557. package/scripts/theme-generator/generate-css.ts +250 -0
  558. package/scripts/theme-generator/index.ts +159 -0
  559. package/scripts/theme-generator/migrate.ts +560 -0
  560. package/scripts/theme-generator/types.ts +86 -0
@@ -0,0 +1,4022 @@
1
+ # Kumo Component Registry
2
+
3
+ > Auto-generated component metadata for AI/agent consumption.
4
+
5
+ ---
6
+
7
+ ### Badge
8
+
9
+ Badge component
10
+
11
+ **Type:** component
12
+
13
+ **Import:** `import { Badge } from "@cloudflare/kumo";`
14
+
15
+ **Category:** Display
16
+
17
+ **Props:**
18
+
19
+ - `variant`: enum [default: primary]
20
+ - `"primary"`: Default high-emphasis badge for important labels
21
+ - `"secondary"`: Subtle badge for secondary information
22
+ - `"destructive"`: Error or danger state indicator
23
+ - `"outline"`: Bordered badge with transparent background
24
+ - `"beta"`: Indicates beta or experimental features
25
+ - `className`: string
26
+ - `children`: ReactNode
27
+
28
+ **Colors (kumo tokens used):**
29
+
30
+ `bg-kumo-contrast`, `bg-kumo-danger`, `bg-kumo-fill`, `border-kumo-brand`, `border-kumo-fill`, `text-kumo-default`, `text-kumo-inverse`, `text-kumo-link`
31
+
32
+ **Examples:**
33
+
34
+ ```tsx
35
+ <div className="flex flex-wrap items-center gap-2">
36
+ <Badge variant="primary">Primary</Badge>
37
+ <Badge variant="secondary">Secondary</Badge>
38
+ <Badge variant="destructive">Destructive</Badge>
39
+ <Badge variant="outline">Outline</Badge>
40
+ <Badge variant="beta">Beta</Badge>
41
+ </div>
42
+ ```
43
+
44
+ ```tsx
45
+ <Badge variant="primary">Primary</Badge>
46
+ ```
47
+
48
+ ```tsx
49
+ <p className="flex items-center gap-2">
50
+ Workers
51
+ <Badge variant="beta">Beta</Badge>
52
+ </p>
53
+ ```
54
+
55
+
56
+ ---
57
+
58
+ ### Banner
59
+
60
+ Banner component
61
+
62
+ **Type:** component
63
+
64
+ **Import:** `import { Banner } from "@cloudflare/kumo";`
65
+
66
+ **Category:** Feedback
67
+
68
+ **Props:**
69
+
70
+ - `icon`: ReactNode
71
+ - `text`: string
72
+ - `children`: ReactNode
73
+ - `variant`: enum [default: default]
74
+ - `"default"`: Informational banner for general messages
75
+ - `"alert"`: Warning banner for cautionary messages
76
+ - `"error"`: Error banner for critical issues
77
+ - `className`: string
78
+
79
+ **Colors (kumo tokens used):**
80
+
81
+ `bg-kumo-danger`, `bg-kumo-danger-tint`, `bg-kumo-info`, `bg-kumo-info-tint`, `bg-kumo-warning`, `bg-kumo-warning-tint`, `border-kumo-danger`, `border-kumo-info`, `border-kumo-warning`, `text-kumo-danger`, `text-kumo-link`, `text-kumo-warning`
82
+
83
+ **Examples:**
84
+
85
+ ```tsx
86
+ <div className="space-y-3">
87
+ <Banner>This is an informational banner.</Banner>
88
+ <Banner variant="alert">This is an alert banner.</Banner>
89
+ <Banner variant="error">This is an error banner.</Banner>
90
+ </div>
91
+ ```
92
+
93
+ ```tsx
94
+ <Banner>This is an informational banner.</Banner>
95
+ ```
96
+
97
+ ```tsx
98
+ <Banner variant="alert">Your session will expire soon.</Banner>
99
+ ```
100
+
101
+ ```tsx
102
+ <Banner icon={<WarningCircle />} variant="alert">
103
+ Review your billing information.
104
+ </Banner>
105
+ ```
106
+
107
+ ```tsx
108
+ <Banner icon={<Info />}>
109
+ <Text DANGEROUS_className="text-inherit">
110
+ This banner supports <strong>custom content</strong> with Text.
111
+ </Text>
112
+ </Banner>
113
+ ```
114
+
115
+
116
+ ---
117
+
118
+ ### Breadcrumbs
119
+
120
+ Breadcrumbs component
121
+
122
+ **Type:** component
123
+
124
+ **Import:** `import { Breadcrumbs } from "@cloudflare/kumo";`
125
+
126
+ **Category:** Display
127
+
128
+ **Props:**
129
+
130
+ - `size`: enum [default: base]
131
+ - `"sm"`: Compact breadcrumbs for dense UIs
132
+ - `"base"`: Default breadcrumbs size
133
+ - `children`: ReactNode
134
+ - `className`: string
135
+
136
+ **Colors (kumo tokens used):**
137
+
138
+ `text-kumo-inactive`, `text-kumo-subtle`, `text-kumo-success`
139
+
140
+ **Sub-Components:**
141
+
142
+ This is a compound component. Use these sub-components:
143
+
144
+ #### Breadcrumbs.Link
145
+
146
+ Link sub-component
147
+
148
+ Props:
149
+ - `href`: string (required)
150
+ - `icon`: React.ReactNode
151
+
152
+ #### Breadcrumbs.Current
153
+
154
+ Current sub-component
155
+
156
+ Props:
157
+ - `loading`: boolean
158
+ - `icon`: React.ReactNode
159
+
160
+ #### Breadcrumbs.Separator
161
+
162
+ Separator sub-component
163
+
164
+ #### Breadcrumbs.Clipboard
165
+
166
+ Clipboard sub-component
167
+
168
+ Props:
169
+ - `text`: string (required)
170
+
171
+
172
+ **Examples:**
173
+
174
+ ```tsx
175
+ <Breadcrumbs>
176
+ <Breadcrumbs.Link href="#">Home</Breadcrumbs.Link>
177
+ <Breadcrumbs.Separator />
178
+ <Breadcrumbs.Link href="#">Docs</Breadcrumbs.Link>
179
+ <Breadcrumbs.Separator />
180
+ <Breadcrumbs.Current>Breadcrumbs</Breadcrumbs.Current>
181
+ </Breadcrumbs>
182
+ ```
183
+
184
+ ```tsx
185
+ <Breadcrumbs>
186
+ <Breadcrumbs.Link href="#" icon={<House size={16} />}>
187
+ Home
188
+ </Breadcrumbs.Link>
189
+ <Breadcrumbs.Separator />
190
+ <Breadcrumbs.Link href="#">Projects</Breadcrumbs.Link>
191
+ <Breadcrumbs.Separator />
192
+ <Breadcrumbs.Current>Current Project</Breadcrumbs.Current>
193
+ </Breadcrumbs>
194
+ ```
195
+
196
+ ```tsx
197
+ <Breadcrumbs>
198
+ <Breadcrumbs.Current icon={<House size={16} />}>
199
+ Worker Analytics
200
+ </Breadcrumbs.Current>
201
+ </Breadcrumbs>
202
+ ```
203
+
204
+ ```tsx
205
+ <Breadcrumbs>
206
+ <Breadcrumbs.Link href="#">Home</Breadcrumbs.Link>
207
+ <Breadcrumbs.Separator />
208
+ <Breadcrumbs.Current>Breadcrumbs</Breadcrumbs.Current>
209
+ <Breadcrumbs.Clipboard text="#" />
210
+ </Breadcrumbs>
211
+ ```
212
+
213
+
214
+ ---
215
+
216
+ ### Button
217
+
218
+ Button component
219
+
220
+ **Type:** component
221
+
222
+ **Import:** `import { Button } from "@cloudflare/kumo";`
223
+
224
+ **Category:** Action
225
+
226
+ **Props:**
227
+
228
+ - `children`: ReactNode
229
+ - `className`: string
230
+ - `icon`: ReactNode
231
+ - `loading`: boolean
232
+ - `shape`: enum [default: base]
233
+ - `"base"`: Default rectangular button shape
234
+ - `"square"`: Square button for icon-only actions
235
+ - `"circle"`: Circular button for icon-only actions
236
+ - `size`: enum [default: base]
237
+ - `"xs"`: Extra small button for compact UIs
238
+ - `"sm"`: Small button for secondary actions
239
+ - `"base"`: Default button size
240
+ - `"lg"`: Large button for primary CTAs
241
+ - `variant`: enum [default: secondary]
242
+ - `"primary"`: High-emphasis button for primary actions
243
+ - `"secondary"`: Default button style for most actions
244
+ - `"ghost"`: Minimal button with no background
245
+ - `"destructive"`: Danger button for destructive actions like delete
246
+ - `"secondary-destructive"`: Secondary button with destructive text for less prominent dangerous actions
247
+ - `"outline"`: Bordered button with transparent background
248
+
249
+ **State Classes:**
250
+ - `"primary"`:
251
+ - `hover`: `hover:bg-kumo-brand-hover`
252
+ - `focus`: `focus:bg-kumo-brand-hover`
253
+ - `disabled`: `disabled:bg-kumo-brand/50`
254
+ - `"secondary"`:
255
+ - `not-disabled`: `not-disabled:hover:border-secondary! not-disabled:hover:bg-kumo-control`
256
+ - `disabled`: `disabled:bg-kumo-control/50 disabled:!text-kumo-default/70`
257
+ - `data-state`: `data-[state=open]:bg-kumo-control`
258
+ - `"ghost"`:
259
+ - `hover`: `hover:bg-kumo-tint`
260
+ - `"destructive"`:
261
+ - `hover`: `hover:bg-kumo-danger/70`
262
+ - `"secondary-destructive"`:
263
+ - `not-disabled`: `not-disabled:hover:border-secondary! not-disabled:hover:bg-kumo-control`
264
+ - `disabled`: `disabled:bg-kumo-control/50 disabled:!text-kumo-danger/70`
265
+ - `data-state`: `data-[state=open]:bg-kumo-control`
266
+ - `id`: string
267
+ - `lang`: string
268
+ - `title`: string
269
+ - `disabled`: boolean
270
+ - `name`: string
271
+ - `type`: enum
272
+ - `value`: string | string[] | number
273
+
274
+ **Colors (kumo tokens used):**
275
+
276
+ `bg-kumo-base`, `bg-kumo-brand`, `bg-kumo-brand-hover`, `bg-kumo-control`, `bg-kumo-danger`, `bg-kumo-tint`, `ring-kumo-line`, `ring-kumo-ring`, `text-kumo-danger`, `text-kumo-default`, `text-kumo-subtle`
277
+
278
+ **Examples:**
279
+
280
+ ```tsx
281
+ <div className="flex flex-wrap items-center gap-2">
282
+ <Button variant="secondary">Button</Button>
283
+ <Button variant="secondary" shape="square" icon={PlusIcon} />
284
+ </div>
285
+ ```
286
+
287
+ ```tsx
288
+ <Button variant="primary">Primary</Button>
289
+ ```
290
+
291
+ ```tsx
292
+ <div className="flex flex-wrap items-center gap-3">
293
+ <Button size="xs" variant="secondary">
294
+ Extra Small
295
+ </Button>
296
+ <Button size="sm" variant="secondary">
297
+ Small
298
+ </Button>
299
+ <Button size="base" variant="secondary">
300
+ Base
301
+ </Button>
302
+ <Button size="lg" variant="secondary">
303
+ Large
304
+ </Button>
305
+ </div>
306
+ ```
307
+
308
+ ```tsx
309
+ <Button variant="secondary" icon={PlusIcon}>
310
+ Create Worker
311
+ </Button>
312
+ ```
313
+
314
+ ```tsx
315
+ <div className="flex flex-wrap items-center gap-3">
316
+ <Button variant="secondary" shape="square" icon={PlusIcon} />
317
+ <Button variant="secondary" shape="circle" icon={PlusIcon} />
318
+ </div>
319
+ ```
320
+
321
+
322
+ ---
323
+
324
+ ### Checkbox
325
+
326
+ Checkbox component
327
+
328
+ **Type:** component
329
+
330
+ **Import:** `import { Checkbox } from "@cloudflare/kumo";`
331
+
332
+ **Category:** Input
333
+
334
+ **Props:**
335
+
336
+ - `variant`: enum [default: default]
337
+ - `"default"`: Default checkbox appearance
338
+ - `"error"`: Error state for validation failures
339
+
340
+ **State Classes:**
341
+ - `"default"`:
342
+ - `focus`: `[&:focus-within>span]:ring-kumo-ring`
343
+ - `hover`: `[&:hover>span]:ring-kumo-ring`
344
+ - `label`: ReactNode
345
+ Label content for the checkbox (enables built-in Field wrapper) - can be a string or any React node
346
+ - `labelTooltip`: ReactNode
347
+ Tooltip content to display next to the label via an info icon
348
+ - `controlFirst`: boolean
349
+ When true (default), checkbox appears before label. When false, label appears before checkbox.
350
+ - `checked`: boolean
351
+ Whether the checkbox is checked (controlled)
352
+ - `indeterminate`: boolean
353
+ Whether the checkbox is in indeterminate state
354
+ - `disabled`: boolean
355
+ Whether the checkbox is disabled
356
+ - `name`: string
357
+ Name for form submission
358
+ - `required`: boolean
359
+ Whether the field is required
360
+ - `className`: string
361
+ Additional class name
362
+ - `onValueChange`: (checked: boolean) => void
363
+ Callback when checkbox value changes
364
+
365
+ **Colors (kumo tokens used):**
366
+
367
+ `bg-kumo-base`, `bg-kumo-contrast`, `border-kumo-line`, `ring-kumo-danger`, `ring-kumo-line`, `ring-kumo-ring`, `text-kumo-danger`, `text-kumo-default`, `text-kumo-inverse`, `text-kumo-subtle`
368
+
369
+ **Styling:**
370
+
371
+ - **Dimensions:** `h-4 w-4`
372
+ - **Border Radius:** `rounded-sm`
373
+ - **Base Tokens:** `bg-kumo-base`, `ring-kumo-line`
374
+ - **States:**
375
+ - `checked`: `bg-kumo-contrast`, `text-kumo-inverse`
376
+ - `indeterminate`: `bg-kumo-contrast`, `text-kumo-inverse`
377
+ - `error`: `ring-kumo-danger`
378
+ - `hover`: `ring-kumo-ring`
379
+ - `focus`: `ring-kumo-ring`
380
+ - `disabled`: `opacity-50`, `cursor-not-allowed`
381
+ - **Icons:**
382
+ - `ph-check` (checked) size 12
383
+ - `ph-minus` (indeterminate) size 12
384
+
385
+ **Sub-Components:**
386
+
387
+ This is a compound component. Use these sub-components:
388
+
389
+ #### Checkbox.Item
390
+
391
+ Item sub-component
392
+
393
+ #### Checkbox.Group
394
+
395
+ Group sub-component
396
+
397
+ Props:
398
+ - `legend`: string (required)
399
+ - `children`: ReactNode (required)
400
+ - `error`: string
401
+ - `description`: ReactNode
402
+ - `value`: string[]
403
+ - `allValues`: string[]
404
+ - `disabled`: boolean
405
+ - `controlFirst`: boolean
406
+ - `className`: string
407
+
408
+
409
+ **Examples:**
410
+
411
+ ```tsx
412
+ <Checkbox
413
+ label="Accept terms and conditions"
414
+ checked={checked}
415
+ onCheckedChange={setChecked}
416
+ />
417
+ ```
418
+
419
+ ```tsx
420
+ <Checkbox
421
+ label="Select all"
422
+ indeterminate={indeterminate}
423
+ onCheckedChange={setIndeterminate}
424
+ />
425
+ ```
426
+
427
+ ```tsx
428
+ <Checkbox
429
+ label="Remember me"
430
+ controlFirst={false}
431
+ checked={checked}
432
+ onCheckedChange={setChecked}
433
+ />
434
+ ```
435
+
436
+ ```tsx
437
+ <Checkbox label="Disabled option" disabled />
438
+ ```
439
+
440
+ ```tsx
441
+ <Checkbox label="Invalid option" variant="error" />
442
+ ```
443
+
444
+ ```tsx
445
+ <Checkbox.Group
446
+ legend="Email preferences"
447
+ description="Choose how you'd like to receive updates"
448
+ value={preferences}
449
+ onValueChange={setPreferences}
450
+ >
451
+ <Checkbox.Item value="email" label="Email notifications" />
452
+ <Checkbox.Item value="sms" label="SMS notifications" />
453
+ <Checkbox.Item value="push" label="Push notifications" />
454
+ </Checkbox.Group>
455
+ ```
456
+
457
+ ```tsx
458
+ <Checkbox.Group
459
+ legend="Required preferences"
460
+ error="Please select at least one notification method"
461
+ value={[]}
462
+ onValueChange={() => {}}
463
+ >
464
+ <Checkbox.Item value="email" label="Email" variant="error" />
465
+ <Checkbox.Item value="sms" label="SMS" variant="error" />
466
+ </Checkbox.Group>
467
+ ```
468
+
469
+
470
+ ---
471
+
472
+ ### ClipboardText
473
+
474
+ ClipboardText component
475
+
476
+ **Type:** component
477
+
478
+ **Import:** `import { ClipboardText } from "@cloudflare/kumo";`
479
+
480
+ **Category:** Action
481
+
482
+ **Props:**
483
+
484
+ - `size`: enum [default: lg]
485
+ - `"sm"`: Small clipboard text for compact UIs
486
+ - `"base"`: Default clipboard text size
487
+ - `"lg"`: Large clipboard text for prominent display
488
+ - `text`: string (required)
489
+ The text to display and copy to clipboard
490
+ - `className`: string
491
+ Additional CSS classes
492
+
493
+ **Colors (kumo tokens used):**
494
+
495
+ `bg-kumo-base`, `border-kumo-line`
496
+
497
+ **Styling:**
498
+
499
+ - **Base Tokens:** `bg-kumo-base`, `text-kumo-default`, `ring-kumo-line`, `border-kumo-fill`
500
+ - **States:**
501
+ - `input`: `bg-kumo-control`, `text-kumo-default`, `ring-kumo-line`
502
+ - `text`: `bg-kumo-base`, `font-mono`
503
+ - `button`: `border-kumo-fill`
504
+ - **Icons:**
505
+ - `ph-clipboard` (default) size 16
506
+ - `ph-check` (copied) size 16
507
+ - **Input Styles:**
508
+ - Base: `bg-kumo-control text-kumo-default ring ring-kumo-line`
509
+ - Sizes:
510
+ - `xs`: `h-5 gap-1 rounded-sm px-1.5 text-xs`
511
+ - `sm`: `h-6.5 gap-1 rounded-md px-2 text-xs`
512
+ - `base`: `h-9 gap-1.5 rounded-lg px-3 text-base`
513
+ - `lg`: `h-10 gap-2 rounded-lg px-4 text-base`
514
+ - **Size Variants:**
515
+ - `sm`:
516
+ - Height: 26px
517
+ - Classes: `text-xs`
518
+ - Button Size: `sm`
519
+ - Dimensions:
520
+ - paddingX: 8
521
+ - gap: 1
522
+ - borderRadius: 6
523
+ - fontSize: 12
524
+ - `base`:
525
+ - Height: 36px
526
+ - Classes: `text-sm`
527
+ - Button Size: `base`
528
+ - Dimensions:
529
+ - paddingX: 12
530
+ - gap: 6
531
+ - borderRadius: 8
532
+ - fontSize: 14
533
+ - `lg`:
534
+ - Height: 40px
535
+ - Classes: `text-sm`
536
+ - Button Size: `lg`
537
+ - Dimensions:
538
+ - paddingX: 16
539
+ - gap: 8
540
+ - borderRadius: 8
541
+ - fontSize: 14
542
+
543
+ **Examples:**
544
+
545
+ ```tsx
546
+ <ClipboardText text="0c239dd2" />
547
+ ```
548
+
549
+
550
+ ---
551
+
552
+ ### Code
553
+
554
+ Code component
555
+
556
+ **Type:** component
557
+
558
+ **Import:** `import { Code } from "@cloudflare/kumo";`
559
+
560
+ **Category:** Display
561
+
562
+ **Props:**
563
+
564
+ - `lang`: enum [default: ts]
565
+ - `"ts"`: TypeScript code
566
+ - `"tsx"`: TypeScript JSX code
567
+ - `"jsonc"`: JSON with comments
568
+ - `"bash"`: Shell/Bash commands
569
+ - `"css"`: CSS styles
570
+ - `code`: string (required)
571
+ The code content to display
572
+ - `values`: Record<string, { value: string; highlight?: boolean }>
573
+ Template values for interpolation
574
+ - `className`: string
575
+ Additional CSS classes
576
+
577
+ **Colors (kumo tokens used):**
578
+
579
+ `bg-kumo-base`, `border-kumo-fill`, `text-kumo-strong`
580
+
581
+ **Styling:**
582
+
583
+ - **Dimensions:** `[object Object]`
584
+ - **Base Tokens:** `text-kumo-strong`
585
+
586
+ **Sub-Components:**
587
+
588
+ This is a compound component. Use these sub-components:
589
+
590
+ #### Code.Block
591
+
592
+ Block sub-component
593
+
594
+ Props:
595
+ - `code`: string (required)
596
+ - `lang`: CodeLang
597
+
598
+
599
+ **Examples:**
600
+
601
+ ```tsx
602
+ <CodeBlock
603
+ lang="tsx"
604
+ code={`const greeting = "Hello, World!";
605
+ console.log(greeting);`}
606
+ />
607
+ ```
608
+
609
+ ```tsx
610
+ <Code
611
+ lang="bash"
612
+ code="export API_KEY={{apiKey}}"
613
+ values={{
614
+ apiKey: { value: "sk_live_123", highlight: true },
615
+ }}
616
+ />
617
+ ```
618
+
619
+
620
+ ---
621
+
622
+ ### Collapsible
623
+
624
+ 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
625
+
626
+ **Type:** component
627
+
628
+ **Import:** `import { Collapsible } from "@cloudflare/kumo";`
629
+
630
+ **Category:** Display
631
+
632
+ **Props:**
633
+
634
+ - `children`: ReactNode
635
+ - `label`: string (required)
636
+ Text label displayed in the trigger button
637
+ - `open`: boolean
638
+ Whether the collapsible content is visible
639
+ - `className`: string
640
+ Additional CSS classes for the content panel
641
+ - `onOpenChange`: (open: boolean) => void
642
+ Callback when collapsed state changes
643
+
644
+ **Colors (kumo tokens used):**
645
+
646
+ `border-kumo-fill`, `text-kumo-link`
647
+
648
+ **Examples:**
649
+
650
+ ```tsx
651
+ <div className="w-full">
652
+ <Collapsible label="What is Kumo?" open={isOpen} onOpenChange={setIsOpen}>
653
+ Kumo is Cloudflare's new design system.
654
+ </Collapsible>
655
+ </div>
656
+ ```
657
+
658
+ ```tsx
659
+ <div className="w-full space-y-2">
660
+ <Collapsible label="What is Kumo?" open={open1} onOpenChange={setOpen1}>
661
+ Kumo is Cloudflare's new design system.
662
+ </Collapsible>
663
+ <Collapsible
664
+ label="How do I use it?"
665
+ open={open2}
666
+ onOpenChange={setOpen2}
667
+ >
668
+ Install the components and import them into your project.
669
+ </Collapsible>
670
+ <Collapsible
671
+ label="Is it open source?"
672
+ open={open3}
673
+ onOpenChange={setOpen3}
674
+ >
675
+ Check the repository for license information.
676
+ </Collapsible>
677
+ </div>
678
+ ```
679
+
680
+
681
+ ---
682
+
683
+ ### Combobox
684
+
685
+ Combobox component
686
+
687
+ **Type:** component
688
+
689
+ **Import:** `import { Combobox } from "@cloudflare/kumo";`
690
+
691
+ **Category:** Input
692
+
693
+ **Props:**
694
+
695
+ - `inputSide`: enum [default: right]
696
+ - `"right"`: Input positioned inline to the right of chips
697
+ - `"top"`: Input positioned above chips
698
+ - `items`: T[] (required)
699
+ Array of items to display in the dropdown
700
+ - `value`: T | T[]
701
+ Currently selected value(s)
702
+ - `children`: ReactNode
703
+ Combobox content (trigger, content, items)
704
+ - `className`: string
705
+ Additional CSS classes
706
+ - `label`: ReactNode
707
+ Label content for the combobox (enables Field wrapper) - can be a string or any React node
708
+ - `required`: boolean
709
+ Whether the combobox is required
710
+ - `labelTooltip`: ReactNode
711
+ Tooltip content to display next to the label via an info icon
712
+ - `description`: ReactNode
713
+ Helper text displayed below the combobox
714
+ - `error`: string | object
715
+ Error message or validation error object
716
+ - `onValueChange`: (value: T | T[]) => void
717
+ Callback when selection changes
718
+ - `multiple`: boolean
719
+ Allow multiple selections
720
+ - `isItemEqualToValue`: (item: T, value: T) => boolean
721
+ Custom equality function for comparing items
722
+
723
+ **Colors (kumo tokens used):**
724
+
725
+ `bg-kumo-control`, `bg-kumo-fill-hover`, `bg-kumo-overlay`, `fill-kumo-ring`, `ring-kumo-line`, `text-kumo-default`, `text-kumo-subtle`
726
+
727
+ **Sub-Components:**
728
+
729
+ This is a compound component. Use these sub-components:
730
+
731
+ #### Combobox.Content
732
+
733
+ Content sub-component
734
+
735
+ Props:
736
+ - `className`: string
737
+ - `align`: ComboboxBase.Positioner.Props["align"]
738
+ - `alignOffset`: ComboboxBase.Positioner.Props["alignOffset"]
739
+ - `side`: ComboboxBase.Positioner.Props["side"]
740
+ - `sideOffset`: ComboboxBase.Positioner.Props["sideOffset"]
741
+
742
+ #### Combobox.TriggerValue
743
+
744
+ TriggerValue sub-component
745
+
746
+ #### Combobox.TriggerInput
747
+
748
+ TriggerInput sub-component
749
+
750
+ #### Combobox.TriggerMultipleWithInput
751
+
752
+ TriggerMultipleWithInput sub-component
753
+
754
+ #### Combobox.Chip
755
+
756
+ Chip sub-component
757
+
758
+ #### Combobox.Item
759
+
760
+ Item sub-component
761
+
762
+ #### Combobox.Input
763
+
764
+ Input sub-component
765
+
766
+ #### Combobox.Empty
767
+
768
+ Empty sub-component
769
+
770
+ #### Combobox.GroupLabel
771
+
772
+ GroupLabel sub-component
773
+
774
+ #### Combobox.Group
775
+
776
+ Group sub-component
777
+
778
+ #### Combobox.List
779
+
780
+ A container for combobox items. Supports render prop for custom item rendering. Renders a `<div>` element.
781
+
782
+ Props:
783
+ - `children`: ReactNode | ((item: T, index: number) => ReactNode) - Items to render, or a function that receives each item and returns a node
784
+
785
+ Usage:
786
+ ```tsx
787
+ <Combobox.List>
788
+ {(item) => <Combobox.Item value={item}>{item.label}</Combobox.Item>}
789
+ </Combobox.List>
790
+ ```
791
+
792
+ #### Combobox.Collection
793
+
794
+ Renders filtered list items. Use when you need more control over item rendering.
795
+
796
+ Props:
797
+ - `children`: (item: T, index: number) => ReactNode (required) - Function that receives each filtered item and returns a node
798
+
799
+ Usage:
800
+ ```tsx
801
+ <Combobox.Collection>
802
+ {(item, index) => (
803
+ <Combobox.Item key={index} value={item}>
804
+ {item.label}
805
+ </Combobox.Item>
806
+ )}
807
+ </Combobox.Collection>
808
+ ```
809
+
810
+
811
+ **Examples:**
812
+
813
+ ```tsx
814
+ <Combobox
815
+ value={value}
816
+ onValueChange={(v) => setValue(v as string | null)}
817
+ items={fruits}
818
+ >
819
+ <Combobox.TriggerInput placeholder="Please select" />
820
+ <Combobox.Content>
821
+ <Combobox.Empty />
822
+ <Combobox.List>
823
+ {(item: string) => (
824
+ <Combobox.Item key={item} value={item}>
825
+ {item}
826
+ </Combobox.Item>
827
+ )}
828
+ </Combobox.List>
829
+ </Combobox.Content>
830
+ </Combobox>
831
+ ```
832
+
833
+ ```tsx
834
+ <Combobox
835
+ value={value}
836
+ onValueChange={(v) => setValue(v as Language)}
837
+ items={languages}
838
+ >
839
+ <Combobox.TriggerValue className="w-[200px]" />
840
+ <Combobox.Content>
841
+ <Combobox.Input placeholder="Search languages" />
842
+ <Combobox.Empty />
843
+ <Combobox.List>
844
+ {(item: Language) => (
845
+ <Combobox.Item key={item.value} value={item}>
846
+ {item.emoji} {item.label}
847
+ </Combobox.Item>
848
+ )}
849
+ </Combobox.List>
850
+ </Combobox.Content>
851
+ </Combobox>
852
+ ```
853
+
854
+ ```tsx
855
+ <Combobox
856
+ value={value}
857
+ onValueChange={(v) => setValue(v as ServerLocation | null)}
858
+ items={servers}
859
+ >
860
+ <Combobox.TriggerInput
861
+ className="w-[200px]"
862
+ placeholder="Select server"
863
+ />
864
+ <Combobox.Content>
865
+ <Combobox.Empty />
866
+ <Combobox.List>
867
+ {(group: ServerLocationGroup) => (
868
+ <Combobox.Group key={group.value} items={group.items}>
869
+ <Combobox.GroupLabel>{group.value}</Combobox.GroupLabel>
870
+ <Combobox.Collection>
871
+ {(item: ServerLocation) => (
872
+ <Combobox.Item key={item.value} value={item}>
873
+ {item.label}
874
+ </Combobox.Item>
875
+ )}
876
+ </Combobox.Collection>
877
+ </Combobox.Group>
878
+ )}
879
+ </Combobox.List>
880
+ </Combobox.Content>
881
+ </Combobox>
882
+ ```
883
+
884
+ ```tsx
885
+ <div className="flex gap-2">
886
+ <Combobox
887
+ value={value}
888
+ onValueChange={setValue}
889
+ items={bots}
890
+ isItemEqualToValue={(bot: BotItem, selected: BotItem) =>
891
+ bot.value === selected.value
892
+ }
893
+ multiple
894
+ >
895
+ <Combobox.TriggerMultipleWithInput
896
+ className="w-[400px]"
897
+ placeholder="Select bots"
898
+ renderItem={(selected: BotItem) => (
899
+ <Combobox.Chip key={selected.value}>{selected.label}</Combobox.Chip>
900
+ )}
901
+ inputSide="right"
902
+ />
903
+ <Combobox.Content className="max-h-[200px] min-w-auto overflow-y-auto">
904
+ <Combobox.Empty />
905
+ <Combobox.List>
906
+ {(item: BotItem) => (
907
+ <Combobox.Item key={item.value} value={item}>
908
+ <div className="flex gap-2">
909
+ <Text>{item.label}</Text>
910
+ <Text variant="secondary">{item.author}</Text>
911
+ </div>
912
+ </Combobox.Item>
913
+ )}
914
+ </Combobox.List>
915
+ </Combobox.Content>
916
+ </Combobox>
917
+ <Button variant="primary">Submit</Button>
918
+ </div>
919
+ ```
920
+
921
+ ```tsx
922
+ <div className="w-80">
923
+ <Combobox
924
+ items={databases}
925
+ value={value}
926
+ onValueChange={setValue}
927
+ label="Database"
928
+ description="Select your preferred database"
929
+ >
930
+ <Combobox.TriggerInput placeholder="Select database" />
931
+ <Combobox.Content>
932
+ <Combobox.Empty />
933
+ <Combobox.List>
934
+ {(item: DatabaseItem) => (
935
+ <Combobox.Item key={item.value} value={item}>
936
+ {item.label}
937
+ </Combobox.Item>
938
+ )}
939
+ </Combobox.List>
940
+ </Combobox.Content>
941
+ </Combobox>
942
+ </div>
943
+ ```
944
+
945
+ ```tsx
946
+ <div className="w-80">
947
+ <Combobox
948
+ items={databases}
949
+ value={value}
950
+ onValueChange={setValue}
951
+ label="Database"
952
+ error={{ message: "Please select a database", match: true }}
953
+ >
954
+ <Combobox.TriggerInput placeholder="Select database" />
955
+ <Combobox.Content>
956
+ <Combobox.Empty />
957
+ <Combobox.List>
958
+ {(item: DatabaseItem) => (
959
+ <Combobox.Item key={item.value} value={item}>
960
+ {item.label}
961
+ </Combobox.Item>
962
+ )}
963
+ </Combobox.List>
964
+ </Combobox.Content>
965
+ </Combobox>
966
+ </div>
967
+ ```
968
+
969
+
970
+ ---
971
+
972
+ ### CommandPalette
973
+
974
+ CommandPalette component
975
+
976
+ **Type:** component
977
+
978
+ **Import:** `import { CommandPalette } from "@cloudflare/kumo";`
979
+
980
+ **Category:** Navigation
981
+
982
+ **Props:**
983
+
984
+ - `open`: boolean (required)
985
+ Whether the dialog is open
986
+ - `children`: ReactNode
987
+ Child content - typically one or more Panel components
988
+
989
+ **Colors (kumo tokens used):**
990
+
991
+ `bg-kumo-base`, `bg-kumo-elevated`, `bg-kumo-overlay`, `bg-kumo-warning`, `ring-kumo-line`, `text-kumo-default`, `text-kumo-strong`, `text-kumo-subtle`
992
+
993
+ **Examples:**
994
+
995
+ ```tsx
996
+ <div className="flex flex-col items-start gap-4">
997
+ <Button onClick={() => setOpen(true)}>Open Command Palette</Button>
998
+ {selectedItem && (
999
+ <p className="text-sm text-kumo-subtle">
1000
+ Last selected:{" "}
1001
+ <span className="text-kumo-default">{selectedItem}</span>
1002
+ </p>
1003
+ )}
1004
+
1005
+ <CommandPalette.Root
1006
+ open={open}
1007
+ onOpenChange={setOpen}
1008
+ items={sampleGroups}
1009
+ value={search}
1010
+ onValueChange={setSearch}
1011
+ itemToStringValue={(group) => group.label}
1012
+ onSelect={(item, { newTab }) => {
1013
+ console.log("Selected:", item.title, newTab ? "(new tab)" : "");
1014
+ handleSelect(item);
1015
+ }}
1016
+ getSelectableItems={getSelectableItems}
1017
+ >
1018
+ <CommandPalette.Input placeholder="Type a command or search..." />
1019
+ <CommandPalette.List>
1020
+ <CommandPalette.Results>
1021
+ {(group: CommandGroup) => (
1022
+ <CommandPalette.Group key={group.id}>
1023
+ <CommandPalette.GroupLabel>
1024
+ {group.label}
1025
+ </CommandPalette.GroupLabel>
1026
+ <CommandPalette.Items>
1027
+ {(item: CommandItem) => (
1028
+ <CommandPalette.Item
1029
+ key={item.id}
1030
+ value={item}
1031
+ onClick={() => handleSelect(item)}
1032
+ >
1033
+ <span className="flex items-center gap-3">
1034
+ {item.icon && (
1035
+ <span className="text-kumo-subtle">{item.icon}</span>
1036
+ )}
1037
+ <span>{item.title}</span>
1038
+ </span>
1039
+ </CommandPalette.Item>
1040
+ )}
1041
+ </CommandPalette.Items>
1042
+ </CommandPalette.Group>
1043
+ )}
1044
+ </CommandPalette.Results>
1045
+ <CommandPalette.Empty>No commands found</CommandPalette.Empty>
1046
+ </CommandPalette.List>
1047
+ <CommandPalette.Footer>
1048
+ <span className="flex items-center gap-2">
1049
+ <kbd className="rounded border border-kumo-line bg-kumo-base px-1.5 py-0.5 text-[10px]">
1050
+ ↑↓
1051
+ </kbd>
1052
+ <span>Navigate</span>
1053
+ </span>
1054
+ <span className="flex items-center gap-2">
1055
+ <kbd className="rounded border border-kumo-line bg-kumo-base px-1.5 py-0.5 text-[10px]">
1056
+
1057
+ </kbd>
1058
+ <span>Select</span>
1059
+ </span>
1060
+ </CommandPalette.Footer>
1061
+ </CommandPalette.Root>
1062
+ </div>
1063
+ ```
1064
+
1065
+ ```tsx
1066
+ <div>
1067
+ <Button onClick={() => setOpen(true)}>Open Simple Palette</Button>
1068
+
1069
+ <CommandPalette.Root
1070
+ open={open}
1071
+ onOpenChange={setOpen}
1072
+ items={simpleItems}
1073
+ value={search}
1074
+ onValueChange={setSearch}
1075
+ itemToStringValue={(item) => item.title}
1076
+ onSelect={(item) => {
1077
+ console.log("Selected:", item.title);
1078
+ setOpen(false);
1079
+ }}
1080
+ getSelectableItems={(items) => items}
1081
+ >
1082
+ <CommandPalette.Input placeholder="Search actions..." />
1083
+ <CommandPalette.List>
1084
+ <CommandPalette.Results>
1085
+ {(item: SimpleItem) => (
1086
+ <CommandPalette.Item
1087
+ key={item.id}
1088
+ value={item}
1089
+ onClick={() => {
1090
+ console.log("Clicked:", item.title);
1091
+ setOpen(false);
1092
+ }}
1093
+ >
1094
+ {item.title}
1095
+ </CommandPalette.Item>
1096
+ )}
1097
+ </CommandPalette.Results>
1098
+ <CommandPalette.Empty>No actions found</CommandPalette.Empty>
1099
+ </CommandPalette.List>
1100
+ </CommandPalette.Root>
1101
+ </div>
1102
+ ```
1103
+
1104
+ ```tsx
1105
+ <div>
1106
+ <Button onClick={handleOpen}>Open with Loading</Button>
1107
+
1108
+ <CommandPalette.Root
1109
+ open={open}
1110
+ onOpenChange={setOpen}
1111
+ items={loading ? [] : sampleGroups}
1112
+ value={search}
1113
+ onValueChange={setSearch}
1114
+ itemToStringValue={(group) => group.label}
1115
+ getSelectableItems={getSelectableItems}
1116
+ >
1117
+ <CommandPalette.Input placeholder="Search..." />
1118
+ <CommandPalette.List>
1119
+ {loading ? (
1120
+ <CommandPalette.Loading />
1121
+ ) : (
1122
+ <>
1123
+ <CommandPalette.Results>
1124
+ {(group: CommandGroup) => (
1125
+ <CommandPalette.Group key={group.id}>
1126
+ <CommandPalette.GroupLabel>
1127
+ {group.label}
1128
+ </CommandPalette.GroupLabel>
1129
+ <CommandPalette.Items>
1130
+ {(item: CommandItem) => (
1131
+ <CommandPalette.Item
1132
+ key={item.id}
1133
+ value={item}
1134
+ onClick={() => setOpen(false)}
1135
+ >
1136
+ <span className="flex items-center gap-3">
1137
+ {item.icon && (
1138
+ <span className="text-kumo-subtle">
1139
+ {item.icon}
1140
+ </span>
1141
+ )}
1142
+ <span>{item.title}</span>
1143
+ </span>
1144
+ </CommandPalette.Item>
1145
+ )}
1146
+ </CommandPalette.Items>
1147
+ </CommandPalette.Group>
1148
+ )}
1149
+ </CommandPalette.Results>
1150
+ <CommandPalette.Empty>No results found</CommandPalette.Empty>
1151
+ </>
1152
+ )}
1153
+ </CommandPalette.List>
1154
+ </CommandPalette.Root>
1155
+ </div>
1156
+ ```
1157
+
1158
+ ```tsx
1159
+ <div>
1160
+ <Button onClick={() => setOpen(true)}>Open with ResultItem</Button>
1161
+
1162
+ <CommandPalette.Root
1163
+ open={open}
1164
+ onOpenChange={setOpen}
1165
+ items={searchResults}
1166
+ value={search}
1167
+ onValueChange={setSearch}
1168
+ itemToStringValue={(item) => item.title}
1169
+ getSelectableItems={(items) => items}
1170
+ >
1171
+ <CommandPalette.Input placeholder="Search documentation..." />
1172
+ <CommandPalette.List>
1173
+ <CommandPalette.Results>
1174
+ {(item: SearchResult) => (
1175
+ <CommandPalette.ResultItem
1176
+ key={item.id}
1177
+ value={item}
1178
+ title={item.title}
1179
+ breadcrumbs={item.breadcrumbs}
1180
+ icon={item.icon}
1181
+ onClick={() => {
1182
+ console.log("Navigate to:", item.title);
1183
+ setOpen(false);
1184
+ }}
1185
+ />
1186
+ )}
1187
+ </CommandPalette.Results>
1188
+ <CommandPalette.Empty>No pages found</CommandPalette.Empty>
1189
+ </CommandPalette.List>
1190
+ <CommandPalette.Footer>
1191
+ <span className="flex items-center gap-2">
1192
+ <kbd className="rounded border border-kumo-line bg-kumo-base px-1.5 py-0.5 text-[10px]">
1193
+ ↑↓
1194
+ </kbd>
1195
+ <span>Navigate</span>
1196
+ </span>
1197
+ <span className="flex items-center gap-2">
1198
+ <kbd className="rounded border border-kumo-line bg-kumo-base px-1.5 py-0.5 text-[10px]">
1199
+ ⌘↵
1200
+ </kbd>
1201
+ <span>Open in new tab</span>
1202
+ </span>
1203
+ </CommandPalette.Footer>
1204
+ </CommandPalette.Root>
1205
+ </div>
1206
+ ```
1207
+
1208
+
1209
+ ---
1210
+
1211
+ ### DateRangePicker
1212
+
1213
+ DateRangePicker component
1214
+
1215
+ **Type:** component
1216
+
1217
+ **Import:** `import { DateRangePicker } from "@cloudflare/kumo";`
1218
+
1219
+ **Category:** Input
1220
+
1221
+ **Props:**
1222
+
1223
+ - `size`: enum [default: base]
1224
+ - `"sm"`: Compact calendar for tight spaces
1225
+ - `"base"`: Default calendar size
1226
+ - `"lg"`: Large calendar for prominent date selection
1227
+ - `variant`: enum [default: default]
1228
+ - `"default"`: Default calendar appearance
1229
+ - `"subtle"`: Subtle calendar with minimal background
1230
+ - `timezone`: string
1231
+ Display timezone (display only)
1232
+ - `className`: string
1233
+ Additional CSS classes
1234
+ - `onStartDateChange`: (date: Date | null) => void
1235
+ Callback when start date changes
1236
+ - `onEndDateChange`: (date: Date | null) => void
1237
+ Callback when end date changes
1238
+
1239
+ **Colors (kumo tokens used):**
1240
+
1241
+ `bg-kumo-base`, `bg-kumo-contrast`, `bg-kumo-fill`, `bg-kumo-interact`, `bg-kumo-overlay`, `text-kumo-default`, `text-kumo-inverse`, `text-kumo-strong`, `text-kumo-subtle`
1242
+
1243
+ **Styling:**
1244
+
1245
+ - **Size Variants:**
1246
+ - `sm`:
1247
+ - Classes: `p-3 gap-2`
1248
+ - Dimensions:
1249
+ - calendarWidth: 168
1250
+ - cellHeight: 22
1251
+ - cellWidth: 24
1252
+ - textSize: 12
1253
+ - iconSize: 14
1254
+ - padding: 12
1255
+ - gap: 8
1256
+ - `base`:
1257
+ - Classes: `p-4 gap-2.5`
1258
+ - Dimensions:
1259
+ - calendarWidth: 196
1260
+ - cellHeight: 26
1261
+ - cellWidth: 28
1262
+ - textSize: 14
1263
+ - iconSize: 16
1264
+ - padding: 16
1265
+ - gap: 10
1266
+ - `lg`:
1267
+ - Classes: `p-5 gap-3`
1268
+ - Dimensions:
1269
+ - calendarWidth: 252
1270
+ - cellHeight: 32
1271
+ - cellWidth: 36
1272
+ - textSize: 16
1273
+ - iconSize: 18
1274
+ - padding: 20
1275
+ - gap: 12
1276
+
1277
+ **Examples:**
1278
+
1279
+ ```tsx
1280
+ <div className="flex flex-col gap-4">
1281
+ <DateRangePicker
1282
+ onStartDateChange={setStartDate}
1283
+ onEndDateChange={setEndDate}
1284
+ />
1285
+ <div className="text-sm text-kumo-subtle">
1286
+ {startDate && endDate ? (
1287
+ <span>
1288
+ Selected: {startDate.toLocaleDateString()} -{" "}
1289
+ {endDate.toLocaleDateString()}
1290
+ </span>
1291
+ ) : startDate ? (
1292
+ <span>Start: {startDate.toLocaleDateString()} (select end date)</span>
1293
+ ) : (
1294
+ <span>Select a date range</span>
1295
+ )}
1296
+ </div>
1297
+ </div>
1298
+ ```
1299
+
1300
+ ```tsx
1301
+ <div className="flex flex-col gap-8">
1302
+ <div>
1303
+ <p className="mb-2 text-sm font-medium text-kumo-default">Small</p>
1304
+ <DateRangePicker
1305
+ size="sm"
1306
+ onStartDateChange={() => {}}
1307
+ onEndDateChange={() => {}}
1308
+ />
1309
+ </div>
1310
+ <div>
1311
+ <p className="mb-2 text-sm font-medium text-kumo-default">
1312
+ Base (default)
1313
+ </p>
1314
+ <DateRangePicker
1315
+ size="base"
1316
+ onStartDateChange={() => {}}
1317
+ onEndDateChange={() => {}}
1318
+ />
1319
+ </div>
1320
+ <div>
1321
+ <p className="mb-2 text-sm font-medium text-kumo-default">Large</p>
1322
+ <DateRangePicker
1323
+ size="lg"
1324
+ onStartDateChange={() => {}}
1325
+ onEndDateChange={() => {}}
1326
+ />
1327
+ </div>
1328
+ </div>
1329
+ ```
1330
+
1331
+ ```tsx
1332
+ <div className="flex flex-col gap-8">
1333
+ <div>
1334
+ <p className="mb-2 text-sm font-medium text-kumo-default">
1335
+ Default variant
1336
+ </p>
1337
+ <DateRangePicker
1338
+ variant="default"
1339
+ onStartDateChange={() => {}}
1340
+ onEndDateChange={() => {}}
1341
+ />
1342
+ </div>
1343
+ <div>
1344
+ <p className="mb-2 text-sm font-medium text-kumo-default">
1345
+ Subtle variant
1346
+ </p>
1347
+ <DateRangePicker
1348
+ variant="subtle"
1349
+ onStartDateChange={() => {}}
1350
+ onEndDateChange={() => {}}
1351
+ />
1352
+ </div>
1353
+ </div>
1354
+ ```
1355
+
1356
+ ```tsx
1357
+ <DateRangePicker
1358
+ timezone="London, UK (GMT+0)"
1359
+ onStartDateChange={() => {}}
1360
+ onEndDateChange={() => {}}
1361
+ />
1362
+ ```
1363
+
1364
+
1365
+ ---
1366
+
1367
+ ### Dialog
1368
+
1369
+ Dialog component
1370
+
1371
+ **Type:** component
1372
+
1373
+ **Import:** `import { Dialog } from "@cloudflare/kumo";`
1374
+
1375
+ **Category:** Overlay
1376
+
1377
+ **Props:**
1378
+
1379
+ - `className`: string
1380
+ - `children`: ReactNode
1381
+ - `size`: enum [default: base]
1382
+ - `"base"`: Default dialog width
1383
+ - `"sm"`: Small dialog for simple confirmations
1384
+ - `"lg"`: Large dialog for complex content
1385
+ - `"xl"`: Extra large dialog for detailed views
1386
+
1387
+ **Colors (kumo tokens used):**
1388
+
1389
+ `bg-kumo-base`, `bg-kumo-overlay`, `text-kumo-default`
1390
+
1391
+ **Styling:**
1392
+
1393
+ - **Dimensions:** `[object Object]`
1394
+
1395
+ **Sub-Components:**
1396
+
1397
+ This is a compound component. Use these sub-components:
1398
+
1399
+ #### Dialog.Root
1400
+
1401
+ Controls the open state of the dialog. Doesn't render its own HTML element.
1402
+
1403
+ Props:
1404
+ - `open`: boolean - Whether the dialog is currently open (controlled mode)
1405
+ - `defaultOpen`: boolean [default: false] - Whether the dialog is initially open (uncontrolled mode)
1406
+ - `onOpenChange`: (open: boolean, event: Event) => void - Callback fired when the dialog opens or closes
1407
+ - `modal`: boolean | 'trap-focus' [default: true] - Whether the dialog is modal. When true, focus is trapped and page scroll is locked
1408
+ - `dismissible`: boolean [default: true] - Whether clicking outside closes the dialog
1409
+
1410
+ Usage:
1411
+ ```tsx
1412
+ <Dialog.Root open={isOpen} onOpenChange={setIsOpen}>
1413
+ ```
1414
+ ```tsx
1415
+ <Dialog.Root defaultOpen={false}>
1416
+ ```
1417
+
1418
+ #### Dialog.Trigger
1419
+
1420
+ A button that opens the dialog when clicked. Renders a `<button>` element.
1421
+
1422
+ Props:
1423
+ - `render`: ReactElement | ((props, state) => ReactElement) - Custom element to render instead of the default button
1424
+ - `disabled`: boolean - Whether the trigger is disabled
1425
+
1426
+ Usage:
1427
+ ```tsx
1428
+ <Dialog.Trigger render={<Button>Open</Button>} />
1429
+ ```
1430
+ ```tsx
1431
+ <Dialog.Trigger>Open Dialog</Dialog.Trigger>
1432
+ ```
1433
+
1434
+ #### Dialog.Title
1435
+
1436
+ A heading that labels the dialog for accessibility. Renders a `<h2>` element.
1437
+
1438
+ Props:
1439
+ - `render`: ReactElement | ((props, state) => ReactElement) - Custom element to render instead of the default h2
1440
+
1441
+ Usage:
1442
+ ```tsx
1443
+ <Dialog.Title>Confirm Action</Dialog.Title>
1444
+ ```
1445
+ ```tsx
1446
+ <Dialog.Title render={<h3 />}>Custom Heading</Dialog.Title>
1447
+ ```
1448
+
1449
+ #### Dialog.Description
1450
+
1451
+ A paragraph providing additional context about the dialog. Renders a `<p>` element.
1452
+
1453
+ Props:
1454
+ - `render`: ReactElement | ((props, state) => ReactElement) - Custom element to render instead of the default p
1455
+
1456
+ Usage:
1457
+ ```tsx
1458
+ <Dialog.Description>Are you sure you want to proceed?</Dialog.Description>
1459
+ ```
1460
+
1461
+ #### Dialog.Close
1462
+
1463
+ A button that closes the dialog when clicked. Renders a `<button>` element.
1464
+
1465
+ Props:
1466
+ - `render`: ReactElement | ((props, state) => ReactElement) - Custom element to render instead of the default button
1467
+ - `disabled`: boolean - Whether the close button is disabled
1468
+
1469
+ Usage:
1470
+ ```tsx
1471
+ <Dialog.Close render={<Button>Cancel</Button>} />
1472
+ ```
1473
+ ```tsx
1474
+ <Dialog.Close>×</Dialog.Close>
1475
+ ```
1476
+
1477
+
1478
+ **Examples:**
1479
+
1480
+ ```tsx
1481
+ <Dialog.Root>
1482
+ <Dialog.Trigger render={(p) => <Button {...p}>Click me</Button>} />
1483
+ <Dialog className="p-8">
1484
+ <div className="mb-4 flex items-start justify-between gap-4">
1485
+ <Dialog.Title className="text-2xl font-semibold">
1486
+ Modal Title
1487
+ </Dialog.Title>
1488
+ <Dialog.Close
1489
+ aria-label="Close"
1490
+ render={(props) => (
1491
+ <Button
1492
+ {...props}
1493
+ variant="secondary"
1494
+ shape="square"
1495
+ icon={<X />}
1496
+ />
1497
+ )}
1498
+ />
1499
+ </div>
1500
+ <Dialog.Description className="text-kumo-subtle">
1501
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
1502
+ eiusmod tempor incididunt ut labore et dolore magna aliqua.
1503
+ </Dialog.Description>
1504
+ </Dialog>
1505
+ </Dialog.Root>
1506
+ ```
1507
+
1508
+ ```tsx
1509
+ <Dialog.Root>
1510
+ <Dialog.Trigger render={(p) => <Button {...p}>Delete</Button>} />
1511
+ <Dialog className="p-8">
1512
+ <div className="mb-4 flex items-start justify-between gap-4">
1513
+ <Dialog.Title className="text-2xl font-semibold">
1514
+ Modal Title
1515
+ </Dialog.Title>
1516
+ <Dialog.Close
1517
+ aria-label="Close"
1518
+ render={(props) => (
1519
+ <Button
1520
+ {...props}
1521
+ variant="secondary"
1522
+ shape="square"
1523
+ icon={<X />}
1524
+ />
1525
+ )}
1526
+ />
1527
+ </div>
1528
+ <Dialog.Description className="text-kumo-subtle">
1529
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
1530
+ eiusmod tempor incididunt ut labore et dolore magna aliqua.
1531
+ </Dialog.Description>
1532
+ <div className="mt-8 flex justify-end gap-2">
1533
+ <Button variant="secondary">Cancel</Button>
1534
+ <Dialog.Close
1535
+ render={(props) => (
1536
+ <Button variant="destructive" {...props}>
1537
+ Delete
1538
+ </Button>
1539
+ )}
1540
+ />
1541
+ </div>
1542
+ </Dialog>
1543
+ </Dialog.Root>
1544
+ ```
1545
+
1546
+
1547
+ ---
1548
+
1549
+ ### DropdownMenu
1550
+
1551
+ DropdownMenu component
1552
+
1553
+ **Type:** component
1554
+
1555
+ **Import:** `import { DropdownMenu } from "@cloudflare/kumo";`
1556
+
1557
+ **Category:** Overlay
1558
+
1559
+ **Props:**
1560
+
1561
+ - `variant`: enum [default: default]
1562
+ - `"default"`: Default dropdown item appearance
1563
+ - `"danger"`: Destructive action item
1564
+
1565
+ **Colors (kumo tokens used):**
1566
+
1567
+ `bg-kumo-control`, `bg-kumo-danger`, `bg-kumo-line`, `bg-kumo-overlay`, `bg-kumo-tint`, `ring-kumo-line`, `text-kumo-danger`, `text-kumo-default`
1568
+
1569
+ **Sub-Components:**
1570
+
1571
+ This is a compound component. Use these sub-components:
1572
+
1573
+ #### DropdownMenu.Trigger
1574
+
1575
+ Trigger sub-component
1576
+
1577
+ #### DropdownMenu.Portal
1578
+
1579
+ Portal sub-component (wraps DropdownMenuPrimitive)
1580
+
1581
+ #### DropdownMenu.Sub
1582
+
1583
+ Sub sub-component (wraps DropdownMenuPrimitive)
1584
+
1585
+ #### DropdownMenu.SubTrigger
1586
+
1587
+ SubTrigger sub-component
1588
+
1589
+ #### DropdownMenu.SubContent
1590
+
1591
+ SubContent sub-component
1592
+
1593
+ #### DropdownMenu.Content
1594
+
1595
+ Content sub-component
1596
+
1597
+ #### DropdownMenu.Item
1598
+
1599
+ Item sub-component
1600
+
1601
+ #### DropdownMenu.CheckboxItem
1602
+
1603
+ CheckboxItem sub-component
1604
+
1605
+ #### DropdownMenu.RadioGroup
1606
+
1607
+ RadioGroup sub-component (wraps DropdownMenuPrimitive)
1608
+
1609
+ #### DropdownMenu.RadioItem
1610
+
1611
+ RadioItem sub-component
1612
+
1613
+ #### DropdownMenu.RadioItemIndicator
1614
+
1615
+ RadioItemIndicator sub-component
1616
+
1617
+ #### DropdownMenu.Label
1618
+
1619
+ Label sub-component
1620
+
1621
+ #### DropdownMenu.Separator
1622
+
1623
+ Separator sub-component
1624
+
1625
+ #### DropdownMenu.Shortcut
1626
+
1627
+ Shortcut sub-component
1628
+
1629
+ #### DropdownMenu.Group
1630
+
1631
+ Group sub-component (wraps DropdownMenuPrimitive)
1632
+
1633
+
1634
+ ---
1635
+
1636
+ ### Empty
1637
+
1638
+ Empty component
1639
+
1640
+ **Type:** component
1641
+
1642
+ **Import:** `import { Empty } from "@cloudflare/kumo";`
1643
+
1644
+ **Category:** Display
1645
+
1646
+ **Props:**
1647
+
1648
+ - `size`: enum [default: base]
1649
+ - `"sm"`: Compact empty state for smaller containers
1650
+ - `"base"`: Default empty state size
1651
+ - `"lg"`: Large empty state for prominent placement
1652
+ - `icon`: ReactNode
1653
+ - `title`: string (required)
1654
+ - `description`: string
1655
+ - `commandLine`: string
1656
+ - `contents`: ReactNode
1657
+ - `className`: string
1658
+
1659
+ **Colors (kumo tokens used):**
1660
+
1661
+ `bg-kumo-control`, `bg-kumo-overlay`, `border-kumo-fill`, `border-kumo-interact`, `text-kumo-brand`, `text-kumo-default`, `text-kumo-inactive`, `text-kumo-strong`, `text-kumo-success`
1662
+
1663
+ **Examples:**
1664
+
1665
+ ```tsx
1666
+ <Empty
1667
+ icon={<PackageIcon size={48} />}
1668
+ title="No packages found"
1669
+ description="Get started by installing your first package."
1670
+ commandLine="npm install @cloudflare/kumo"
1671
+ contents={
1672
+ <div className="flex items-center gap-2">
1673
+ <Button icon={<CodeIcon />}>See examples</Button>
1674
+ <Button icon={<GlobeIcon />} variant="primary">
1675
+ View documentation
1676
+ </Button>
1677
+ </div>
1678
+ }
1679
+ />
1680
+ ```
1681
+
1682
+ ```tsx
1683
+ <div className="flex flex-col gap-8">
1684
+ <div>
1685
+ <p className="mb-2 text-sm text-kumo-subtle">Small</p>
1686
+ <Empty
1687
+ size="sm"
1688
+ icon={<Database size={32} className="text-kumo-inactive" />}
1689
+ title="No data available"
1690
+ description="There is no data to display."
1691
+ />
1692
+ </div>
1693
+ <div>
1694
+ <p className="mb-2 text-sm text-kumo-subtle">Base</p>
1695
+ <Empty
1696
+ size="base"
1697
+ icon={<Database size={48} className="text-kumo-inactive" />}
1698
+ title="No data available"
1699
+ description="There is no data to display."
1700
+ />
1701
+ </div>
1702
+ <div>
1703
+ <p className="mb-2 text-sm text-kumo-subtle">Large</p>
1704
+ <Empty
1705
+ size="lg"
1706
+ icon={<Database size={64} className="text-kumo-inactive" />}
1707
+ title="No data available"
1708
+ description="There is no data to display."
1709
+ />
1710
+ </div>
1711
+ </div>
1712
+ ```
1713
+
1714
+ ```tsx
1715
+ <Empty
1716
+ icon={<FolderOpen size={48} className="text-kumo-inactive" />}
1717
+ title="No projects found"
1718
+ description="Get started by creating your first project using the command below."
1719
+ commandLine="npm create kumo-project"
1720
+ />
1721
+ ```
1722
+
1723
+ ```tsx
1724
+ <Empty
1725
+ icon={<CloudSlash size={48} className="text-kumo-inactive" />}
1726
+ title="No connection"
1727
+ description="Unable to connect to the server. Please check your connection and try again."
1728
+ contents={
1729
+ <div className="flex gap-2">
1730
+ <Button variant="primary">Retry</Button>
1731
+ <Button variant="secondary">Go Back</Button>
1732
+ </div>
1733
+ }
1734
+ />
1735
+ ```
1736
+
1737
+ ```tsx
1738
+ <Empty title="Nothing here" />
1739
+ ```
1740
+
1741
+ ```tsx
1742
+ <Empty
1743
+ title="No results found"
1744
+ description="Try adjusting your search or filter to find what you're looking for."
1745
+ />
1746
+ ```
1747
+
1748
+
1749
+ ---
1750
+
1751
+ ### Field
1752
+
1753
+ Field component
1754
+
1755
+ **Type:** component
1756
+
1757
+ **Import:** `import { Field } from "@cloudflare/kumo";`
1758
+
1759
+ **Category:** Input
1760
+
1761
+ **Props:**
1762
+
1763
+ - `controlFirst`: boolean
1764
+ When true, places the control (checkbox/switch) before the label visually. When false (default), places the label before the control. Used to support different layout patterns (e.g., iOS-style toggles on the right).
1765
+ - `children`: ReactNode
1766
+ - `label`: ReactNode
1767
+ The label content - can be a string or any React node
1768
+ - `required`: boolean
1769
+ When explicitly false, shows gray "(optional)" text after the label. When true or undefined, no indicator is shown.
1770
+ - `labelTooltip`: ReactNode
1771
+ Tooltip content to display next to the label via an info icon
1772
+ - `error`: object
1773
+ - `description`: ReactNode
1774
+
1775
+ **Colors (kumo tokens used):**
1776
+
1777
+ `text-kumo-danger`, `text-kumo-default`, `text-kumo-subtle`
1778
+
1779
+ ---
1780
+
1781
+ ### Grid
1782
+
1783
+ Grid component
1784
+
1785
+ **Type:** component
1786
+
1787
+ **Import:** `import { Grid } from "@cloudflare/kumo";`
1788
+
1789
+ **Category:** Layout
1790
+
1791
+ **Props:**
1792
+
1793
+ - `children`: ReactNode
1794
+ Child node(s) that can be nested inside component
1795
+ - `className`: string
1796
+ CSS class names that can be appended to the component
1797
+ - `id`: string
1798
+ - `lang`: string
1799
+ - `title`: string
1800
+ - `mobileDivider`: boolean
1801
+ Show dividers between grid items on mobile (only works with 4up variant)
1802
+ - `gap`: enum [default: base]
1803
+ - `"none"`: No gap between grid items
1804
+ - `"sm"`: Small gap between grid items
1805
+ - `"base"`: Default responsive gap between grid items
1806
+ - `"lg"`: Large gap between grid items
1807
+ - `variant`: enum
1808
+ - `"2up"`: Grid items stack on small screens, display side-by-side on medium screens and up
1809
+ - `"side-by-side"`: Grid items always displayed side-by-side
1810
+ - `"2-1"`: Two-thirds / one-third split (66%/33%) on medium screens and up
1811
+ - `"1-2"`: One-third / two-thirds split (33%/66%) on medium screens and up
1812
+ - `"1-3up"`: Grid items stack on small screens, expand to 3 across on large screens
1813
+ - `"3up"`: Grid items stack on small screens, 2 across on medium, 3 across on large
1814
+ - `"4up"`: Grid items stack on small screens, progressively increase columns at larger breakpoints
1815
+ - `"6up"`: Grid items start at 2 across, expand to 6 across on XL
1816
+ - `"1-2-4up"`: Grid items stack on small screens, 2 across on medium, 4 across on large
1817
+
1818
+ **Colors (kumo tokens used):**
1819
+
1820
+ `border-kumo-line`
1821
+
1822
+ **Examples:**
1823
+
1824
+ ```tsx
1825
+ <Grid variant="2up" gap="base">
1826
+ <GridItem>
1827
+ <Surface className="rounded-lg p-4">
1828
+ <Text bold>Item 1</Text>
1829
+ <div className="mt-1">
1830
+ <Text variant="secondary">First grid item</Text>
1831
+ </div>
1832
+ </Surface>
1833
+ </GridItem>
1834
+ <GridItem>
1835
+ <Surface className="rounded-lg p-4">
1836
+ <Text bold>Item 2</Text>
1837
+ <div className="mt-1">
1838
+ <Text variant="secondary">Second grid item</Text>
1839
+ </div>
1840
+ </Surface>
1841
+ </GridItem>
1842
+ </Grid>
1843
+ ```
1844
+
1845
+ ```tsx
1846
+ <div className="flex flex-col gap-8">
1847
+ <div>
1848
+ <p className="mb-2 text-kumo-subtle">variant="2up"</p>
1849
+ <Grid variant="2up" gap="sm">
1850
+ <GridItem>
1851
+ <Surface className="rounded-lg p-4 text-center">
1852
+ <Text>1</Text>
1853
+ </Surface>
1854
+ </GridItem>
1855
+ <GridItem>
1856
+ <Surface className="rounded-lg p-4 text-center">
1857
+ <Text>2</Text>
1858
+ </Surface>
1859
+ </GridItem>
1860
+ </Grid>
1861
+ </div>
1862
+
1863
+ <div>
1864
+ <p className="mb-2 text-kumo-subtle">variant="3up"</p>
1865
+ <Grid variant="3up" gap="sm">
1866
+ <GridItem>
1867
+ <Surface className="rounded-lg p-4 text-center">
1868
+ <Text>1</Text>
1869
+ </Surface>
1870
+ </GridItem>
1871
+ <GridItem>
1872
+ <Surface className="rounded-lg p-4 text-center">
1873
+ <Text>2</Text>
1874
+ </Surface>
1875
+ </GridItem>
1876
+ <GridItem>
1877
+ <Surface className="rounded-lg p-4 text-center">
1878
+ <Text>3</Text>
1879
+ </Surface>
1880
+ </GridItem>
1881
+ </Grid>
1882
+ </div>
1883
+
1884
+ <div>
1885
+ <p className="mb-2 text-kumo-subtle">variant="4up"</p>
1886
+ <Grid variant="4up" gap="sm">
1887
+ <GridItem>
1888
+ <Surface className="rounded-lg p-4 text-center">
1889
+ <Text>1</Text>
1890
+ </Surface>
1891
+ </GridItem>
1892
+ <GridItem>
1893
+ <Surface className="rounded-lg p-4 text-center">
1894
+ <Text>2</Text>
1895
+ </Surface>
1896
+ </GridItem>
1897
+ <GridItem>
1898
+ <Surface className="rounded-lg p-4 text-center">
1899
+ <Text>3</Text>
1900
+ </Surface>
1901
+ </GridItem>
1902
+ <GridItem>
1903
+ <Surface className="rounded-lg p-4 text-center">
1904
+ <Text>4</Text>
1905
+ </Surface>
1906
+ </GridItem>
1907
+ </Grid>
1908
+ </div>
1909
+ </div>
1910
+ ```
1911
+
1912
+ ```tsx
1913
+ <div className="flex flex-col gap-8">
1914
+ <div>
1915
+ <p className="mb-2 text-kumo-subtle">variant="2-1" (66% / 33%)</p>
1916
+ <Grid variant="2-1" gap="sm">
1917
+ <GridItem>
1918
+ <Surface className="rounded-lg p-4">
1919
+ <Text bold>Main Content</Text>
1920
+ <div className="mt-1">
1921
+ <Text variant="secondary">Two-thirds width</Text>
1922
+ </div>
1923
+ </Surface>
1924
+ </GridItem>
1925
+ <GridItem>
1926
+ <Surface className="rounded-lg p-4">
1927
+ <Text bold>Sidebar</Text>
1928
+ <div className="mt-1">
1929
+ <Text variant="secondary">One-third width</Text>
1930
+ </div>
1931
+ </Surface>
1932
+ </GridItem>
1933
+ </Grid>
1934
+ </div>
1935
+
1936
+ <div>
1937
+ <p className="mb-2 text-kumo-subtle">variant="1-2" (33% / 66%)</p>
1938
+ <Grid variant="1-2" gap="sm">
1939
+ <GridItem>
1940
+ <Surface className="rounded-lg p-4">
1941
+ <Text bold>Sidebar</Text>
1942
+ <div className="mt-1">
1943
+ <Text variant="secondary">One-third width</Text>
1944
+ </div>
1945
+ </Surface>
1946
+ </GridItem>
1947
+ <GridItem>
1948
+ <Surface className="rounded-lg p-4">
1949
+ <Text bold>Main Content</Text>
1950
+ <div className="mt-1">
1951
+ <Text variant="secondary">Two-thirds width</Text>
1952
+ </div>
1953
+ </Surface>
1954
+ </GridItem>
1955
+ </Grid>
1956
+ </div>
1957
+ </div>
1958
+ ```
1959
+
1960
+ ```tsx
1961
+ <div className="flex flex-col gap-8">
1962
+ <div>
1963
+ <p className="mb-2 text-kumo-subtle">gap="none"</p>
1964
+ <Grid variant="side-by-side" gap="none">
1965
+ <GridItem>
1966
+ <Surface className="rounded-lg p-4 text-center">
1967
+ <Text>1</Text>
1968
+ </Surface>
1969
+ </GridItem>
1970
+ <GridItem>
1971
+ <Surface className="rounded-lg p-4 text-center">
1972
+ <Text>2</Text>
1973
+ </Surface>
1974
+ </GridItem>
1975
+ </Grid>
1976
+ </div>
1977
+
1978
+ <div>
1979
+ <p className="mb-2 text-kumo-subtle">gap="sm"</p>
1980
+ <Grid variant="side-by-side" gap="sm">
1981
+ <GridItem>
1982
+ <Surface className="rounded-lg p-4 text-center">
1983
+ <Text>1</Text>
1984
+ </Surface>
1985
+ </GridItem>
1986
+ <GridItem>
1987
+ <Surface className="rounded-lg p-4 text-center">
1988
+ <Text>2</Text>
1989
+ </Surface>
1990
+ </GridItem>
1991
+ </Grid>
1992
+ </div>
1993
+
1994
+ <div>
1995
+ <p className="mb-2 text-kumo-subtle">
1996
+ gap="base" (default, responsive)
1997
+ </p>
1998
+ <Grid variant="side-by-side" gap="base">
1999
+ <GridItem>
2000
+ <Surface className="rounded-lg p-4 text-center">
2001
+ <Text>1</Text>
2002
+ </Surface>
2003
+ </GridItem>
2004
+ <GridItem>
2005
+ <Surface className="rounded-lg p-4 text-center">
2006
+ <Text>2</Text>
2007
+ </Surface>
2008
+ </GridItem>
2009
+ </Grid>
2010
+ </div>
2011
+
2012
+ <div>
2013
+ <p className="mb-2 text-kumo-subtle">gap="lg"</p>
2014
+ <Grid variant="side-by-side" gap="lg">
2015
+ <GridItem>
2016
+ <Surface className="rounded-lg p-4 text-center">
2017
+ <Text>1</Text>
2018
+ </Surface>
2019
+ </GridItem>
2020
+ <GridItem>
2021
+ <Surface className="rounded-lg p-4 text-center">
2022
+ <Text>2</Text>
2023
+ </Surface>
2024
+ </GridItem>
2025
+ </Grid>
2026
+ </div>
2027
+ </div>
2028
+ ```
2029
+
2030
+ ```tsx
2031
+ <Grid variant="4up" gap="base" mobileDivider>
2032
+ <GridItem>
2033
+ <Surface className="rounded-lg p-4">
2034
+ <Text bold>Item 1</Text>
2035
+ <div className="mt-1">
2036
+ <Text variant="secondary">Has divider on mobile</Text>
2037
+ </div>
2038
+ </Surface>
2039
+ </GridItem>
2040
+ <GridItem>
2041
+ <Surface className="rounded-lg p-4">
2042
+ <Text bold>Item 2</Text>
2043
+ <div className="mt-1">
2044
+ <Text variant="secondary">Has divider on mobile</Text>
2045
+ </div>
2046
+ </Surface>
2047
+ </GridItem>
2048
+ <GridItem>
2049
+ <Surface className="rounded-lg p-4">
2050
+ <Text bold>Item 3</Text>
2051
+ <div className="mt-1">
2052
+ <Text variant="secondary">Has divider on mobile</Text>
2053
+ </div>
2054
+ </Surface>
2055
+ </GridItem>
2056
+ <GridItem>
2057
+ <Surface className="rounded-lg p-4">
2058
+ <Text bold>Item 4</Text>
2059
+ <div className="mt-1">
2060
+ <Text variant="secondary">Has divider on mobile</Text>
2061
+ </div>
2062
+ </Surface>
2063
+ </GridItem>
2064
+ </Grid>
2065
+ ```
2066
+
2067
+
2068
+ ---
2069
+
2070
+ ### Input
2071
+
2072
+ Input component
2073
+
2074
+ **Type:** component
2075
+
2076
+ **Import:** `import { Input } from "@cloudflare/kumo";`
2077
+
2078
+ **Category:** Input
2079
+
2080
+ **Props:**
2081
+
2082
+ - `label`: ReactNode
2083
+ Label content for the input (enables Field wrapper) - can be a string or any React node
2084
+ - `labelTooltip`: ReactNode
2085
+ Tooltip content to display next to the label via an info icon
2086
+ - `description`: ReactNode
2087
+ Helper text displayed below the input
2088
+ - `error`: string | object
2089
+ Error message or validation error object
2090
+ - `size`: enum [default: base]
2091
+ - `"xs"`: Extra small input for compact UIs
2092
+ - `"sm"`: Small input for secondary fields
2093
+ - `"base"`: Default input size
2094
+ - `"lg"`: Large input for prominent fields
2095
+ - `variant`: enum [default: default]
2096
+ - `"default"`: Default input appearance
2097
+ - `"error"`: Error state for validation failures
2098
+
2099
+ **State Classes:**
2100
+ - `"default"`:
2101
+ - `focus`: `focus:ring-kumo-ring`
2102
+ - `"error"`:
2103
+ - `focus`: `focus:ring-kumo-danger`
2104
+
2105
+ **Colors (kumo tokens used):**
2106
+
2107
+ `bg-kumo-control`, `ring-kumo-danger`, `ring-kumo-line`, `ring-kumo-ring`, `text-kumo-default`, `text-kumo-subtle`
2108
+
2109
+ **Styling:**
2110
+
2111
+ - **Dimensions:** `[object Object]`
2112
+
2113
+ **Examples:**
2114
+
2115
+ ```tsx
2116
+ <Input
2117
+ label="Email"
2118
+ placeholder="you@example.com"
2119
+ description="We'll never share your email"
2120
+ />
2121
+ ```
2122
+
2123
+ ```tsx
2124
+ <Input
2125
+ label="Email"
2126
+ placeholder="you@example.com"
2127
+ value="invalid-email"
2128
+ variant="error"
2129
+ error="Please enter a valid email address"
2130
+ />
2131
+ ```
2132
+
2133
+ ```tsx
2134
+ <Input
2135
+ label="Password"
2136
+ type="password"
2137
+ value="short"
2138
+ variant="error"
2139
+ error={{
2140
+ message: "Password must be at least 8 characters",
2141
+ match: "tooShort",
2142
+ }}
2143
+ minLength={8}
2144
+ />
2145
+ ```
2146
+
2147
+ ```tsx
2148
+ <div className="flex flex-col gap-4">
2149
+ <Input size="xs" label="Extra Small" placeholder="Extra small input" />
2150
+ <Input size="sm" label="Small" placeholder="Small input" />
2151
+ <Input label="Base" placeholder="Base input (default)" />
2152
+ <Input size="lg" label="Large" placeholder="Large input" />
2153
+ </div>
2154
+ ```
2155
+
2156
+ ```tsx
2157
+ <Input label="Disabled field" placeholder="Cannot edit" disabled />
2158
+ ```
2159
+
2160
+ ```tsx
2161
+ <div className="flex flex-col gap-4">
2162
+ <Input type="email" label="Email" placeholder="you@example.com" />
2163
+ <Input type="password" label="Password" placeholder="••••••••" />
2164
+ <Input type="number" label="Age" placeholder="18" />
2165
+ <Input type="tel" label="Phone" placeholder="+1 (555) 000-0000" />
2166
+ </div>
2167
+ ```
2168
+
2169
+ ```tsx
2170
+ <Input
2171
+ label="Phone Number"
2172
+ required={false}
2173
+ placeholder="+1 (555) 000-0000"
2174
+ />
2175
+ ```
2176
+
2177
+ ```tsx
2178
+ <Input
2179
+ label="API Key"
2180
+ labelTooltip="Find this in your dashboard under Settings > API Keys"
2181
+ placeholder="sk_live_..."
2182
+ />
2183
+ ```
2184
+
2185
+ ```tsx
2186
+ <Input
2187
+ label={
2188
+ <span>
2189
+ Email for <strong>billing</strong>
2190
+ </span>
2191
+ }
2192
+ required
2193
+ placeholder="billing@company.com"
2194
+ type="email"
2195
+ />
2196
+ ```
2197
+
2198
+
2199
+ ---
2200
+
2201
+ ### Label
2202
+
2203
+ 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
2204
+
2205
+ **Type:** component
2206
+
2207
+ **Import:** `import { Label } from "@cloudflare/kumo";`
2208
+
2209
+ **Category:** Other
2210
+
2211
+ **Props:**
2212
+
2213
+ - `children`: ReactNode
2214
+ The label content - can be a string or any React node
2215
+ - `showOptional`: boolean
2216
+ When true (and required is false), shows gray "(optional)" text after the label
2217
+ - `tooltip`: ReactNode
2218
+ Tooltip content to display next to the label via an info icon
2219
+ - `className`: string
2220
+ Additional CSS classes
2221
+ - `asContent`: boolean
2222
+ When true, only renders the inline content (indicators, tooltip) without the outer span with font styling. Useful when composed inside another label element that already provides the text styling.
2223
+
2224
+ **Colors (kumo tokens used):**
2225
+
2226
+ `text-kumo-default`, `text-kumo-strong`
2227
+
2228
+ **Examples:**
2229
+
2230
+ ```tsx
2231
+ <div className="flex flex-col gap-4">
2232
+ <Label>Default Label</Label>
2233
+ <Label showOptional>Optional Label</Label>
2234
+ <Label tooltip="More information about this field">
2235
+ Label with Tooltip
2236
+ </Label>
2237
+ </div>
2238
+ ```
2239
+
2240
+ ```tsx
2241
+ <Input label="Phone Number" required={false} placeholder="+1 555-0000" />
2242
+ ```
2243
+
2244
+ ```tsx
2245
+ <Input
2246
+ label="API Key"
2247
+ labelTooltip="Find this in your dashboard settings under API > Keys"
2248
+ placeholder="sk_live_..."
2249
+ />
2250
+ ```
2251
+
2252
+ ```tsx
2253
+ <Checkbox
2254
+ label={
2255
+ <span>
2256
+ I agree to the <strong>Terms of Service</strong>
2257
+ </span>
2258
+ }
2259
+ />
2260
+ ```
2261
+
2262
+ ```tsx
2263
+ <div className="flex max-w-md flex-col gap-4">
2264
+ <Input label="Full Name" placeholder="John Doe" />
2265
+ <Input
2266
+ label="Email"
2267
+ labelTooltip="We'll send your receipt here"
2268
+ placeholder="john@example.com"
2269
+ type="email"
2270
+ />
2271
+ <Input label="Company" required={false} placeholder="Acme Inc." />
2272
+ <Select label="Country" hideLabel={false} placeholder="Select a country">
2273
+ <Select.Option value="us">United States</Select.Option>
2274
+ <Select.Option value="uk">United Kingdom</Select.Option>
2275
+ <Select.Option value="ca">Canada</Select.Option>
2276
+ </Select>
2277
+ </div>
2278
+ ```
2279
+
2280
+
2281
+ ---
2282
+
2283
+ ### LayerCard
2284
+
2285
+ LayerCard component
2286
+
2287
+ **Type:** component
2288
+
2289
+ **Import:** `import { LayerCard } from "@cloudflare/kumo";`
2290
+
2291
+ **Category:** Display
2292
+
2293
+ **Props:**
2294
+
2295
+ - `children`: ReactNode
2296
+ - `className`: string
2297
+
2298
+ **Colors (kumo tokens used):**
2299
+
2300
+ `bg-kumo-base`, `bg-kumo-elevated`, `ring-kumo-fill`, `ring-kumo-line`, `text-kumo-strong`
2301
+
2302
+ **Styling:**
2303
+
2304
+
2305
+ **Sub-Components:**
2306
+
2307
+ This is a compound component. Use these sub-components:
2308
+
2309
+ #### LayerCard.Primary
2310
+
2311
+ Primary sub-component
2312
+
2313
+ #### LayerCard.Secondary
2314
+
2315
+ Secondary sub-component
2316
+
2317
+
2318
+ **Examples:**
2319
+
2320
+ ```tsx
2321
+ <LayerCard>
2322
+ <LayerCard.Secondary className="flex items-center justify-between">
2323
+ <div>Next Steps</div>
2324
+ <Button variant="ghost" size="sm" shape="square">
2325
+ <ArrowRightIcon size={16} />
2326
+ </Button>
2327
+ </LayerCard.Secondary>
2328
+
2329
+ <LayerCard.Primary>Get started with Kumo</LayerCard.Primary>
2330
+ </LayerCard>
2331
+ ```
2332
+
2333
+ ```tsx
2334
+ <LayerCard className="w-[250px]">
2335
+ <LayerCard.Secondary>Getting Started</LayerCard.Secondary>
2336
+ <LayerCard.Primary>
2337
+ <p className="text-sm text-kumo-subtle">
2338
+ Quick start guide for new users
2339
+ </p>
2340
+ </LayerCard.Primary>
2341
+ </LayerCard>
2342
+ ```
2343
+
2344
+ ```tsx
2345
+ <div className="flex gap-4">
2346
+ <LayerCard className="w-[200px]">
2347
+ <LayerCard.Secondary>Components</LayerCard.Secondary>
2348
+ <LayerCard.Primary>
2349
+ <p className="text-sm">Browse all components</p>
2350
+ </LayerCard.Primary>
2351
+ </LayerCard>
2352
+ <LayerCard className="w-[200px]">
2353
+ <LayerCard.Secondary>Examples</LayerCard.Secondary>
2354
+ <LayerCard.Primary>
2355
+ <p className="text-sm">View code examples</p>
2356
+ </LayerCard.Primary>
2357
+ </LayerCard>
2358
+ </div>
2359
+ ```
2360
+
2361
+
2362
+ ---
2363
+
2364
+ ### Link
2365
+
2366
+ Link component
2367
+
2368
+ **Type:** component
2369
+
2370
+ **Import:** `import { Link } from "@cloudflare/kumo";`
2371
+
2372
+ **Category:** Other
2373
+
2374
+ **Props:**
2375
+
2376
+ - `variant`: enum [default: inline]
2377
+ - `"inline"`: Inline text link that flows with content
2378
+ - `"current"`: Link that inherits color from parent text
2379
+ - `"plain"`: Link without underline decoration
2380
+
2381
+ **State Classes:**
2382
+ - `"plain"`:
2383
+ - `hover`: `hover:text-primary/70`
2384
+ - `to`: string
2385
+ - `children`: ReactNode
2386
+ - `className`: string
2387
+ - `id`: string
2388
+ - `lang`: string
2389
+ - `title`: string
2390
+ - `download`: unknown
2391
+ - `href`: string
2392
+ - `hrefLang`: string
2393
+ - `media`: string
2394
+ - `ping`: string
2395
+ - `target`: React.HTMLAttributeAnchorTarget
2396
+ - `type`: string
2397
+ - `referrerPolicy`: enum
2398
+ - `render`: ReactNode
2399
+ Allows you to replace the component’s HTML element with a different tag, or compose it with another component.
2400
+
2401
+ Accepts a `ReactElement` or a function that returns the element to render.
2402
+
2403
+ **Sub-Components:**
2404
+
2405
+ This is a compound component. Use these sub-components:
2406
+
2407
+ #### Link.ExternalIcon
2408
+
2409
+ ExternalIcon sub-component
2410
+
2411
+
2412
+ **Examples:**
2413
+
2414
+ ```tsx
2415
+ <div className="grid gap-x-6 gap-y-4 text-base md:grid-cols-3">
2416
+ <Link href="#">Default inline link</Link>
2417
+ <Link href="#" variant="current">
2418
+ Current color link
2419
+ </Link>
2420
+ <Link href="#" variant="plain">
2421
+ Plain inline link
2422
+ </Link>
2423
+ </div>
2424
+ ```
2425
+
2426
+ ```tsx
2427
+ <p className="mx-auto max-w-md text-base leading-relaxed text-kumo-default">
2428
+ This is a paragraph with an <Link href="#">inline link</Link> that flows
2429
+ naturally with the surrounding text. Links maintain proper underline
2430
+ offset for readability.
2431
+ </p>
2432
+ ```
2433
+
2434
+ ```tsx
2435
+ <Link
2436
+ href="https://cloudflare.com"
2437
+ target="_blank"
2438
+ rel="noopener noreferrer"
2439
+ className="text-base"
2440
+ >
2441
+ Visit Cloudflare <Link.ExternalIcon />
2442
+ </Link>
2443
+ ```
2444
+
2445
+ ```tsx
2446
+ <p className="text-base text-kumo-danger">
2447
+ This error message contains a{" "}
2448
+ <Link href="#" variant="current">
2449
+ link
2450
+ </Link>{" "}
2451
+ that inherits the red color from its parent.
2452
+ </p>
2453
+ ```
2454
+
2455
+ ```tsx
2456
+ <div className="flex flex-col gap-x-6 gap-y-4 text-base md:flex-row">
2457
+ <Link render={<CustomRouterLink href="/dashboard" />} variant="inline">
2458
+ Dashboard (via render)
2459
+ </Link>
2460
+ <Link
2461
+ render={
2462
+ <CustomRouterLink
2463
+ href="https://developers.cloudflare.com"
2464
+ target="_blank"
2465
+ rel="noopener noreferrer"
2466
+ />
2467
+ }
2468
+ variant="inline"
2469
+ >
2470
+ Cloudflare Docs <Link.ExternalIcon />
2471
+ </Link>
2472
+ </div>
2473
+ ```
2474
+
2475
+
2476
+ ---
2477
+
2478
+ ### Loader
2479
+
2480
+ Loader component
2481
+
2482
+ **Type:** component
2483
+
2484
+ **Import:** `import { Loader } from "@cloudflare/kumo";`
2485
+
2486
+ **Category:** Feedback
2487
+
2488
+ **Props:**
2489
+
2490
+ - `className`: string
2491
+ - `size`: enum [default: base]
2492
+ - `"sm"`: Small loader for inline use
2493
+ - `"base"`: Default loader size
2494
+ - `"lg"`: Large loader for prominent loading states
2495
+
2496
+ **Examples:**
2497
+
2498
+ ```tsx
2499
+ <div className="flex items-center gap-4">
2500
+ <Loader size="sm" />
2501
+ <Loader size="base" />
2502
+ <Loader size="lg" />
2503
+ </div>
2504
+ ```
2505
+
2506
+ ```tsx
2507
+ <Loader size={24} />
2508
+ ```
2509
+
2510
+
2511
+ ---
2512
+
2513
+ ### MenuBar
2514
+
2515
+ MenuBar component
2516
+
2517
+ **Type:** component
2518
+
2519
+ **Import:** `import { MenuBar } from "@cloudflare/kumo";`
2520
+
2521
+ **Category:** Navigation
2522
+
2523
+ **Props:**
2524
+
2525
+ - `className`: string
2526
+ - `isActive`: number | boolean | string
2527
+ - `options`: MenuOptionProps[] (required)
2528
+ - `optionIds`: boolean
2529
+
2530
+ **Colors (kumo tokens used):**
2531
+
2532
+ `bg-kumo-base`, `bg-kumo-fill`, `border-kumo-fill`
2533
+
2534
+ **Styling:**
2535
+
2536
+
2537
+ **Examples:**
2538
+
2539
+ ```tsx
2540
+ <MenuBar
2541
+ isActive="bold"
2542
+ optionIds
2543
+ options={[
2544
+ {
2545
+ icon: <TextBolderIcon />,
2546
+ id: "bold",
2547
+ tooltip: "Bold",
2548
+ onClick: () => {},
2549
+ },
2550
+ {
2551
+ icon: <TextItalicIcon />,
2552
+ id: "italic",
2553
+ tooltip: "Italic",
2554
+ onClick: () => {},
2555
+ },
2556
+ ]}
2557
+ />
2558
+ ```
2559
+
2560
+
2561
+ ---
2562
+
2563
+ ### Meter
2564
+
2565
+ Meter component
2566
+
2567
+ **Type:** component
2568
+
2569
+ **Import:** `import { Meter } from "@cloudflare/kumo";`
2570
+
2571
+ **Category:** Display
2572
+
2573
+ **Props:**
2574
+
2575
+ - `customValue`: string
2576
+ - `label`: string (required)
2577
+ - `showValue`: boolean
2578
+ - `trackClassName`: string
2579
+ - `indicatorClassName`: string
2580
+ - `value`: number
2581
+ Current value of the meter
2582
+ - `max`: number
2583
+ Maximum value of the meter (default: 100)
2584
+ - `min`: number
2585
+ Minimum value of the meter (default: 0)
2586
+
2587
+ **Colors (kumo tokens used):**
2588
+
2589
+ `bg-kumo-fill`, `text-kumo-default`, `text-kumo-strong`
2590
+
2591
+ **Examples:**
2592
+
2593
+ ```tsx
2594
+ <Meter label="Storage used" value={65} />
2595
+ ```
2596
+
2597
+ ```tsx
2598
+ <Meter label="API requests" value={75} customValue="750 / 1,000" />
2599
+ ```
2600
+
2601
+ ```tsx
2602
+ <Meter label="Progress" value={40} showValue={false} />
2603
+ ```
2604
+
2605
+ ```tsx
2606
+ <Meter
2607
+ label="Upload progress"
2608
+ value={80}
2609
+ indicatorClassName="from-green-500 via-green-500 to-green-500"
2610
+ />
2611
+ ```
2612
+
2613
+
2614
+ ---
2615
+
2616
+ ### Pagination
2617
+
2618
+ Pagination component
2619
+
2620
+ **Type:** component
2621
+
2622
+ **Import:** `import { Pagination } from "@cloudflare/kumo";`
2623
+
2624
+ **Category:** Navigation
2625
+
2626
+ **Props:**
2627
+
2628
+ - `controls`: enum [default: full]
2629
+ - `"full"`: Full pagination controls with first, previous, page input, next, and last buttons
2630
+ - `"simple"`: Simple pagination controls with only previous and next buttons
2631
+ - `setPage`: (page: number) => void (required)
2632
+ Callback when page changes
2633
+ - `page`: number
2634
+ - `perPage`: number
2635
+ - `totalCount`: number
2636
+
2637
+ **Colors (kumo tokens used):**
2638
+
2639
+ `text-kumo-strong`
2640
+
2641
+ **Styling:**
2642
+
2643
+
2644
+ **Examples:**
2645
+
2646
+ ```tsx
2647
+ <Pagination page={page} setPage={setPage} perPage={10} totalCount={100} />
2648
+ ```
2649
+
2650
+ ```tsx
2651
+ <Pagination
2652
+ page={page}
2653
+ setPage={setPage}
2654
+ perPage={10}
2655
+ totalCount={100}
2656
+ controls="simple"
2657
+ />
2658
+ ```
2659
+
2660
+
2661
+ ---
2662
+
2663
+ ### Popover
2664
+
2665
+ Popover component for displaying accessible popup content anchored to a trigger.
2666
+
2667
+ **Type:** component
2668
+
2669
+ **Import:** `import { Popover } from "@cloudflare/kumo";`
2670
+
2671
+ **Category:** Overlay
2672
+
2673
+ **Props:**
2674
+
2675
+ - `side`: enum [default: bottom]
2676
+ - `"top"`: Popover appears above the trigger
2677
+ - `"bottom"`: Popover appears below the trigger
2678
+ - `"left"`: Popover appears to the left of the trigger
2679
+ - `"right"`: Popover appears to the right of the trigger
2680
+
2681
+ **Colors (kumo tokens used):**
2682
+
2683
+ `bg-kumo-base`, `fill-kumo-base`, `fill-kumo-tip-shadow`, `fill-kumo-tip-stroke`, `outline-kumo-fill`, `text-kumo-default`, `text-kumo-subtle`
2684
+
2685
+ **Sub-Components:**
2686
+
2687
+ This is a compound component. Use these sub-components:
2688
+
2689
+ #### Popover.Trigger
2690
+
2691
+ Trigger sub-component
2692
+
2693
+ #### Popover.Content
2694
+
2695
+ Content sub-component
2696
+
2697
+ #### Popover.Title
2698
+
2699
+ Title sub-component
2700
+
2701
+ #### Popover.Description
2702
+
2703
+ Description sub-component
2704
+
2705
+ #### Popover.Close
2706
+
2707
+ Close sub-component
2708
+
2709
+
2710
+ **Examples:**
2711
+
2712
+ ```tsx
2713
+ <Popover>
2714
+ <Popover.Trigger asChild>
2715
+ <Button shape="square" icon={BellIcon} />
2716
+ </Popover.Trigger>
2717
+ <Popover.Content>
2718
+ <Popover.Title>Notifications</Popover.Title>
2719
+ <Popover.Description>
2720
+ You are all caught up. Good job!
2721
+ </Popover.Description>
2722
+ </Popover.Content>
2723
+ </Popover>
2724
+ ```
2725
+
2726
+ ```tsx
2727
+ <Popover>
2728
+ <Popover.Trigger asChild>
2729
+ <Button>Open Popover</Button>
2730
+ </Popover.Trigger>
2731
+ <Popover.Content>
2732
+ <Popover.Title>Popover Title</Popover.Title>
2733
+ <Popover.Description>
2734
+ This is a basic popover with a title and description.
2735
+ </Popover.Description>
2736
+ </Popover.Content>
2737
+ </Popover>
2738
+ ```
2739
+
2740
+ ```tsx
2741
+ <Popover>
2742
+ <Popover.Trigger asChild>
2743
+ <Button>Open Settings</Button>
2744
+ </Popover.Trigger>
2745
+ <Popover.Content>
2746
+ <Popover.Title>Settings</Popover.Title>
2747
+ <Popover.Description>
2748
+ Configure your preferences below.
2749
+ </Popover.Description>
2750
+ <div className="mt-3">
2751
+ <Popover.Close asChild>
2752
+ <Button variant="secondary" size="sm">
2753
+ Close
2754
+ </Button>
2755
+ </Popover.Close>
2756
+ </div>
2757
+ </Popover.Content>
2758
+ </Popover>
2759
+ ```
2760
+
2761
+ ```tsx
2762
+ <div className="flex flex-wrap gap-4">
2763
+ <Popover>
2764
+ <Popover.Trigger asChild>
2765
+ <Button variant="secondary">Bottom</Button>
2766
+ </Popover.Trigger>
2767
+ <Popover.Content side="bottom">
2768
+ <Popover.Title>Bottom</Popover.Title>
2769
+ <Popover.Description>
2770
+ Popover on bottom (default).
2771
+ </Popover.Description>
2772
+ </Popover.Content>
2773
+ </Popover>
2774
+
2775
+ <Popover>
2776
+ <Popover.Trigger asChild>
2777
+ <Button variant="secondary">Top</Button>
2778
+ </Popover.Trigger>
2779
+ <Popover.Content side="top">
2780
+ <Popover.Title>Top</Popover.Title>
2781
+ <Popover.Description>Popover on top.</Popover.Description>
2782
+ </Popover.Content>
2783
+ </Popover>
2784
+
2785
+ <Popover>
2786
+ <Popover.Trigger asChild>
2787
+ <Button variant="secondary">Left</Button>
2788
+ </Popover.Trigger>
2789
+ <Popover.Content side="left">
2790
+ <Popover.Title>Left</Popover.Title>
2791
+ <Popover.Description>Popover on left.</Popover.Description>
2792
+ </Popover.Content>
2793
+ </Popover>
2794
+
2795
+ <Popover>
2796
+ <Popover.Trigger asChild>
2797
+ <Button variant="secondary">Right</Button>
2798
+ </Popover.Trigger>
2799
+ <Popover.Content side="right">
2800
+ <Popover.Title>Right</Popover.Title>
2801
+ <Popover.Description>Popover on right.</Popover.Description>
2802
+ </Popover.Content>
2803
+ </Popover>
2804
+ </div>
2805
+ ```
2806
+
2807
+ ```tsx
2808
+ <Popover>
2809
+ <Popover.Trigger asChild>
2810
+ <Button>User Profile</Button>
2811
+ </Popover.Trigger>
2812
+ <Popover.Content className="w-64">
2813
+ <div className="flex items-center gap-3">
2814
+ <div className="size-10 rounded-full bg-kumo-recessed" />
2815
+ <div>
2816
+ <Popover.Title>Jane Doe</Popover.Title>
2817
+ <p className="text-sm text-kumo-subtle">jane@example.com</p>
2818
+ </div>
2819
+ </div>
2820
+ <div className="mt-3 flex gap-2 border-t border-kumo-line pt-3">
2821
+ <Button variant="secondary" size="sm" className="flex-1">
2822
+ Profile
2823
+ </Button>
2824
+ <Popover.Close asChild>
2825
+ <Button variant="ghost" size="sm" className="flex-1">
2826
+ Sign Out
2827
+ </Button>
2828
+ </Popover.Close>
2829
+ </div>
2830
+ </Popover.Content>
2831
+ </Popover>
2832
+ ```
2833
+
2834
+ ```tsx
2835
+ <Popover>
2836
+ <Popover.Trigger openOnHover delay={200} asChild>
2837
+ <Button variant="secondary">Hover Me</Button>
2838
+ </Popover.Trigger>
2839
+ <Popover.Content>
2840
+ <Popover.Title>Hover Triggered</Popover.Title>
2841
+ <Popover.Description>
2842
+ This popover opens on hover with a 200ms delay. It can still contain
2843
+ interactive content like buttons and links.
2844
+ </Popover.Description>
2845
+ <div className="mt-3">
2846
+ <Popover.Close asChild>
2847
+ <Button variant="secondary" size="sm">
2848
+ Got it
2849
+ </Button>
2850
+ </Popover.Close>
2851
+ </div>
2852
+ </Popover.Content>
2853
+ </Popover>
2854
+ ```
2855
+
2856
+
2857
+ ---
2858
+
2859
+ ### Radio
2860
+
2861
+ Radio component
2862
+
2863
+ **Type:** component
2864
+
2865
+ **Import:** `import { Radio } from "@cloudflare/kumo";`
2866
+
2867
+ **Category:** Input
2868
+
2869
+ **Props:**
2870
+
2871
+ - `legend`: string (required)
2872
+ Legend text for the group (required for accessibility)
2873
+ - `children`: ReactNode
2874
+ Child Radio.Item components
2875
+ - `orientation`: enum
2876
+ Layout direction of the radio items
2877
+ - `error`: string
2878
+ Error message for the group
2879
+ - `description`: ReactNode
2880
+ Helper text for the group
2881
+ - `value`: string
2882
+ Value of the radio that should be selected (controlled)
2883
+ - `disabled`: boolean
2884
+ Whether all radios in the group are disabled
2885
+ - `controlPosition`: enum
2886
+ Position of radio control relative to label: "start" (default) puts radio before label, "end" puts label before radio
2887
+ - `name`: string
2888
+ Form submission name for the radio group
2889
+ - `className`: string
2890
+ Additional CSS classes
2891
+
2892
+ **Colors (kumo tokens used):**
2893
+
2894
+ `bg-kumo-base`, `bg-kumo-contrast`, `border-kumo-line`, `ring-kumo-danger`, `ring-kumo-line`, `ring-kumo-ring`, `text-kumo-danger`, `text-kumo-default`, `text-kumo-subtle`
2895
+
2896
+ **Examples:**
2897
+
2898
+ ```tsx
2899
+ <Radio.Group
2900
+ legend="Notification preference"
2901
+ value={value}
2902
+ onValueChange={setValue}
2903
+ >
2904
+ <Radio.Item label="Email" value="email" />
2905
+ <Radio.Item label="SMS" value="sms" />
2906
+ <Radio.Item label="Push notification" value="push" />
2907
+ </Radio.Group>
2908
+ ```
2909
+
2910
+ ```tsx
2911
+ <Radio.Group
2912
+ legend="Size"
2913
+ orientation="horizontal"
2914
+ value={value}
2915
+ onValueChange={setValue}
2916
+ >
2917
+ <Radio.Item label="Small" value="sm" />
2918
+ <Radio.Item label="Medium" value="md" />
2919
+ <Radio.Item label="Large" value="lg" />
2920
+ </Radio.Group>
2921
+ ```
2922
+
2923
+ ```tsx
2924
+ <Radio.Group
2925
+ legend="Shipping method"
2926
+ description="Choose how you'd like to receive your order"
2927
+ value={value}
2928
+ onValueChange={setValue}
2929
+ >
2930
+ <Radio.Item label="Standard (5-7 days)" value="standard" />
2931
+ <Radio.Item label="Express (2-3 days)" value="express" />
2932
+ <Radio.Item label="Overnight" value="overnight" />
2933
+ </Radio.Group>
2934
+ ```
2935
+
2936
+ ```tsx
2937
+ <Radio.Group
2938
+ legend="Payment method"
2939
+ error="Please select a payment method to continue"
2940
+ >
2941
+ <Radio.Item label="Credit Card" value="card" variant="error" />
2942
+ <Radio.Item label="PayPal" value="paypal" variant="error" />
2943
+ <Radio.Item label="Bank Transfer" value="bank" variant="error" />
2944
+ </Radio.Group>
2945
+ ```
2946
+
2947
+ ```tsx
2948
+ <div className="flex flex-col gap-6">
2949
+ <Radio.Group legend="Disabled group" disabled defaultValue="a">
2950
+ <Radio.Item label="Option A" value="a" />
2951
+ <Radio.Item label="Option B" value="b" />
2952
+ </Radio.Group>
2953
+ <Radio.Group legend="Individual disabled" defaultValue="available">
2954
+ <Radio.Item label="Available" value="available" />
2955
+ <Radio.Item label="Unavailable" value="unavailable" disabled />
2956
+ </Radio.Group>
2957
+ </div>
2958
+ ```
2959
+
2960
+ ```tsx
2961
+ <Radio.Group legend="Preferences" controlPosition="end" defaultValue="a">
2962
+ <Radio.Item label="Label before radio" value="a" />
2963
+ <Radio.Item label="Another option" value="b" />
2964
+ </Radio.Group>
2965
+ ```
2966
+
2967
+
2968
+ ---
2969
+
2970
+ ### Select
2971
+
2972
+ Select component
2973
+
2974
+ **Type:** component
2975
+
2976
+ **Import:** `import { Select } from "@cloudflare/kumo";`
2977
+
2978
+ **Category:** Input
2979
+
2980
+ **Props:**
2981
+
2982
+ - `className`: string
2983
+ Additional CSS classes
2984
+ - `label`: ReactNode
2985
+ Label content for the select (enables Field wrapper) - can be a string or any React node
2986
+ - `hideLabel`: boolean
2987
+ Whether to visually hide the label (still accessible to screen readers)
2988
+ - `placeholder`: string
2989
+ Placeholder text when no value is selected
2990
+ - `loading`: boolean
2991
+ Whether the select is in a loading state
2992
+ - `disabled`: boolean
2993
+ Whether the select is disabled
2994
+ - `required`: boolean
2995
+ Whether the select is required
2996
+ - `labelTooltip`: ReactNode
2997
+ Tooltip content to display next to the label via an info icon
2998
+ - `value`: string
2999
+ The currently selected value
3000
+ - `children`: ReactNode
3001
+ Child elements (Select.Option components)
3002
+ - `description`: ReactNode
3003
+ Helper text displayed below the select
3004
+ - `error`: string | object
3005
+ Error message or validation error object
3006
+ - `onValueChange`: (value: string) => void
3007
+ Callback when selection changes
3008
+ - `defaultValue`: string
3009
+ Initial value for uncontrolled mode
3010
+
3011
+ **Colors (kumo tokens used):**
3012
+
3013
+ `bg-kumo-control`, `bg-kumo-overlay`, `ring-kumo-line`, `ring-kumo-ring`, `text-kumo-default`
3014
+
3015
+ **Styling:**
3016
+
3017
+
3018
+ **Sub-Components:**
3019
+
3020
+ This is a compound component. Use these sub-components:
3021
+
3022
+ #### Select.Option
3023
+
3024
+ Option sub-component
3025
+
3026
+
3027
+ **Examples:**
3028
+
3029
+ ```tsx
3030
+ <Select
3031
+ className="w-[200px]"
3032
+ value={value}
3033
+ onValueChange={(v) => setValue(v ?? "Apple")}
3034
+ placeholder="Please select"
3035
+ >
3036
+ <Select.Option value="Apple">Apple</Select.Option>
3037
+ <Select.Option value="Banana">Banana</Select.Option>
3038
+ <Select.Option value="Cherry">Cherry</Select.Option>
3039
+ </Select>
3040
+ ```
3041
+
3042
+ ```tsx
3043
+ <Select
3044
+ className="w-[200px]"
3045
+ value={value}
3046
+ onValueChange={(v) => setValue(v as string)}
3047
+ items={{
3048
+ bug: "Bug",
3049
+ documentation: "Documentation",
3050
+ feature: "Feature",
3051
+ }}
3052
+ >
3053
+ <Select.Option value="bug">Bug</Select.Option>
3054
+ <Select.Option value="documentation">Documentation</Select.Option>
3055
+ <Select.Option value="feature">Feature</Select.Option>
3056
+ </Select>
3057
+ ```
3058
+
3059
+ ```tsx
3060
+ <Select
3061
+ className="w-[200px]"
3062
+ renderValue={(v) => (
3063
+ <span>
3064
+ {v.emoji} {v.label}
3065
+ </span>
3066
+ )}
3067
+ value={value}
3068
+ onValueChange={(v) => setValue(v as (typeof languages)[0])}
3069
+ >
3070
+ {languages.map((language) => (
3071
+ <Select.Option key={language.value} value={language}>
3072
+ {language.emoji} {language.label}
3073
+ </Select.Option>
3074
+ ))}
3075
+ </Select>
3076
+ ```
3077
+
3078
+ ```tsx
3079
+ <Select className="w-[200px]" loading />
3080
+ ```
3081
+
3082
+ ```tsx
3083
+ <Select
3084
+ className="w-[200px]"
3085
+ loading={loading}
3086
+ value={value}
3087
+ onValueChange={(v) => setValue(v as string | null)}
3088
+ placeholder="Please select"
3089
+ >
3090
+ {data?.map((item) => (
3091
+ <Select.Option key={item} value={item}>
3092
+ {item}
3093
+ </Select.Option>
3094
+ ))}
3095
+ </Select>
3096
+ ```
3097
+
3098
+ ```tsx
3099
+ <Select
3100
+ className="w-[250px]"
3101
+ multiple
3102
+ renderValue={(value) => {
3103
+ if (value.length > 3) {
3104
+ return (
3105
+ <span className="line-clamp-1">
3106
+ {value.slice(2).join(", ") + ` and ${value.length - 2} more`}
3107
+ </span>
3108
+ );
3109
+ }
3110
+ return <span>{value.join(", ")}</span>;
3111
+ }}
3112
+ value={value}
3113
+ onValueChange={(v) => setValue(v as string[])}
3114
+ >
3115
+ <Select.Option value="Name">Name</Select.Option>
3116
+ <Select.Option value="Location">Location</Select.Option>
3117
+ <Select.Option value="Size">Size</Select.Option>
3118
+ <Select.Option value="Read">Read</Select.Option>
3119
+ <Select.Option value="Write">Write</Select.Option>
3120
+ <Select.Option value="CreatedAt">Created At</Select.Option>
3121
+ </Select>
3122
+ ```
3123
+
3124
+ ```tsx
3125
+ <Select
3126
+ className="w-[200px]"
3127
+ onValueChange={(v) => setValue(v as (typeof authors)[0] | null)}
3128
+ value={value}
3129
+ isItemEqualToValue={(item, value) => item?.id === value?.id}
3130
+ renderValue={(author) => {
3131
+ return author?.name ?? "Please select author";
3132
+ }}
3133
+ >
3134
+ {authors.map((author) => (
3135
+ <Select.Option key={author.id} value={author}>
3136
+ <div className="flex w-[300px] items-center justify-between gap-2">
3137
+ <Text>{author.name}</Text>
3138
+ <Text variant="secondary">{author.title}</Text>
3139
+ </div>
3140
+ </Select.Option>
3141
+ ))}
3142
+ </Select>
3143
+ ```
3144
+
3145
+
3146
+ ---
3147
+
3148
+ ### SensitiveInput
3149
+
3150
+ SensitiveInput component
3151
+
3152
+ **Type:** component
3153
+
3154
+ **Import:** `import { SensitiveInput } from "@cloudflare/kumo";`
3155
+
3156
+ **Category:** Other
3157
+
3158
+ **Props:**
3159
+
3160
+ - `alt`: string
3161
+ - `autoComplete`: React.HTMLInputAutoCompleteAttribute
3162
+ - `checked`: boolean
3163
+ - `disabled`: boolean
3164
+ - `height`: number | string
3165
+ - `list`: string
3166
+ - `name`: string
3167
+ - `placeholder`: string
3168
+ - `readOnly`: boolean
3169
+ - `required`: boolean
3170
+ - `width`: number | string
3171
+ - `className`: string
3172
+ - `id`: string
3173
+ - `lang`: string
3174
+ - `title`: string
3175
+ - `children`: ReactNode
3176
+ - `value`: string
3177
+ Controlled value
3178
+ - `size`: enum [default: base]
3179
+ Size variant
3180
+ - `variant`: enum [default: default]
3181
+ Style variant
3182
+ - `label`: ReactNode
3183
+ Label content for the input (enables Field wrapper and sets masked state label) - can be a string or any React node
3184
+ - `labelTooltip`: ReactNode
3185
+ Tooltip content to display next to the label via an info icon
3186
+ - `description`: ReactNode
3187
+ Helper text displayed below the input
3188
+ - `error`: string | object
3189
+ Error message or validation error object
3190
+
3191
+ **Colors (kumo tokens used):**
3192
+
3193
+ `bg-kumo-brand`, `bg-kumo-control`, `outline-kumo-ring`, `text-kumo-default`, `text-kumo-subtle`
3194
+
3195
+ **Examples:**
3196
+
3197
+ ```tsx
3198
+ <div className="w-80">
3199
+ <SensitiveInput label="API Key" defaultValue="sk_live_abc123xyz789" />
3200
+ </div>
3201
+ ```
3202
+
3203
+ ```tsx
3204
+ <div className="flex flex-col gap-4">
3205
+ {sizes.map((size) => (
3206
+ <div key={size} className="flex items-center gap-2">
3207
+ <span className="w-12 text-sm text-kumo-subtle">{size}</span>
3208
+ <SensitiveInput
3209
+ label={`${size} size`}
3210
+ size={size}
3211
+ defaultValue="secret-api-key-123"
3212
+ />
3213
+ </div>
3214
+ ))}
3215
+ </div>
3216
+ ```
3217
+
3218
+ ```tsx
3219
+ <div className="flex w-80 flex-col gap-4">
3220
+ <SensitiveInput
3221
+ label="Controlled Secret"
3222
+ value={value}
3223
+ onValueChange={setValue}
3224
+ />
3225
+ <div className="text-sm text-kumo-subtle">
3226
+ Current value: <code className="text-kumo-default">{value}</code>
3227
+ </div>
3228
+ <div className="flex gap-2">
3229
+ <Button
3230
+ onClick={() => setValue("new-secret-" + Date.now())}
3231
+ variant="primary"
3232
+ size="sm"
3233
+ >
3234
+ Change value
3235
+ </Button>
3236
+ <Button onClick={() => setValue("")} variant="secondary" size="sm">
3237
+ Clear
3238
+ </Button>
3239
+ </div>
3240
+ </div>
3241
+ ```
3242
+
3243
+ ```tsx
3244
+ <div className="flex w-80 flex-col gap-4">
3245
+ <SensitiveInput
3246
+ label="Error State"
3247
+ variant="error"
3248
+ defaultValue="invalid-key"
3249
+ error="This API key is not valid"
3250
+ />
3251
+ <SensitiveInput label="Disabled" defaultValue="cannot-edit" disabled />
3252
+ <SensitiveInput
3253
+ label="Read-only"
3254
+ defaultValue="view-only-secret-key"
3255
+ readOnly
3256
+ />
3257
+ <SensitiveInput
3258
+ label="With Description"
3259
+ defaultValue="my-secret-value"
3260
+ description="Keep this value secure and don't share it"
3261
+ />
3262
+ </div>
3263
+ ```
3264
+
3265
+
3266
+ ---
3267
+
3268
+ ### Surface
3269
+
3270
+ Surface component
3271
+
3272
+ **Type:** component
3273
+
3274
+ **Import:** `import { Surface } from "@cloudflare/kumo";`
3275
+
3276
+ **Category:** Layout
3277
+
3278
+ **Props:**
3279
+
3280
+ - `as`: React.ElementType
3281
+ The element type to render as (default: "div")
3282
+ - `className`: string
3283
+ Additional CSS classes
3284
+ - `children`: ReactNode
3285
+ Child elements
3286
+
3287
+ **Colors (kumo tokens used):**
3288
+
3289
+ `bg-kumo-base`, `ring-kumo-line`
3290
+
3291
+ **Examples:**
3292
+
3293
+ ```tsx
3294
+ <Surface className="rounded-lg p-6">
3295
+ <Text size="lg" bold>
3296
+ Surface Component
3297
+ </Text>
3298
+ <div className="mt-2">
3299
+ <Text variant="secondary">
3300
+ A container with consistent elevation and border styling.
3301
+ </Text>
3302
+ </div>
3303
+ </Surface>
3304
+ ```
3305
+
3306
+ ```tsx
3307
+ <div className="flex flex-col gap-4">
3308
+ <Surface as="section" className="rounded-lg p-4">
3309
+ <Text bold>As section element</Text>
3310
+ </Surface>
3311
+ <Surface as="article" className="rounded-lg p-4">
3312
+ <Text bold>As article element</Text>
3313
+ </Surface>
3314
+ <Surface as="aside" className="rounded-lg p-4">
3315
+ <Text bold>As aside element</Text>
3316
+ </Surface>
3317
+ </div>
3318
+ ```
3319
+
3320
+ ```tsx
3321
+ <Surface className="rounded-lg p-6">
3322
+ <Text bold>Outer Surface</Text>
3323
+ <Surface className="mt-4 rounded-md bg-kumo-elevated p-4">
3324
+ <Text variant="secondary">Nested Surface</Text>
3325
+ </Surface>
3326
+ </Surface>
3327
+ ```
3328
+
3329
+
3330
+ ---
3331
+
3332
+ ### Switch
3333
+
3334
+ Switch component
3335
+
3336
+ **Type:** component
3337
+
3338
+ **Import:** `import { Switch } from "@cloudflare/kumo";`
3339
+
3340
+ **Category:** Input
3341
+
3342
+ **Props:**
3343
+
3344
+ - `variant`: enum [default: default]
3345
+ - `"default"`: Default switch appearance
3346
+ - `"error"`: Error state for validation failures
3347
+ - `label`: ReactNode
3348
+ Label content for the switch (Field wrapper is built-in) - can be a string or any React node. Optional when used standalone for visual-only purposes.
3349
+ - `labelTooltip`: ReactNode
3350
+ Tooltip content to display next to the label via an info icon
3351
+ - `required`: boolean
3352
+ Whether the switch is required. When explicitly false, shows "(optional)" text after the label.
3353
+ - `controlFirst`: boolean
3354
+ When true (default), switch appears before label. When false, label appears before switch.
3355
+ - `size`: enum [default: base]
3356
+ - `"sm"`: Small switch for compact UIs
3357
+ - `"base"`: Default switch size
3358
+ - `"lg"`: Large switch for prominent toggles
3359
+ - `checked`: boolean
3360
+ - `disabled`: boolean
3361
+ - `transitioning`: boolean
3362
+ - `name`: string
3363
+ - `type`: enum
3364
+ - `value`: string | string[] | number
3365
+ - `className`: string
3366
+ - `id`: string
3367
+ - `lang`: string
3368
+ - `title`: string
3369
+ - `onClick`: (event: React.MouseEvent) => void (required)
3370
+ Callback when switch is clicked
3371
+
3372
+ **Colors (kumo tokens used):**
3373
+
3374
+ `bg-kumo-brand`, `bg-kumo-brand-hover`, `bg-kumo-danger`, `bg-kumo-interact`, `bg-kumo-recessed`, `border-kumo-line`, `ring-kumo-danger`, `text-kumo-danger`, `text-kumo-default`, `text-kumo-subtle`
3375
+
3376
+ **Sub-Components:**
3377
+
3378
+ This is a compound component. Use these sub-components:
3379
+
3380
+ #### Switch.Item
3381
+
3382
+ Item sub-component
3383
+
3384
+ #### Switch.Group
3385
+
3386
+ Group sub-component
3387
+
3388
+ Props:
3389
+ - `legend`: string (required)
3390
+ - `children`: ReactNode (required)
3391
+ - `error`: string
3392
+ - `description`: ReactNode
3393
+ - `disabled`: boolean
3394
+ - `controlFirst`: boolean
3395
+ - `className`: string
3396
+
3397
+
3398
+ **Examples:**
3399
+
3400
+ ```tsx
3401
+ <Switch label="Switch" checked={checked} onCheckedChange={setChecked} />
3402
+ ```
3403
+
3404
+ ```tsx
3405
+ <Switch label="Disabled" checked={false} disabled />
3406
+ ```
3407
+
3408
+
3409
+ ---
3410
+
3411
+ ### Table
3412
+
3413
+ Table component
3414
+
3415
+ **Type:** component
3416
+
3417
+ **Import:** `import { Table } from "@cloudflare/kumo";`
3418
+
3419
+ **Category:** Other
3420
+
3421
+ **Props:**
3422
+
3423
+ - `layout`: enum [default: auto]
3424
+ - `"auto"`: Auto table layout - columns resize based on content
3425
+ - `"fixed"`: Fixed table layout - columns have equal width, controlled via colgroup
3426
+ - `variant`: enum [default: default]
3427
+ - `"default"`: Default row variant
3428
+ - `"selected"`: Selected row variant
3429
+ - `className`: string
3430
+ Additional CSS classes
3431
+ - `children`: ReactNode
3432
+ Child elements
3433
+
3434
+ **Colors (kumo tokens used):**
3435
+
3436
+ `bg-kumo-base`, `bg-kumo-ring`, `bg-kumo-tint`, `border-kumo-fill`, `text-kumo-default`
3437
+
3438
+ **Sub-Components:**
3439
+
3440
+ This is a compound component. Use these sub-components:
3441
+
3442
+ #### Table.Header
3443
+
3444
+ Header sub-component
3445
+
3446
+ #### Table.Head
3447
+
3448
+ Head sub-component
3449
+
3450
+ #### Table.Row
3451
+
3452
+ Row sub-component
3453
+
3454
+ #### Table.Body
3455
+
3456
+ Body sub-component
3457
+
3458
+ #### Table.Cell
3459
+
3460
+ Cell sub-component
3461
+
3462
+ #### Table.CheckCell
3463
+
3464
+ CheckCell sub-component
3465
+
3466
+ #### Table.CheckHead
3467
+
3468
+ CheckHead sub-component
3469
+
3470
+ #### Table.Footer
3471
+
3472
+ Footer sub-component
3473
+
3474
+ #### Table.ResizeHandle
3475
+
3476
+ ResizeHandle sub-component
3477
+
3478
+
3479
+ **Examples:**
3480
+
3481
+ ```tsx
3482
+ <LayerCard>
3483
+ <LayerCard.Primary className="p-0">
3484
+ <Table>
3485
+ <Table.Header>
3486
+ <Table.Row>
3487
+ <Table.Head>Subject</Table.Head>
3488
+ <Table.Head>From</Table.Head>
3489
+ <Table.Head>Date</Table.Head>
3490
+ </Table.Row>
3491
+ </Table.Header>
3492
+ <Table.Body>
3493
+ {emailData.slice(0, 3).map((row) => (
3494
+ <Table.Row key={row.id}>
3495
+ <Table.Cell>{row.subject}</Table.Cell>
3496
+ <Table.Cell>{row.from}</Table.Cell>
3497
+ <Table.Cell>{row.date}</Table.Cell>
3498
+ </Table.Row>
3499
+ ))}
3500
+ </Table.Body>
3501
+ </Table>
3502
+ </LayerCard.Primary>
3503
+ </LayerCard>
3504
+ ```
3505
+
3506
+ ```tsx
3507
+ <LayerCard>
3508
+ <LayerCard.Primary className="p-0">
3509
+ <Table>
3510
+ <Table.Header>
3511
+ <Table.Row>
3512
+ <Table.CheckHead aria-label="Select all rows" />
3513
+ <Table.Head>Subject</Table.Head>
3514
+ <Table.Head>From</Table.Head>
3515
+ <Table.Head>Date</Table.Head>
3516
+ </Table.Row>
3517
+ </Table.Header>
3518
+ <Table.Body>
3519
+ {emailData.slice(0, 3).map((row) => (
3520
+ <Table.Row key={row.id}>
3521
+ <Table.CheckCell aria-label={`Select ${row.subject}`} />
3522
+ <Table.Cell>{row.subject}</Table.Cell>
3523
+ <Table.Cell>{row.from}</Table.Cell>
3524
+ <Table.Cell>{row.date}</Table.Cell>
3525
+ </Table.Row>
3526
+ ))}
3527
+ </Table.Body>
3528
+ </Table>
3529
+ </LayerCard.Primary>
3530
+ </LayerCard>
3531
+ ```
3532
+
3533
+ ```tsx
3534
+ <LayerCard>
3535
+ <LayerCard.Primary className="p-0">
3536
+ <Table>
3537
+ <Table.Header>
3538
+ <Table.Row>
3539
+ <Table.CheckHead aria-label="Select all rows" />
3540
+ <Table.Head>Subject</Table.Head>
3541
+ <Table.Head>From</Table.Head>
3542
+ <Table.Head>Date</Table.Head>
3543
+ </Table.Row>
3544
+ </Table.Header>
3545
+ <Table.Body>
3546
+ <Table.Row>
3547
+ <Table.CheckCell aria-label="Select row 1" />
3548
+ <Table.Cell>Kumo v1.0.0 released</Table.Cell>
3549
+ <Table.Cell>Visal In</Table.Cell>
3550
+ <Table.Cell>5 seconds ago</Table.Cell>
3551
+ </Table.Row>
3552
+ <Table.Row variant="selected">
3553
+ <Table.CheckCell checked aria-label="Select row 2" />
3554
+ <Table.Cell>New Job Offer</Table.Cell>
3555
+ <Table.Cell>Cloudflare</Table.Cell>
3556
+ <Table.Cell>10 minutes ago</Table.Cell>
3557
+ </Table.Row>
3558
+ <Table.Row>
3559
+ <Table.CheckCell aria-label="Select row 3" />
3560
+ <Table.Cell>Daily Email Digest</Table.Cell>
3561
+ <Table.Cell>Cloudflare</Table.Cell>
3562
+ <Table.Cell>1 hour ago</Table.Cell>
3563
+ </Table.Row>
3564
+ </Table.Body>
3565
+ </Table>
3566
+ </LayerCard.Primary>
3567
+ </LayerCard>
3568
+ ```
3569
+
3570
+ ```tsx
3571
+ <LayerCard>
3572
+ <LayerCard.Primary className="p-0">
3573
+ <Table layout="fixed">
3574
+ <colgroup>
3575
+ <col />
3576
+ <col className="w-[150px]" />
3577
+ <col className="w-[150px]" />
3578
+ </colgroup>
3579
+ <Table.Header>
3580
+ <Table.Row>
3581
+ <Table.Head>Subject</Table.Head>
3582
+ <Table.Head>From</Table.Head>
3583
+ <Table.Head>Date</Table.Head>
3584
+ </Table.Row>
3585
+ </Table.Header>
3586
+ <Table.Body>
3587
+ {emailData.map((row) => (
3588
+ <Table.Row key={row.id}>
3589
+ <Table.Cell>{row.subject}</Table.Cell>
3590
+ <Table.Cell>{row.from}</Table.Cell>
3591
+ <Table.Cell>{row.date}</Table.Cell>
3592
+ </Table.Row>
3593
+ ))}
3594
+ </Table.Body>
3595
+ </Table>
3596
+ </LayerCard.Primary>
3597
+ </LayerCard>
3598
+ ```
3599
+
3600
+ ```tsx
3601
+ <LayerCard>
3602
+ <LayerCard.Primary className="w-full overflow-x-auto p-0">
3603
+ <Table layout="fixed">
3604
+ <colgroup>
3605
+ <col style={{ width: "40px" }} />
3606
+ <col />
3607
+ <col style={{ width: "150px" }} />
3608
+ <col style={{ width: "120px" }} />
3609
+ <col style={{ width: "50px" }} />
3610
+ </colgroup>
3611
+ <Table.Header>
3612
+ <Table.Row>
3613
+ <Table.CheckHead aria-label="Select all rows" />
3614
+ <Table.Head>Subject</Table.Head>
3615
+ <Table.Head>From</Table.Head>
3616
+ <Table.Head>Date</Table.Head>
3617
+ <Table.Head></Table.Head>
3618
+ </Table.Row>
3619
+ </Table.Header>
3620
+ <Table.Body>
3621
+ {emailData.map((row, index) => (
3622
+ <Table.Row
3623
+ key={row.id}
3624
+ variant={index === 1 ? "selected" : "default"}
3625
+ >
3626
+ <Table.CheckCell
3627
+ checked={index === 1}
3628
+ aria-label={`Select ${row.subject}`}
3629
+ />
3630
+ <Table.Cell>
3631
+ <div className="flex items-center gap-2">
3632
+ <EnvelopeSimple size={16} />
3633
+ <span className="truncate">{row.subject}</span>
3634
+ {row.tags && (
3635
+ <div className="ml-2 inline-flex gap-1">
3636
+ {row.tags.map((tag) => (
3637
+ <Badge key={tag}>{tag}</Badge>
3638
+ ))}
3639
+ </div>
3640
+ )}
3641
+ </div>
3642
+ </Table.Cell>
3643
+ <Table.Cell>
3644
+ <span className="truncate">{row.from}</span>
3645
+ </Table.Cell>
3646
+ <Table.Cell>
3647
+ <span className="truncate">{row.date}</span>
3648
+ </Table.Cell>
3649
+ <Table.Cell className="text-right">
3650
+ <Button
3651
+ variant="ghost"
3652
+ size="sm"
3653
+ shape="square"
3654
+ aria-label="More options"
3655
+ >
3656
+ <DotsThree weight="bold" size={16} />
3657
+ </Button>
3658
+ </Table.Cell>
3659
+ </Table.Row>
3660
+ ))}
3661
+ </Table.Body>
3662
+ </Table>
3663
+ </LayerCard.Primary>
3664
+ </LayerCard>
3665
+ ```
3666
+
3667
+
3668
+ ---
3669
+
3670
+ ### Tabs
3671
+
3672
+ Tabs component
3673
+
3674
+ **Type:** component
3675
+
3676
+ **Import:** `import { Tabs } from "@cloudflare/kumo";`
3677
+
3678
+ **Category:** Navigation
3679
+
3680
+ **Props:**
3681
+
3682
+ - `tabs`: TabsItem[]
3683
+ Array of tab items to render
3684
+ - `value`: string
3685
+ Controlled value. When set, component becomes controlled.
3686
+ - `selectedValue`: string
3687
+ Default selected value for uncontrolled mode. Ignored when `value` is set.
3688
+ - `activateOnFocus`: boolean
3689
+ When true, tabs are activated immediately upon receiving focus via arrow keys. When false (default), tabs receive focus but require Enter/Space to activate. Set to true for better keyboard UX in most cases.
3690
+ - `className`: string
3691
+ Additional class name for the root element
3692
+ - `listClassName`: string
3693
+ Additional class name for the tab list element
3694
+ - `indicatorClassName`: string
3695
+ Additional class name for the indicator element
3696
+ - `variant`: enum [default: segmented]
3697
+ - `onValueChange`: (value: string) => void
3698
+ Callback when active tab changes
3699
+
3700
+ **Colors (kumo tokens used):**
3701
+
3702
+ `bg-kumo-brand`, `bg-kumo-overlay`, `bg-kumo-tint`, `border-kumo-line`, `border-kumo-tint`, `ring-kumo-fill-hover`, `ring-kumo-ring`, `text-kumo-default`, `text-kumo-strong`, `text-kumo-subtle`
3703
+
3704
+ **Styling:**
3705
+
3706
+
3707
+ **Examples:**
3708
+
3709
+ ```tsx
3710
+ <div className="flex flex-col gap-6">
3711
+ <div>
3712
+ <p className="mb-2 text-sm text-kumo-subtle">Segmented (default)</p>
3713
+ <Tabs
3714
+ variant="segmented"
3715
+ tabs={[
3716
+ { value: "tab1", label: "Tab 1" },
3717
+ { value: "tab2", label: "Tab 2" },
3718
+ { value: "tab3", label: "Tab 3" },
3719
+ ]}
3720
+ selectedValue="tab1"
3721
+ />
3722
+ </div>
3723
+ <div>
3724
+ <p className="mb-2 text-sm text-kumo-subtle">Underline</p>
3725
+ <Tabs
3726
+ variant="underline"
3727
+ tabs={[
3728
+ { value: "tab1", label: "Tab 1" },
3729
+ { value: "tab2", label: "Tab 2" },
3730
+ { value: "tab3", label: "Tab 3" },
3731
+ ]}
3732
+ selectedValue="tab1"
3733
+ />
3734
+ </div>
3735
+ </div>
3736
+ ```
3737
+
3738
+ ```tsx
3739
+ <Tabs
3740
+ variant="segmented"
3741
+ tabs={[
3742
+ { value: "tab1", label: "Tab 1" },
3743
+ { value: "tab2", label: "Tab 2" },
3744
+ { value: "tab3", label: "Tab 3" },
3745
+ ]}
3746
+ selectedValue="tab1"
3747
+ />
3748
+ ```
3749
+
3750
+ ```tsx
3751
+ <div className="space-y-4">
3752
+ <Tabs
3753
+ tabs={[
3754
+ { value: "tab1", label: "Tab 1" },
3755
+ { value: "tab2", label: "Tab 2" },
3756
+ { value: "tab3", label: "Tab 3" },
3757
+ ]}
3758
+ value={activeTab}
3759
+ onValueChange={setActiveTab}
3760
+ />
3761
+ <p className="text-sm text-kumo-subtle">
3762
+ Active tab: <code className="text-sm">{activeTab}</code>
3763
+ </p>
3764
+ </div>
3765
+ ```
3766
+
3767
+ ```tsx
3768
+ <Tabs
3769
+ tabs={[
3770
+ { value: "overview", label: "Overview" },
3771
+ { value: "analytics", label: "Analytics" },
3772
+ { value: "reports", label: "Reports" },
3773
+ { value: "notifications", label: "Notifications" },
3774
+ { value: "settings", label: "Settings" },
3775
+ { value: "billing", label: "Billing" },
3776
+ ]}
3777
+ selectedValue="overview"
3778
+ />
3779
+ ```
3780
+
3781
+ ```tsx
3782
+ <Tabs
3783
+ tabs={[
3784
+ {
3785
+ value: "tab1",
3786
+ label: "Regular Tab",
3787
+ },
3788
+ {
3789
+ value: "tab2",
3790
+ label: "Link Tab",
3791
+ render: (props) => <a {...props} href="#tab2" />,
3792
+ },
3793
+ {
3794
+ value: "tab3",
3795
+ label: "Another Link",
3796
+ render: (props) => <a {...props} href="#tab3" />,
3797
+ },
3798
+ ]}
3799
+ selectedValue="tab1"
3800
+ />
3801
+ ```
3802
+
3803
+
3804
+ ---
3805
+
3806
+ ### Text
3807
+
3808
+ Text component
3809
+
3810
+ **Type:** component
3811
+
3812
+ **Import:** `import { Text } from "@cloudflare/kumo";`
3813
+
3814
+ **Category:** Display
3815
+
3816
+ **Props:**
3817
+
3818
+ - `variant`: enum [default: body]
3819
+ - `"heading1"`: Large heading for page titles
3820
+ - `"heading2"`: Medium heading for section titles
3821
+ - `"heading3"`: Small heading for subsections
3822
+ - `"body"`: Default body text
3823
+ - `"secondary"`: Muted text for secondary information
3824
+ - `"success"`: Success state text
3825
+ - `"error"`: Error state text
3826
+ - `"mono"`: Monospace text for code
3827
+ - `"mono-secondary"`: Muted monospace text
3828
+ - `size`: enum [default: base]
3829
+ - `"xs"`: Extra small text
3830
+ - `"sm"`: Small text
3831
+ - `"base"`: Default text size
3832
+ - `"lg"`: Large text
3833
+ - `bold`: boolean
3834
+ Whether to use bold font weight (only applies to body variants)
3835
+ - `as`: React.ElementType
3836
+ The element type to render as
3837
+ - `children`: ReactNode
3838
+ Child text content
3839
+
3840
+ **Colors (kumo tokens used):**
3841
+
3842
+ `text-kumo-danger`, `text-kumo-default`, `text-kumo-link`, `text-kumo-subtle`
3843
+
3844
+ **Styling:**
3845
+
3846
+
3847
+ **Examples:**
3848
+
3849
+ ```tsx
3850
+ <div className="grid w-full grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3">
3851
+ <div className="flex flex-col justify-end gap-1 rounded-lg border border-kumo-line bg-kumo-base p-4">
3852
+ <Text variant="heading1">Heading 1</Text>
3853
+ <p className="font-mono text-xs text-kumo-subtle">text-3xl (30px)</p>
3854
+ </div>
3855
+ <div className="flex flex-col justify-end gap-1 rounded-lg border border-kumo-line bg-kumo-base p-4">
3856
+ <Text variant="heading2">Heading 2</Text>
3857
+ <p className="font-mono text-xs text-kumo-subtle">text-2xl (24px)</p>
3858
+ </div>
3859
+ <div className="flex flex-col justify-end gap-1 rounded-lg border border-kumo-line bg-kumo-base p-4">
3860
+ <Text variant="heading3">Heading 3</Text>
3861
+ <p className="font-mono text-xs text-kumo-subtle">text-lg (16px)</p>
3862
+ </div>
3863
+ <div className="flex flex-col justify-end gap-1 rounded-lg border border-kumo-line bg-kumo-base p-4">
3864
+ <Text>Body</Text>
3865
+ <p className="font-mono text-xs text-kumo-subtle">text-base (14px)</p>
3866
+ </div>
3867
+ <div className="flex flex-col justify-end gap-1 rounded-lg border border-kumo-line bg-kumo-base p-4">
3868
+ <Text bold>Body bold</Text>
3869
+ <p className="font-mono text-xs text-kumo-subtle">text-base (14px)</p>
3870
+ </div>
3871
+ <div className="flex flex-col justify-end gap-1 rounded-lg border border-kumo-line bg-kumo-base p-4">
3872
+ <Text size="lg">Body lg</Text>
3873
+ <p className="font-mono text-xs text-kumo-subtle">text-lg (16px)</p>
3874
+ </div>
3875
+ <div className="flex flex-col justify-end gap-1 rounded-lg border border-kumo-line bg-kumo-base p-4">
3876
+ <Text size="sm">Body sm</Text>
3877
+ <p className="font-mono text-xs text-kumo-subtle">text-sm (13px)</p>
3878
+ </div>
3879
+ <div className="flex flex-col justify-end gap-1 rounded-lg border border-kumo-line bg-kumo-base p-4">
3880
+ <Text size="xs">Body xs</Text>
3881
+ <p className="font-mono text-xs text-kumo-subtle">text-xs (12px)</p>
3882
+ </div>
3883
+ <div className="flex flex-col justify-end gap-1 rounded-lg border border-kumo-line bg-kumo-base p-4">
3884
+ <Text variant="secondary">Body secondary</Text>
3885
+ <p className="font-mono text-xs text-kumo-subtle">text-base (14px)</p>
3886
+ </div>
3887
+ <div className="flex flex-col justify-end gap-1 rounded-lg border border-kumo-line bg-kumo-base p-4">
3888
+ <Text variant="mono">Monospace</Text>
3889
+ <p className="font-mono text-xs text-kumo-subtle">text-sm (13px)</p>
3890
+ </div>
3891
+ <div className="flex flex-col justify-end gap-1 rounded-lg border border-kumo-line bg-kumo-base p-4">
3892
+ <Text variant="mono" size="lg">
3893
+ Monospace lg
3894
+ </Text>
3895
+ <p className="font-mono text-xs text-kumo-subtle">text-base (14px)</p>
3896
+ </div>
3897
+ <div className="flex flex-col justify-end gap-1 rounded-lg border border-kumo-line bg-kumo-base p-4">
3898
+ <Text variant="mono-secondary">Monospace secondary</Text>
3899
+ <p className="font-mono text-xs text-kumo-subtle">text-sm (13px)</p>
3900
+ </div>
3901
+ <div className="flex flex-col justify-end gap-1 rounded-lg border border-kumo-line bg-kumo-base p-4">
3902
+ <Text variant="success">Success</Text>
3903
+ <p className="font-mono text-xs text-kumo-subtle">text-base (14px)</p>
3904
+ </div>
3905
+ <div className="flex flex-col justify-end gap-1 rounded-lg border border-kumo-line bg-kumo-base p-4">
3906
+ <Text variant="error">Error</Text>
3907
+ <p className="font-mono text-xs text-kumo-subtle">text-base (14px)</p>
3908
+ </div>
3909
+ </div>
3910
+ ```
3911
+
3912
+
3913
+ ---
3914
+
3915
+ ### Toasty
3916
+
3917
+ Toasty component
3918
+
3919
+ **Type:** component
3920
+
3921
+ **Import:** `import { Toasty } from "@cloudflare/kumo";`
3922
+
3923
+ **Category:** Feedback
3924
+
3925
+ **Props:**
3926
+
3927
+ - `children`: ReactNode
3928
+
3929
+ **Colors (kumo tokens used):**
3930
+
3931
+ `bg-kumo-control`, `bg-kumo-fill-hover`, `border-kumo-fill`, `text-kumo-default`, `text-kumo-strong`, `text-kumo-subtle`
3932
+
3933
+ **Styling:**
3934
+
3935
+
3936
+ ---
3937
+
3938
+ ### Tooltip
3939
+
3940
+ Tooltip component
3941
+
3942
+ **Type:** component
3943
+
3944
+ **Import:** `import { Tooltip } from "@cloudflare/kumo";`
3945
+
3946
+ **Category:** Overlay
3947
+
3948
+ **Props:**
3949
+
3950
+ - `align`: enum
3951
+ - `asChild`: boolean
3952
+ - `className`: string
3953
+ - `side`: enum [default: top]
3954
+ - `"top"`: Tooltip appears above the trigger
3955
+ - `"bottom"`: Tooltip appears below the trigger
3956
+ - `"left"`: Tooltip appears to the left of the trigger
3957
+ - `"right"`: Tooltip appears to the right of the trigger
3958
+ - `content`: ReactNode (required)
3959
+ Content to display in the tooltip
3960
+
3961
+ **Colors (kumo tokens used):**
3962
+
3963
+ `bg-kumo-base`, `fill-kumo-base`, `fill-kumo-tip-shadow`, `fill-kumo-tip-stroke`, `outline-kumo-fill`, `text-kumo-default`
3964
+
3965
+ **Examples:**
3966
+
3967
+ ```tsx
3968
+ <TooltipProvider>
3969
+ <Tooltip content="Add new item" asChild>
3970
+ <Button shape="square" icon={PlusIcon} />
3971
+ </Tooltip>
3972
+ </TooltipProvider>
3973
+ ```
3974
+
3975
+ ```tsx
3976
+ <TooltipProvider>
3977
+ <div className="flex gap-2">
3978
+ <Tooltip content="Add" asChild>
3979
+ <Button shape="square" icon={PlusIcon} />
3980
+ </Tooltip>
3981
+ <Tooltip content="Change language" asChild>
3982
+ <Button shape="square" icon={TranslateIcon} />
3983
+ </Tooltip>
3984
+ </div>
3985
+ </TooltipProvider>
3986
+ ```
3987
+
3988
+
3989
+ ---
3990
+
3991
+ ### InputArea
3992
+
3993
+ Multi-line textarea input with Input variants and InputArea-specific dimensions
3994
+
3995
+ **Type:** component
3996
+
3997
+ **Import:** `import { InputArea } from "@cloudflare/kumo (synthetic - uses Input component)";`
3998
+
3999
+ **Category:** Input
4000
+
4001
+ **Props:**
4002
+
4003
+
4004
+ **Styling:**
4005
+
4006
+ - **Size Variants:**
4007
+ - `xs`:
4008
+ - `sm`:
4009
+ - `base`:
4010
+ - `lg`:
4011
+
4012
+ ## Quick Reference
4013
+
4014
+ **Components by Category:**
4015
+ - **Display:** Badge, Breadcrumbs, Code, Collapsible, Empty, LayerCard, Meter, Text
4016
+ - **Feedback:** Banner, Loader, Toasty
4017
+ - **Action:** Button, ClipboardText
4018
+ - **Input:** Checkbox, Combobox, DateRangePicker, Field, Input, Radio, Select, Switch
4019
+ - **Navigation:** CommandPalette, MenuBar, Pagination, Tabs
4020
+ - **Overlay:** Dialog, DropdownMenu, Popover, Tooltip
4021
+ - **Layout:** Grid, Surface, PageHeader, ResourceListPage
4022
+ - **Other:** Label, Link, SensitiveInput, Table