@cloudflare/kumo 1.19.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (289) hide show
  1. package/CHANGELOG.md +239 -0
  2. package/ai/component-registry.json +758 -118
  3. package/ai/component-registry.md +1151 -153
  4. package/ai/schemas.ts +42 -14
  5. package/dist/.build-complete +1 -1
  6. package/dist/ai/schemas.d.ts +153 -21
  7. package/dist/ai/schemas.d.ts.map +1 -1
  8. package/dist/ai/schemas.js +1994 -1956
  9. package/dist/ai/schemas.js.map +1 -1
  10. package/dist/chunks/Legend-ibjxhfm9pn2vrb6f.js +430 -0
  11. package/dist/chunks/Legend-ibjxhfm9pn2vrb6f.js.map +1 -0
  12. package/dist/chunks/autocomplete-cs3fwy6lwzlyirpq.js +174 -0
  13. package/dist/chunks/autocomplete-cs3fwy6lwzlyirpq.js.map +1 -0
  14. package/dist/chunks/{breadcrumbs-ge20hcb3o5spswrk.js → breadcrumbs-cxcwf2l1ki3ffg5d.js} +2 -2
  15. package/dist/chunks/{breadcrumbs-ge20hcb3o5spswrk.js.map → breadcrumbs-cxcwf2l1ki3ffg5d.js.map} +1 -1
  16. package/dist/chunks/{button-oaqi7ykdisyskoos.js → button-6by9ntsa3nj553mq.js} +23 -24
  17. package/dist/chunks/button-6by9ntsa3nj553mq.js.map +1 -0
  18. package/dist/chunks/checkbox-eren6w2csum1xghg.js +210 -0
  19. package/dist/chunks/checkbox-eren6w2csum1xghg.js.map +1 -0
  20. package/dist/chunks/{clipboard-text-dxczqon3d27xp6f0.js → clipboard-text-f9q753udny1uyxr5.js} +45 -41
  21. package/dist/chunks/{clipboard-text-dxczqon3d27xp6f0.js.map → clipboard-text-f9q753udny1uyxr5.js.map} +1 -1
  22. package/dist/chunks/collapsible-k8urhi16pg90jvxa.js +71 -0
  23. package/dist/chunks/collapsible-k8urhi16pg90jvxa.js.map +1 -0
  24. package/dist/chunks/{combobox-eaowwt1xr4d23gsn.js → combobox-n9qht9h9ag6kh5sn.js} +86 -74
  25. package/dist/chunks/combobox-n9qht9h9ag6kh5sn.js.map +1 -0
  26. package/dist/chunks/{command-palette-maqtbmpfev9mysqd.js → command-palette-gk9m34ymp2b3hfc5.js} +126 -126
  27. package/dist/chunks/command-palette-gk9m34ymp2b3hfc5.js.map +1 -0
  28. package/dist/chunks/{date-range-picker-j318zxjyqz4o3dak.js → date-range-picker-c9wnx9tbwohai7jy.js} +26 -26
  29. package/dist/chunks/{date-range-picker-j318zxjyqz4o3dak.js.map → date-range-picker-c9wnx9tbwohai7jy.js.map} +1 -1
  30. package/dist/chunks/{dialog-e3m5bhs7fds26p9y.js → dialog-94v7wiz7j3in6528.js} +3 -3
  31. package/dist/chunks/{dialog-e3m5bhs7fds26p9y.js.map → dialog-94v7wiz7j3in6528.js.map} +1 -1
  32. package/dist/chunks/{dropdown-ewte287db3vyt8t5.js → dropdown-zbax0zowy6m9zhmt.js} +87 -87
  33. package/dist/chunks/dropdown-zbax0zowy6m9zhmt.js.map +1 -0
  34. package/dist/chunks/{empty-dr1eckm2z40euns6.js → empty-kpymw59thjf2ip8g.js} +9 -9
  35. package/dist/chunks/{empty-dr1eckm2z40euns6.js.map → empty-kpymw59thjf2ip8g.js.map} +1 -1
  36. package/dist/chunks/{field-bo5gmna16odrrb1q.js → field-lnj619xpe8zjd26r.js} +7 -7
  37. package/dist/chunks/{field-bo5gmna16odrrb1q.js.map → field-lnj619xpe8zjd26r.js.map} +1 -1
  38. package/dist/chunks/{input-area-jkkkjej6luumrqpa.js → input-area-h8xbqturegdfm1mi.js} +4 -4
  39. package/dist/chunks/{input-area-jkkkjej6luumrqpa.js.map → input-area-h8xbqturegdfm1mi.js.map} +1 -1
  40. package/dist/chunks/input-group-dh4pg8p20rh4mdi0.js +505 -0
  41. package/dist/chunks/input-group-dh4pg8p20rh4mdi0.js.map +1 -0
  42. package/dist/chunks/{input-cw05pbqdburghkus.js → input-lpa5fc75tgrraafv.js} +46 -46
  43. package/dist/chunks/input-lpa5fc75tgrraafv.js.map +1 -0
  44. package/dist/chunks/{label-cvyvbqmt4mt757ff.js → label-be8m7qzlakzig2sl.js} +3 -3
  45. package/dist/chunks/{label-cvyvbqmt4mt757ff.js.map → label-be8m7qzlakzig2sl.js.map} +1 -1
  46. package/dist/chunks/{layer-card-ljqth3yxgnk04v2o.js → layer-card-hvivdirwwnyq88wa.js} +5 -5
  47. package/dist/chunks/{layer-card-ljqth3yxgnk04v2o.js.map → layer-card-hvivdirwwnyq88wa.js.map} +1 -1
  48. package/dist/chunks/{link-fjnhtxvfe5ieamjf.js → link-kt74pxkud4olmcer.js} +4 -4
  49. package/dist/chunks/{link-fjnhtxvfe5ieamjf.js.map → link-kt74pxkud4olmcer.js.map} +1 -1
  50. package/dist/chunks/menubar-hwev159bm4rw9ixk.js +96 -0
  51. package/dist/chunks/menubar-hwev159bm4rw9ixk.js.map +1 -0
  52. package/dist/chunks/{meter-duj3micor1lqj3y2.js → meter-bqetlujwg8gm2u7m.js} +2 -2
  53. package/dist/chunks/{meter-duj3micor1lqj3y2.js.map → meter-bqetlujwg8gm2u7m.js.map} +1 -1
  54. package/dist/chunks/{pagination-olaypvwr8swsmn8m.js → pagination-ho8zesqfyp6ckmrl.js} +21 -21
  55. package/dist/chunks/pagination-ho8zesqfyp6ckmrl.js.map +1 -0
  56. package/dist/chunks/{popover-nv9cmzbo7mf6bky0.js → popover-iayd9ya5yhujz6ve.js} +5 -5
  57. package/dist/chunks/{popover-nv9cmzbo7mf6bky0.js.map → popover-iayd9ya5yhujz6ve.js.map} +1 -1
  58. package/dist/chunks/{radio-ihxbe37us2jnqtzf.js → radio-datzh3pilz8ojak1.js} +86 -74
  59. package/dist/chunks/radio-datzh3pilz8ojak1.js.map +1 -0
  60. package/dist/chunks/{select-nx6ded5swra74iar.js → select-kpfbib9l8xrrmzpz.js} +64 -62
  61. package/dist/chunks/select-kpfbib9l8xrrmzpz.js.map +1 -0
  62. package/dist/chunks/{sensitive-input-00fujb510rrn61v9.js → sensitive-input-i1upqytzaw2pus8v.js} +42 -42
  63. package/dist/chunks/sensitive-input-i1upqytzaw2pus8v.js.map +1 -0
  64. package/dist/chunks/{sidebar-ltbfius1eolkl8tb.js → sidebar-kh37grvfxto14ek6.js} +129 -126
  65. package/dist/chunks/sidebar-kh37grvfxto14ek6.js.map +1 -0
  66. package/dist/chunks/{surface-dfgurg5eu3et4vw1.js → surface-o63tktyrifcjejyb.js} +2 -2
  67. package/dist/chunks/{surface-dfgurg5eu3et4vw1.js.map → surface-o63tktyrifcjejyb.js.map} +1 -1
  68. package/dist/chunks/{switch-fbv3iawqo3o3jgap.js → switch-lclhiplr9zqf73tj.js} +86 -78
  69. package/dist/chunks/switch-lclhiplr9zqf73tj.js.map +1 -0
  70. package/dist/chunks/{table-olwwulga2l3hdwlx.js → table-fyy8gl875yyevqs3.js} +89 -71
  71. package/dist/chunks/table-fyy8gl875yyevqs3.js.map +1 -0
  72. package/dist/chunks/table-of-contents-fzyv7uhnnyr13dqu.js +102 -0
  73. package/dist/chunks/table-of-contents-fzyv7uhnnyr13dqu.js.map +1 -0
  74. package/dist/chunks/{tabs-lohcglgppp6gj0hp.js → tabs-jywwt8ebjqjkux75.js} +19 -19
  75. package/dist/chunks/{tabs-lohcglgppp6gj0hp.js.map → tabs-jywwt8ebjqjkux75.js.map} +1 -1
  76. package/dist/chunks/{text-nmyi1rkwdj37f30f.js → text-f7t467waymhb30sx.js} +8 -8
  77. package/dist/chunks/text-f7t467waymhb30sx.js.map +1 -0
  78. package/dist/chunks/{toast-dg52x89yd231mxhe.js → toast-h573o0tc7tefivk2.js} +11 -11
  79. package/dist/chunks/{toast-dg52x89yd231mxhe.js.map → toast-h573o0tc7tefivk2.js.map} +1 -1
  80. package/dist/chunks/{tooltip-hikjvdbg3xghnq1x.js → tooltip-odudhkxe282wxinq.js} +5 -5
  81. package/dist/chunks/{tooltip-hikjvdbg3xghnq1x.js.map → tooltip-odudhkxe282wxinq.js.map} +1 -1
  82. package/dist/chunks/vendor-base-ui-ie71jahf0czyf58j.js +24638 -0
  83. package/dist/chunks/vendor-base-ui-ie71jahf0czyf58j.js.map +1 -0
  84. package/dist/chunks/vendor-floating-ui-dwag5e88viikh2zs.js +1311 -0
  85. package/dist/chunks/vendor-floating-ui-dwag5e88viikh2zs.js.map +1 -0
  86. package/dist/chunks/vendor-utils-ixnhxmehwihk5tr7.js +534 -0
  87. package/dist/chunks/vendor-utils-ixnhxmehwihk5tr7.js.map +1 -0
  88. package/dist/code.js +1 -1
  89. package/dist/components/autocomplete.js +9 -0
  90. package/dist/components/autocomplete.js.map +1 -0
  91. package/dist/components/breadcrumbs.js +1 -1
  92. package/dist/components/button.js +1 -1
  93. package/dist/components/chart.js +1 -1
  94. package/dist/components/checkbox.js +1 -1
  95. package/dist/components/clipboard-text.js +1 -1
  96. package/dist/components/collapsible.js +1 -1
  97. package/dist/components/combobox.js +1 -1
  98. package/dist/components/command-palette.js +1 -1
  99. package/dist/components/date-range-picker.js +1 -1
  100. package/dist/components/dialog.js +1 -1
  101. package/dist/components/dropdown.js +1 -1
  102. package/dist/components/empty.js +1 -1
  103. package/dist/components/field.js +1 -1
  104. package/dist/components/input-group.js +8 -0
  105. package/dist/components/input-group.js.map +1 -0
  106. package/dist/components/input.js +9 -7
  107. package/dist/components/label.js +1 -1
  108. package/dist/components/layer-card.js +1 -1
  109. package/dist/components/link.js +1 -1
  110. package/dist/components/menubar.js +1 -1
  111. package/dist/components/meter.js +1 -1
  112. package/dist/components/pagination.js +1 -1
  113. package/dist/components/popover.js +1 -1
  114. package/dist/components/radio.js +1 -1
  115. package/dist/components/select.js +1 -1
  116. package/dist/components/sensitive-input.js +1 -1
  117. package/dist/components/sidebar.js +1 -1
  118. package/dist/components/surface.js +1 -1
  119. package/dist/components/switch.js +1 -1
  120. package/dist/components/table-of-contents.js +1 -1
  121. package/dist/components/table.js +1 -1
  122. package/dist/components/tabs.js +1 -1
  123. package/dist/components/text.js +1 -1
  124. package/dist/components/toast.js +2 -2
  125. package/dist/components/tooltip.js +1 -1
  126. package/dist/index.js +148 -143
  127. package/dist/index.js.map +1 -1
  128. package/dist/primitives/accordion.js +1 -1
  129. package/dist/primitives/alert-dialog.js +1 -1
  130. package/dist/primitives/autocomplete.js +1 -1
  131. package/dist/primitives/avatar.js +1 -1
  132. package/dist/primitives/button.js +1 -1
  133. package/dist/primitives/checkbox-group.js +1 -1
  134. package/dist/primitives/checkbox.js +1 -1
  135. package/dist/primitives/collapsible.js +1 -1
  136. package/dist/primitives/combobox.js +1 -1
  137. package/dist/primitives/context-menu.js +1 -1
  138. package/dist/primitives/csp-provider.js +1 -1
  139. package/dist/primitives/dialog.js +1 -1
  140. package/dist/primitives/direction-provider.js +1 -1
  141. package/dist/primitives/drawer.js +2 -2
  142. package/dist/primitives/field.js +1 -1
  143. package/dist/primitives/fieldset.js +1 -1
  144. package/dist/primitives/form.js +1 -1
  145. package/dist/primitives/input.js +1 -1
  146. package/dist/primitives/menu.js +1 -1
  147. package/dist/primitives/menubar.js +1 -1
  148. package/dist/primitives/meter.js +1 -1
  149. package/dist/primitives/navigation-menu.js +1 -1
  150. package/dist/primitives/number-field.js +1 -1
  151. package/dist/primitives/otp-field.js +6 -0
  152. package/dist/primitives/otp-field.js.map +1 -0
  153. package/dist/primitives/popover.js +1 -1
  154. package/dist/primitives/preview-card.js +2 -2
  155. package/dist/primitives/progress.js +1 -1
  156. package/dist/primitives/radio-group.js +1 -1
  157. package/dist/primitives/radio.js +1 -1
  158. package/dist/primitives/scroll-area.js +1 -1
  159. package/dist/primitives/select.js +1 -1
  160. package/dist/primitives/separator.js +1 -1
  161. package/dist/primitives/slider.js +1 -1
  162. package/dist/primitives/switch.js +1 -1
  163. package/dist/primitives/tabs.js +1 -1
  164. package/dist/primitives/toast.js +1 -1
  165. package/dist/primitives/toggle-group.js +1 -1
  166. package/dist/primitives/toggle.js +1 -1
  167. package/dist/primitives/toolbar.js +1 -1
  168. package/dist/primitives/tooltip.js +1 -1
  169. package/dist/primitives.js +22 -21
  170. package/dist/scripts/theme-generator/config.d.ts.map +1 -1
  171. package/dist/scripts/theme-generator/config.js +10 -0
  172. package/dist/scripts/theme-generator/config.js.map +1 -1
  173. package/dist/src/components/autocomplete/autocomplete.d.ts +180 -0
  174. package/dist/src/components/autocomplete/autocomplete.d.ts.map +1 -0
  175. package/dist/src/components/autocomplete/index.d.ts +2 -0
  176. package/dist/src/components/autocomplete/index.d.ts.map +1 -0
  177. package/dist/src/components/button/button.d.ts +3 -3
  178. package/dist/src/components/button/button.d.ts.map +1 -1
  179. package/dist/src/components/chart/Color.d.ts +36 -52
  180. package/dist/src/components/chart/Color.d.ts.map +1 -1
  181. package/dist/src/components/checkbox/checkbox.d.ts +37 -14
  182. package/dist/src/components/checkbox/checkbox.d.ts.map +1 -1
  183. package/dist/src/components/checkbox/index.d.ts +1 -1
  184. package/dist/src/components/checkbox/index.d.ts.map +1 -1
  185. package/dist/src/components/clipboard-text/clipboard-text.d.ts.map +1 -1
  186. package/dist/src/components/collapsible/collapsible.d.ts +77 -40
  187. package/dist/src/components/collapsible/collapsible.d.ts.map +1 -1
  188. package/dist/src/components/collapsible/index.d.ts +1 -1
  189. package/dist/src/components/collapsible/index.d.ts.map +1 -1
  190. package/dist/src/components/combobox/combobox.d.ts +3 -1
  191. package/dist/src/components/combobox/combobox.d.ts.map +1 -1
  192. package/dist/src/components/command-palette/command-palette.d.ts +2 -11
  193. package/dist/src/components/command-palette/command-palette.d.ts.map +1 -1
  194. package/dist/src/components/command-palette/index.d.ts +1 -1
  195. package/dist/src/components/command-palette/index.d.ts.map +1 -1
  196. package/dist/src/components/command-palette/types.d.ts +13 -1
  197. package/dist/src/components/command-palette/types.d.ts.map +1 -1
  198. package/dist/src/components/input/index.d.ts +16 -1
  199. package/dist/src/components/input/index.d.ts.map +1 -1
  200. package/dist/src/components/input/input.d.ts +2 -2
  201. package/dist/src/components/input/input.d.ts.map +1 -1
  202. package/dist/src/components/input-group/context.d.ts +96 -0
  203. package/dist/src/components/input-group/context.d.ts.map +1 -0
  204. package/dist/src/components/input-group/index.d.ts +2 -0
  205. package/dist/src/components/input-group/index.d.ts.map +1 -0
  206. package/dist/src/components/input-group/input-group-addon.d.ts +15 -0
  207. package/dist/src/components/input-group/input-group-addon.d.ts.map +1 -0
  208. package/dist/src/components/input-group/input-group-button.d.ts +36 -0
  209. package/dist/src/components/input-group/input-group-button.d.ts.map +1 -0
  210. package/dist/src/components/input-group/input-group-input.d.ts +9 -0
  211. package/dist/src/components/input-group/input-group-input.d.ts.map +1 -0
  212. package/dist/src/components/input-group/input-group-suffix.d.ts +13 -0
  213. package/dist/src/components/input-group/input-group-suffix.d.ts.map +1 -0
  214. package/dist/src/components/input-group/input-group.d.ts +43 -0
  215. package/dist/src/components/input-group/input-group.d.ts.map +1 -0
  216. package/dist/src/components/menubar/menubar.d.ts.map +1 -1
  217. package/dist/src/components/radio/index.d.ts +1 -1
  218. package/dist/src/components/radio/index.d.ts.map +1 -1
  219. package/dist/src/components/radio/radio.d.ts +43 -7
  220. package/dist/src/components/radio/radio.d.ts.map +1 -1
  221. package/dist/src/components/select/select.d.ts +3 -3
  222. package/dist/src/components/select/select.d.ts.map +1 -1
  223. package/dist/src/components/sensitive-input/sensitive-input.d.ts +2 -2
  224. package/dist/src/components/sidebar/sidebar.d.ts.map +1 -1
  225. package/dist/src/components/switch/index.d.ts +1 -1
  226. package/dist/src/components/switch/index.d.ts.map +1 -1
  227. package/dist/src/components/switch/switch.d.ts +31 -3
  228. package/dist/src/components/switch/switch.d.ts.map +1 -1
  229. package/dist/src/components/table/table.d.ts +17 -2
  230. package/dist/src/components/table/table.d.ts.map +1 -1
  231. package/dist/src/components/table-of-contents/table-of-contents.d.ts +9 -7
  232. package/dist/src/components/table-of-contents/table-of-contents.d.ts.map +1 -1
  233. package/dist/src/components/text/text.d.ts +34 -6
  234. package/dist/src/components/text/text.d.ts.map +1 -1
  235. package/dist/src/components/text/text.type-spec.d.ts +44 -0
  236. package/dist/src/components/text/text.type-spec.d.ts.map +1 -0
  237. package/dist/src/components/toast/toast.d.ts +1 -1
  238. package/dist/src/components/toast/toast.d.ts.map +1 -1
  239. package/dist/src/index.d.ts +8 -6
  240. package/dist/src/index.d.ts.map +1 -1
  241. package/dist/src/primitives/index.d.ts +1 -0
  242. package/dist/src/primitives/index.d.ts.map +1 -1
  243. package/dist/src/primitives/otp-field.d.ts +13 -0
  244. package/dist/src/primitives/otp-field.d.ts.map +1 -0
  245. package/dist/styles/kumo-binding.css +18 -0
  246. package/dist/styles/kumo-standalone.css +1 -1
  247. package/dist/styles/kumo.css +2 -2
  248. package/dist/styles/theme-kumo.css +7 -0
  249. package/package.json +14 -2
  250. package/scripts/component-registry/discovery.ts +1 -0
  251. package/scripts/component-registry/index.test.ts +265 -0
  252. package/scripts/component-registry/index.ts +14 -0
  253. package/scripts/component-registry/metadata.ts +55 -7
  254. package/scripts/component-registry/sub-components.ts +81 -50
  255. package/scripts/component-registry/types.ts +2 -0
  256. package/scripts/theme-generator/config.ts +10 -0
  257. package/dist/chunks/Legend-ks7se6149vsa3tze.js +0 -430
  258. package/dist/chunks/Legend-ks7se6149vsa3tze.js.map +0 -1
  259. package/dist/chunks/button-oaqi7ykdisyskoos.js.map +0 -1
  260. package/dist/chunks/checkbox-mwgmohffm22ut13s.js +0 -211
  261. package/dist/chunks/checkbox-mwgmohffm22ut13s.js.map +0 -1
  262. package/dist/chunks/collapsible-jhzee3ks51d3xowb.js +0 -58
  263. package/dist/chunks/collapsible-jhzee3ks51d3xowb.js.map +0 -1
  264. package/dist/chunks/combobox-eaowwt1xr4d23gsn.js.map +0 -1
  265. package/dist/chunks/command-palette-maqtbmpfev9mysqd.js.map +0 -1
  266. package/dist/chunks/dropdown-ewte287db3vyt8t5.js.map +0 -1
  267. package/dist/chunks/input-cw05pbqdburghkus.js.map +0 -1
  268. package/dist/chunks/input-group-lfugneuz71g42n0w.js +0 -111
  269. package/dist/chunks/input-group-lfugneuz71g42n0w.js.map +0 -1
  270. package/dist/chunks/menubar-e5e4zwfagr0wx023.js +0 -96
  271. package/dist/chunks/menubar-e5e4zwfagr0wx023.js.map +0 -1
  272. package/dist/chunks/pagination-olaypvwr8swsmn8m.js.map +0 -1
  273. package/dist/chunks/radio-ihxbe37us2jnqtzf.js.map +0 -1
  274. package/dist/chunks/select-nx6ded5swra74iar.js.map +0 -1
  275. package/dist/chunks/sensitive-input-00fujb510rrn61v9.js.map +0 -1
  276. package/dist/chunks/sidebar-ltbfius1eolkl8tb.js.map +0 -1
  277. package/dist/chunks/switch-fbv3iawqo3o3jgap.js.map +0 -1
  278. package/dist/chunks/table-of-contents-f813ivi7ta23vqdm.js +0 -88
  279. package/dist/chunks/table-of-contents-f813ivi7ta23vqdm.js.map +0 -1
  280. package/dist/chunks/table-olwwulga2l3hdwlx.js.map +0 -1
  281. package/dist/chunks/text-nmyi1rkwdj37f30f.js.map +0 -1
  282. package/dist/chunks/vendor-base-ui-m5pz3e8c4grg5qmj.js +0 -22813
  283. package/dist/chunks/vendor-base-ui-m5pz3e8c4grg5qmj.js.map +0 -1
  284. package/dist/chunks/vendor-floating-ui-gr9m6tsa1cpqwn99.js +0 -1286
  285. package/dist/chunks/vendor-floating-ui-gr9m6tsa1cpqwn99.js.map +0 -1
  286. package/dist/chunks/vendor-utils-fxk97j6xi1g42z2v.js +0 -740
  287. package/dist/chunks/vendor-utils-fxk97j6xi1g42z2v.js.map +0 -1
  288. package/dist/src/components/input/input-group.d.ts +0 -39
  289. package/dist/src/components/input/input-group.d.ts.map +0 -1
@@ -1,6 +1,171 @@
1
1
  {
2
2
  "version": "1.0.0",
3
3
  "components": {
4
+ "Autocomplete": {
5
+ "name": "Autocomplete",
6
+ "type": "component",
7
+ "description": "Autocomplete — free-form text input with an optional filtered suggestion list. Unlike Combobox, the input value is not restricted to items in the list. Use Combobox when the selected value must come from the list. Compound component: `Autocomplete` (Root), `.InputGroup`, `.Content`, `.Item`, `.GroupLabel`, `.Group`, `.Separator`, `.List`, `.Collection`. `InputGroup` renders the text input with Input component styling. Pass a `size` prop to `InputGroup` to match the Input component sizes.",
8
+ "importPath": "@cloudflare/kumo",
9
+ "category": "Other",
10
+ "props": {
11
+ "items": {
12
+ "type": "unknown[]",
13
+ "required": true,
14
+ "description": "Array of items to display in the dropdown"
15
+ },
16
+ "value": {
17
+ "type": "string | number | string[]",
18
+ "optional": true,
19
+ "description": "The controlled input value"
20
+ },
21
+ "open": {
22
+ "type": "boolean",
23
+ "optional": true,
24
+ "description": "Whether the popup is open (controlled)"
25
+ },
26
+ "children": {
27
+ "type": "ReactNode",
28
+ "optional": true,
29
+ "description": "Autocomplete content (input group, popup content)"
30
+ },
31
+ "className": {
32
+ "type": "string",
33
+ "optional": true,
34
+ "description": "Additional CSS classes"
35
+ },
36
+ "label": {
37
+ "type": "ReactNode",
38
+ "optional": true,
39
+ "description": "Label content (enables Field wrapper)"
40
+ },
41
+ "required": {
42
+ "type": "boolean",
43
+ "optional": true,
44
+ "description": "Whether the field is required"
45
+ },
46
+ "labelTooltip": {
47
+ "type": "ReactNode",
48
+ "optional": true,
49
+ "description": "Tooltip content to display next to the label"
50
+ },
51
+ "description": {
52
+ "type": "ReactNode",
53
+ "optional": true,
54
+ "description": "Helper text displayed below the field"
55
+ },
56
+ "error": {
57
+ "type": "string | object",
58
+ "optional": true,
59
+ "description": "Error message or validation error object"
60
+ }
61
+ },
62
+ "examples": [
63
+ "<Autocomplete items={fruits}>\n <Autocomplete.InputGroup placeholder=\"Search fruits…\" />\n <Autocomplete.Content>\n <Autocomplete.List>\n {(item: string) => (\n <Autocomplete.Item key={item} value={item}>\n {item}\n </Autocomplete.Item>\n )}\n </Autocomplete.List>\n </Autocomplete.Content>\n </Autocomplete>",
64
+ "<div className=\"w-80\">\n <Autocomplete\n items={countries}\n label=\"Country\"\n description=\"Start typing to filter countries\"\n filter={(item: Country, query: string) =>\n item.label.toLowerCase().includes(query.toLowerCase())\n }\n >\n <Autocomplete.InputGroup placeholder=\"Search countries…\" />\n <Autocomplete.Content>\n <Autocomplete.List>\n {(item: Country) => (\n <Autocomplete.Item key={item.code} value={item}>\n {item.label}\n </Autocomplete.Item>\n )}\n </Autocomplete.List>\n </Autocomplete.Content>\n </Autocomplete>\n </div>",
65
+ "<div className=\"w-80\">\n <Autocomplete\n items={countries}\n label=\"Country\"\n error={{ message: \"Please enter a valid country\", match: true }}\n filter={(item: Country, query: string) =>\n item.label.toLowerCase().includes(query.toLowerCase())\n }\n >\n <Autocomplete.InputGroup placeholder=\"Search countries…\" />\n <Autocomplete.Content>\n <Autocomplete.List>\n {(item: Country) => (\n <Autocomplete.Item key={item.code} value={item}>\n {item.label}\n </Autocomplete.Item>\n )}\n </Autocomplete.List>\n </Autocomplete.Content>\n </Autocomplete>\n </div>",
66
+ "<Autocomplete items={servers}>\n <Autocomplete.InputGroup placeholder=\"Select region…\" />\n <Autocomplete.Content>\n <Autocomplete.List>\n {(group: ServerGroup) => (\n <Autocomplete.Group key={group.value} items={group.items}>\n <Autocomplete.GroupLabel>{group.value}</Autocomplete.GroupLabel>\n <Autocomplete.Collection>\n {(item: ServerLocation) => (\n <Autocomplete.Item key={item.value} value={item}>\n {item.label}\n </Autocomplete.Item>\n )}\n </Autocomplete.Collection>\n </Autocomplete.Group>\n )}\n </Autocomplete.List>\n </Autocomplete.Content>\n </Autocomplete>",
67
+ "<div className=\"flex flex-wrap items-center gap-4\">\n <Autocomplete items={fruits.slice(0, 10)}>\n <Autocomplete.InputGroup size=\"xs\" placeholder=\"xs\" />\n <Autocomplete.Content>\n <Autocomplete.List>\n {(item: string) => (\n <Autocomplete.Item key={item} value={item}>\n {item}\n </Autocomplete.Item>\n )}\n </Autocomplete.List>\n </Autocomplete.Content>\n </Autocomplete>\n <Autocomplete items={fruits.slice(0, 10)}>\n <Autocomplete.InputGroup size=\"sm\" placeholder=\"sm\" />\n <Autocomplete.Content>\n <Autocomplete.List>\n {(item: string) => (\n <Autocomplete.Item key={item} value={item}>\n {item}\n </Autocomplete.Item>\n )}\n </Autocomplete.List>\n </Autocomplete.Content>\n </Autocomplete>\n <Autocomplete items={fruits.slice(0, 10)}>\n <Autocomplete.InputGroup size=\"base\" placeholder=\"base (default)\" />\n <Autocomplete.Content>\n <Autocomplete.List>\n {(item: string) => (\n <Autocomplete.Item key={item} value={item}>\n {item}\n </Autocomplete.Item>\n )}\n </Autocomplete.List>\n </Autocomplete.Content>\n </Autocomplete>\n <Autocomplete items={fruits.slice(0, 10)}>\n <Autocomplete.InputGroup size=\"lg\" placeholder=\"lg\" />\n <Autocomplete.Content>\n <Autocomplete.List>\n {(item: string) => (\n <Autocomplete.Item key={item} value={item}>\n {item}\n </Autocomplete.Item>\n )}\n </Autocomplete.List>\n </Autocomplete.Content>\n </Autocomplete>\n </div>",
68
+ "<div className=\"flex flex-col gap-3 w-80\">\n <Autocomplete\n items={fruits}\n value={value}\n onValueChange={(v) => setValue(v)}\n >\n <Autocomplete.InputGroup placeholder=\"Type a fruit…\" />\n <Autocomplete.Content>\n <Autocomplete.List>\n {(item: string) => (\n <Autocomplete.Item key={item} value={item}>\n {item}\n </Autocomplete.Item>\n )}\n </Autocomplete.List>\n </Autocomplete.Content>\n </Autocomplete>\n {value && (\n <p className=\"text-sm text-kumo-subtle\">\n Value: <span className=\"text-kumo-default font-medium\">{value}</span>\n </p>\n )}\n </div>"
69
+ ],
70
+ "colors": [
71
+ "bg-kumo-control",
72
+ "bg-kumo-line",
73
+ "bg-kumo-overlay",
74
+ "border-kumo-line",
75
+ "ring-kumo-line",
76
+ "text-kumo-default",
77
+ "text-kumo-strong"
78
+ ],
79
+ "subComponents": {
80
+ "InputGroup": {
81
+ "name": "InputGroup",
82
+ "description": "InputGroup sub-component",
83
+ "props": {
84
+ "className": {
85
+ "type": "string",
86
+ "optional": true
87
+ },
88
+ "size": {
89
+ "type": "KumoAutocompleteSize",
90
+ "optional": true
91
+ },
92
+ "placeholder": {
93
+ "type": "string",
94
+ "optional": true
95
+ }
96
+ }
97
+ },
98
+ "Content": {
99
+ "name": "Content",
100
+ "description": "Content sub-component",
101
+ "props": {
102
+ "children": {
103
+ "type": "ReactNode",
104
+ "optional": true
105
+ },
106
+ "className": {
107
+ "type": "string",
108
+ "optional": true
109
+ },
110
+ "align": {
111
+ "type": "AutocompleteBase.Positioner.Props[\"align\"]",
112
+ "optional": true
113
+ },
114
+ "alignOffset": {
115
+ "type": "AutocompleteBase.Positioner.Props[\"alignOffset\"]",
116
+ "optional": true
117
+ },
118
+ "side": {
119
+ "type": "AutocompleteBase.Positioner.Props[\"side\"]",
120
+ "optional": true
121
+ },
122
+ "sideOffset": {
123
+ "type": "AutocompleteBase.Positioner.Props[\"sideOffset\"]",
124
+ "optional": true
125
+ }
126
+ }
127
+ },
128
+ "Item": {
129
+ "name": "Item",
130
+ "description": "Item sub-component",
131
+ "props": {}
132
+ },
133
+ "GroupLabel": {
134
+ "name": "GroupLabel",
135
+ "description": "GroupLabel sub-component",
136
+ "props": {}
137
+ },
138
+ "Group": {
139
+ "name": "Group",
140
+ "description": "Group sub-component",
141
+ "props": {}
142
+ },
143
+ "Separator": {
144
+ "name": "Separator",
145
+ "description": "Separator sub-component",
146
+ "props": {}
147
+ },
148
+ "List": {
149
+ "name": "List",
150
+ "description": "List sub-component",
151
+ "props": {}
152
+ },
153
+ "Empty": {
154
+ "name": "Empty",
155
+ "description": "Empty sub-component (wraps AutocompleteBase)",
156
+ "props": {},
157
+ "isPassThrough": true,
158
+ "baseComponent": "AutocompleteBase.Empty"
159
+ },
160
+ "Collection": {
161
+ "name": "Collection",
162
+ "description": "Collection sub-component (wraps AutocompleteBase)",
163
+ "props": {},
164
+ "isPassThrough": true,
165
+ "baseComponent": "AutocompleteBase.Collection"
166
+ }
167
+ }
168
+ },
4
169
  "Badge": {
5
170
  "name": "Badge",
6
171
  "type": "component",
@@ -368,21 +533,20 @@
368
533
  "outline": "Bordered button with transparent background"
369
534
  },
370
535
  "classes": {
371
- "primary": "bg-kumo-brand !text-white hover:bg-kumo-brand-hover focus:bg-kumo-brand-hover disabled:bg-kumo-brand/50",
372
- "secondary": "bg-kumo-base !text-kumo-default ring not-disabled:hover:border-secondary! not-disabled:hover:bg-kumo-tint disabled:bg-kumo-base/50 disabled:!text-kumo-default/70 ring-kumo-hairline data-[state=open]:bg-kumo-base",
536
+ "primary": "bg-kumo-brand !text-white hover:bg-kumo-brand-hover disabled:bg-kumo-brand/50",
537
+ "secondary": "bg-kumo-base !text-kumo-default ring not-disabled:hover:bg-kumo-tint disabled:bg-kumo-base/50 disabled:!text-kumo-default/70 ring-kumo-hairline data-[state=open]:bg-kumo-base",
373
538
  "ghost": "text-kumo-default hover:bg-kumo-tint shadow-none bg-inherit",
374
539
  "destructive": "bg-kumo-danger !text-white hover:bg-kumo-danger/70",
375
- "secondary-destructive": "bg-kumo-base !text-kumo-danger ring not-disabled:hover:border-secondary! not-disabled:hover:bg-kumo-base disabled:bg-kumo-base/50 disabled:!text-kumo-danger/70 ring-kumo-hairline data-[state=open]:bg-kumo-base",
540
+ "secondary-destructive": "bg-kumo-base !text-kumo-danger ring not-disabled:hover:bg-kumo-base disabled:bg-kumo-base/50 disabled:!text-kumo-danger/70 ring-kumo-hairline data-[state=open]:bg-kumo-base",
376
541
  "outline": "bg-transparent text-kumo-default ring ring-kumo-hairline"
377
542
  },
378
543
  "stateClasses": {
379
544
  "primary": {
380
545
  "hover": "hover:bg-kumo-brand-hover",
381
- "focus": "focus:bg-kumo-brand-hover",
382
546
  "disabled": "disabled:bg-kumo-brand/50"
383
547
  },
384
548
  "secondary": {
385
- "not-disabled": "not-disabled:hover:border-secondary! not-disabled:hover:bg-kumo-tint",
549
+ "not-disabled": "not-disabled:hover:bg-kumo-tint",
386
550
  "disabled": "disabled:bg-kumo-base/50 disabled:!text-kumo-default/70",
387
551
  "data-state": "data-[state=open]:bg-kumo-base"
388
552
  },
@@ -393,7 +557,7 @@
393
557
  "hover": "hover:bg-kumo-danger/70"
394
558
  },
395
559
  "secondary-destructive": {
396
- "not-disabled": "not-disabled:hover:border-secondary! not-disabled:hover:bg-kumo-base",
560
+ "not-disabled": "not-disabled:hover:bg-kumo-base",
397
561
  "disabled": "disabled:bg-kumo-base/50 disabled:!text-kumo-danger/70",
398
562
  "data-state": "data-[state=open]:bg-kumo-base"
399
563
  }
@@ -466,7 +630,8 @@
466
630
  "<Button variant=\"primary\" loading>\n Loading...\n </Button>",
467
631
  "<Button variant=\"secondary\" disabled>\n Disabled\n </Button>",
468
632
  "<Button variant=\"secondary\">Click me</Button>",
469
- "<div className=\"flex flex-wrap items-center gap-3\">\n <Button variant=\"secondary\" title=\"Create a new Worker\">\n Create Worker\n </Button>\n <Button\n variant=\"secondary\"\n shape=\"square\"\n icon={PlusIcon}\n aria-label=\"Add item\"\n title=\"Add item\"\n />\n </div>"
633
+ "<div className=\"flex flex-wrap items-center gap-3\">\n <Button variant=\"secondary\" title=\"Create a new Worker\">\n Create Worker\n </Button>\n <Button\n variant=\"secondary\"\n shape=\"square\"\n icon={PlusIcon}\n aria-label=\"Add item\"\n title=\"Add item\"\n />\n </div>",
634
+ "<div className=\"flex flex-wrap items-center gap-3\">\n <LinkButton href=\"/components/link\" variant=\"secondary\">\n Read Link docs\n </LinkButton>\n <LinkButton\n href=\"https://developers.cloudflare.com\"\n variant=\"ghost\"\n icon={ArrowSquareOutIcon}\n external\n >\n Cloudflare Docs\n </LinkButton>\n </div>"
470
635
  ],
471
636
  "colors": [
472
637
  "bg-kumo-base",
@@ -474,6 +639,8 @@
474
639
  "bg-kumo-brand-hover",
475
640
  "bg-kumo-danger",
476
641
  "bg-kumo-tint",
642
+ "ring-kumo-brand",
643
+ "ring-kumo-focus",
477
644
  "ring-kumo-hairline",
478
645
  "text-kumo-danger",
479
646
  "text-kumo-default",
@@ -500,12 +667,12 @@
500
667
  "error": "Error state for validation failures"
501
668
  },
502
669
  "classes": {
503
- "default": "[&:focus-within>span]:ring-kumo-hairline [&:hover>span]:ring-kumo-hairline",
670
+ "default": "[&:focus-within>span]:ring-kumo-focus [&:hover>span]:ring-kumo-hairline",
504
671
  "error": "[&>span]:ring-kumo-danger"
505
672
  },
506
673
  "stateClasses": {
507
674
  "default": {
508
- "focus": "[&:focus-within>span]:ring-kumo-hairline",
675
+ "focus": "[&:focus-within>span]:ring-kumo-focus",
509
676
  "hover": "[&:hover>span]:ring-kumo-hairline"
510
677
  }
511
678
  },
@@ -555,10 +722,6 @@
555
722
  "type": "string",
556
723
  "optional": true,
557
724
  "description": "Additional class name"
558
- },
559
- "onValueChange": {
560
- "type": "(checked: boolean) => void",
561
- "description": "Callback when checkbox value changes"
562
725
  }
563
726
  },
564
727
  "examples": [
@@ -570,13 +733,17 @@
570
733
  "<Checkbox label=\"Disabled option\" disabled />",
571
734
  "<Checkbox label=\"Invalid option\" variant=\"error\" />",
572
735
  "<Checkbox.Group\n legend=\"Email preferences\"\n description=\"Choose how you'd like to receive updates\"\n value={preferences}\n onValueChange={setPreferences}\n >\n <Checkbox.Item value=\"email\" label=\"Email notifications\" />\n <Checkbox.Item value=\"sms\" label=\"SMS notifications\" />\n <Checkbox.Item value=\"push\" label=\"Push notifications\" />\n </Checkbox.Group>",
736
+ "<Checkbox.Group value={preferences} onValueChange={setPreferences}>\n <Checkbox.Legend className=\"sr-only\">\n Notification preferences\n </Checkbox.Legend>\n <Checkbox.Item value=\"email\" label=\"Email notifications\" />\n <Checkbox.Item value=\"sms\" label=\"SMS notifications\" />\n <Checkbox.Item value=\"push\" label=\"Push notifications\" />\n </Checkbox.Group>",
737
+ "<Checkbox.Group value={preferences} onValueChange={setPreferences}>\n <Checkbox.Legend className=\"text-sm font-normal text-kumo-subtle\">\n Notification preferences\n </Checkbox.Legend>\n <Checkbox.Item value=\"email\" label=\"Email notifications\" />\n <Checkbox.Item value=\"sms\" label=\"SMS notifications\" />\n <Checkbox.Item value=\"push\" label=\"Push notifications\" />\n </Checkbox.Group>",
573
738
  "<Checkbox.Group\n legend=\"Required preferences\"\n error=\"Please select at least one notification method\"\n value={[]}\n onValueChange={() => {}}\n >\n <Checkbox.Item value=\"email\" label=\"Email\" variant=\"error\" />\n <Checkbox.Item value=\"sms\" label=\"SMS\" variant=\"error\" />\n </Checkbox.Group>"
574
739
  ],
575
740
  "colors": [
576
741
  "bg-kumo-base",
577
742
  "bg-kumo-contrast",
743
+ "ring-kumo-brand",
578
744
  "ring-kumo-contrast",
579
745
  "ring-kumo-danger",
746
+ "ring-kumo-focus",
580
747
  "ring-kumo-hairline",
581
748
  "text-kumo-danger",
582
749
  "text-kumo-default",
@@ -595,7 +762,7 @@
595
762
  "props": {
596
763
  "legend": {
597
764
  "type": "string",
598
- "required": true
765
+ "optional": true
599
766
  },
600
767
  "children": {
601
768
  "type": "ReactNode",
@@ -630,6 +797,20 @@
630
797
  "optional": true
631
798
  }
632
799
  }
800
+ },
801
+ "Legend": {
802
+ "name": "Legend",
803
+ "description": "Legend sub-component",
804
+ "props": {
805
+ "children": {
806
+ "type": "ReactNode",
807
+ "required": true
808
+ },
809
+ "className": {
810
+ "type": "string",
811
+ "optional": true
812
+ }
813
+ }
633
814
  }
634
815
  },
635
816
  "styling": {
@@ -740,8 +921,10 @@
740
921
  ],
741
922
  "colors": [
742
923
  "bg-kumo-base",
743
- "border-kumo-hairline",
924
+ "border-kumo-line",
744
925
  "outline-kumo-fill",
926
+ "ring-kumo-brand",
927
+ "ring-kumo-focus",
745
928
  "text-kumo-default"
746
929
  ],
747
930
  "styling": {
@@ -2040,28 +2223,14 @@
2040
2223
  "Collapsible": {
2041
2224
  "name": "Collapsible",
2042
2225
  "type": "component",
2043
- "description": "Collapsible component for showing/hiding content. Features: - Animated chevron indicator (rotates 180° when open) - Accessible with aria-expanded and aria-controls - Content panel with left border accent",
2226
+ "description": "Collapsible — a composable disclosure component for showing/hiding content. Built on Base UI's Collapsible with full composition support. ## Basic Usage ```tsx const [open, setOpen] = useState(false); <Collapsible.Root open={open} onOpenChange={setOpen}> <Collapsible.Trigger render={<Button variant=\"ghost\" />}> Show details </Collapsible.Trigger> <Collapsible.Panel className=\"mt-2\"> <Text>Hidden content revealed when expanded.</Text> </Collapsible.Panel> </Collapsible.Root> ``` ## With Default Styling Use `DefaultTrigger` and `DefaultPanel` for the classic Kumo style: ```tsx <Collapsible.Root> <Collapsible.DefaultTrigger>Show details</Collapsible.DefaultTrigger> <Collapsible.DefaultPanel> <Text>Content with border-left accent</Text> </Collapsible.DefaultPanel> </Collapsible.Root> ``` ## Controlled Accordion Pattern ```tsx const [activeIndex, setActiveIndex] = useState<number | null>(null); {items.map((item, i) => ( <Collapsible.Root key={i} open={activeIndex === i} onOpenChange={(open) => setActiveIndex(open ? i : null)} > <Collapsible.DefaultTrigger>{item.title}</Collapsible.DefaultTrigger> <Collapsible.DefaultPanel>{item.content}</Collapsible.DefaultPanel> </Collapsible.Root> ))} ```",
2044
2227
  "importPath": "@cloudflare/kumo",
2045
2228
  "category": "Display",
2046
2229
  "props": {
2047
- "children": {
2048
- "type": "ReactNode",
2049
- "optional": true
2050
- },
2051
- "label": {
2052
- "type": "string",
2053
- "required": true,
2054
- "description": "Text label displayed in the trigger button"
2055
- },
2056
- "open": {
2057
- "type": "boolean",
2058
- "optional": true,
2059
- "description": "Whether the collapsible content is visible"
2060
- },
2061
2230
  "className": {
2062
2231
  "type": "string",
2063
2232
  "optional": true,
2064
- "description": "Additional CSS classes for the content panel"
2233
+ "description": "Additional CSS classes"
2065
2234
  },
2066
2235
  "onOpenChange": {
2067
2236
  "type": "(open: boolean) => void",
@@ -2069,14 +2238,76 @@
2069
2238
  }
2070
2239
  },
2071
2240
  "examples": [
2072
- "<div className=\"w-full\">\n <Collapsible label=\"What is Kumo?\" open={isOpen} onOpenChange={setIsOpen}>\n Kumo is Cloudflare's new design system.\n </Collapsible>\n </div>",
2073
- "<div className=\"w-full\">\n <Collapsible label=\"What is Kumo?\" open={isOpen} onOpenChange={setIsOpen}>\n Kumo is Cloudflare's new design system.\n </Collapsible>\n </div>",
2074
- "<div className=\"w-full space-y-2\">\n <Collapsible label=\"What is Kumo?\" open={open1} onOpenChange={setOpen1}>\n Kumo is Cloudflare's new design system.\n </Collapsible>\n <Collapsible\n label=\"How do I use it?\"\n open={open2}\n onOpenChange={setOpen2}\n >\n Install the components and import them into your project.\n </Collapsible>\n <Collapsible\n label=\"Is it open source?\"\n open={open3}\n onOpenChange={setOpen3}\n >\n Check the repository for license information.\n </Collapsible>\n </div>"
2241
+ "<div className=\"w-full\">\n <Collapsible.Root open={isOpen} onOpenChange={setIsOpen}>\n <Collapsible.DefaultTrigger>What is Kumo?</Collapsible.DefaultTrigger>\n <Collapsible.DefaultPanel>\n <Text>Kumo is Cloudflare's new design system.</Text>\n </Collapsible.DefaultPanel>\n </Collapsible.Root>\n </div>",
2242
+ "<div className=\"w-full\">\n <Collapsible.Root open={isOpen} onOpenChange={setIsOpen}>\n <Collapsible.DefaultTrigger>What is Kumo?</Collapsible.DefaultTrigger>\n <Collapsible.DefaultPanel>\n <Text>Kumo is Cloudflare's new design system.</Text>\n </Collapsible.DefaultPanel>\n </Collapsible.Root>\n </div>",
2243
+ "<div className=\"w-full space-y-2\">\n <Collapsible.Root open={open1} onOpenChange={setOpen1}>\n <Collapsible.DefaultTrigger>What is Kumo?</Collapsible.DefaultTrigger>\n <Collapsible.DefaultPanel>\n <Text>Kumo is Cloudflare's new design system.</Text>\n </Collapsible.DefaultPanel>\n </Collapsible.Root>\n <Collapsible.Root open={open2} onOpenChange={setOpen2}>\n <Collapsible.DefaultTrigger>How do I use it?</Collapsible.DefaultTrigger>\n <Collapsible.DefaultPanel>\n <Text>Install the components and import them into your project.</Text>\n </Collapsible.DefaultPanel>\n </Collapsible.Root>\n <Collapsible.Root open={open3} onOpenChange={setOpen3}>\n <Collapsible.DefaultTrigger>Is it open source?</Collapsible.DefaultTrigger>\n <Collapsible.DefaultPanel>\n <Text>Check the repository for license information.</Text>\n </Collapsible.DefaultPanel>\n </Collapsible.Root>\n </div>",
2244
+ "<div className=\"w-full\">\n <Collapsible.Root open={isOpen} onOpenChange={setIsOpen}>\n <Collapsible.Trigger\n render={<Button variant=\"secondary\" size=\"sm\" />}\n >\n {isOpen ? \"Hide details\" : \"Show details\"}\n </Collapsible.Trigger>\n <Collapsible.Panel className=\"mt-3 rounded-lg bg-kumo-tint p-4\">\n <Text>\n This panel uses custom styling instead of the default border-left accent.\n </Text>\n </Collapsible.Panel>\n </Collapsible.Root>\n </div>",
2245
+ "<div className=\"w-full space-y-2\">\n {items.map((item, i) => (\n <Collapsible.Root\n key={i}\n open={activeIndex === i}\n onOpenChange={(open) => setActiveIndex(open ? i : null)}\n >\n <Collapsible.DefaultTrigger>{item.title}</Collapsible.DefaultTrigger>\n <Collapsible.DefaultPanel>\n <Text>{item.content}</Text>\n </Collapsible.DefaultPanel>\n </Collapsible.Root>\n ))}\n </div>"
2075
2246
  ],
2076
2247
  "colors": [
2077
2248
  "border-kumo-fill",
2078
2249
  "text-kumo-link"
2079
- ]
2250
+ ],
2251
+ "subComponents": {
2252
+ "Root": {
2253
+ "name": "Root",
2254
+ "description": "Root sub-component",
2255
+ "props": {
2256
+ "className": {
2257
+ "type": "string",
2258
+ "optional": true
2259
+ }
2260
+ }
2261
+ },
2262
+ "Trigger": {
2263
+ "name": "Trigger",
2264
+ "description": "Trigger sub-component",
2265
+ "props": {
2266
+ "className": {
2267
+ "type": "string",
2268
+ "optional": true
2269
+ }
2270
+ }
2271
+ },
2272
+ "Panel": {
2273
+ "name": "Panel",
2274
+ "description": "Panel sub-component",
2275
+ "props": {
2276
+ "className": {
2277
+ "type": "string",
2278
+ "optional": true
2279
+ }
2280
+ }
2281
+ },
2282
+ "DefaultTrigger": {
2283
+ "name": "DefaultTrigger",
2284
+ "description": "DefaultTrigger sub-component",
2285
+ "props": {
2286
+ "children": {
2287
+ "type": "ReactNode",
2288
+ "required": true
2289
+ },
2290
+ "className": {
2291
+ "type": "string",
2292
+ "optional": true
2293
+ }
2294
+ }
2295
+ },
2296
+ "DefaultPanel": {
2297
+ "name": "DefaultPanel",
2298
+ "description": "DefaultPanel sub-component",
2299
+ "props": {
2300
+ "children": {
2301
+ "type": "ReactNode",
2302
+ "required": true
2303
+ },
2304
+ "className": {
2305
+ "type": "string",
2306
+ "optional": true
2307
+ }
2308
+ }
2309
+ }
2310
+ }
2080
2311
  },
2081
2312
  "Combobox": {
2082
2313
  "name": "Combobox",
@@ -2176,6 +2407,7 @@
2176
2407
  "<div className=\"flex gap-2\">\n <Combobox\n value={value}\n onValueChange={setValue}\n items={bots}\n isItemEqualToValue={(bot: BotItem, selected: BotItem) =>\n bot.value === selected.value\n }\n multiple\n >\n <Combobox.TriggerMultipleWithInput\n className=\"w-[400px]\"\n placeholder=\"Select bots\"\n renderItem={(selected: BotItem) => (\n <Combobox.Chip key={selected.value}>{selected.label}</Combobox.Chip>\n )}\n inputSide=\"right\"\n />\n <Combobox.Content className=\"max-h-[200px] min-w-auto overflow-y-auto\">\n <Combobox.Empty />\n <Combobox.List>\n {(item: BotItem) => (\n <Combobox.Item key={item.value} value={item}>\n <div className=\"flex gap-2\">\n <Text>{item.label}</Text>\n <Text variant=\"secondary\">{item.author}</Text>\n </div>\n </Combobox.Item>\n )}\n </Combobox.List>\n </Combobox.Content>\n </Combobox>\n <Button variant=\"primary\">Submit</Button>\n </div>",
2177
2408
  "<div className=\"w-80\">\n <Combobox\n items={databases}\n value={value}\n onValueChange={setValue}\n label=\"Database\"\n description=\"Select your preferred database\"\n >\n <Combobox.TriggerInput placeholder=\"Select database\" />\n <Combobox.Content>\n <Combobox.Empty />\n <Combobox.List>\n {(item: DatabaseItem) => (\n <Combobox.Item key={item.value} value={item}>\n {item.label}\n </Combobox.Item>\n )}\n </Combobox.List>\n </Combobox.Content>\n </Combobox>\n </div>",
2178
2409
  "<div className=\"flex flex-wrap gap-4 items-start\">\n <Combobox value=\"Apple\" items={fruits} disabled>\n <Combobox.TriggerInput\n className=\"w-[200px]\"\n placeholder=\"Select fruit\"\n />\n <Combobox.Content>\n <Combobox.Empty />\n <Combobox.List>\n {(item: string) => (\n <Combobox.Item key={item} value={item}>\n {item}\n </Combobox.Item>\n )}\n </Combobox.List>\n </Combobox.Content>\n </Combobox>\n\n <Combobox value={languages[0]} items={languages} disabled>\n <Combobox.TriggerValue className=\"w-[200px]\" />\n <Combobox.Content>\n <Combobox.Input placeholder=\"Search\" />\n <Combobox.Empty />\n <Combobox.List>\n {(item: Language) => (\n <Combobox.Item key={item.value} value={item}>\n {item.emoji} {item.label}\n </Combobox.Item>\n )}\n </Combobox.List>\n </Combobox.Content>\n </Combobox>\n </div>",
2410
+ "<div className=\"w-80\">\n <Combobox value={value} onValueChange={setValue} items={items}>\n <Combobox.TriggerInput placeholder=\"Select database\" />\n <Combobox.Content>\n <Combobox.Empty />\n <Combobox.List>\n {(item: DatabaseItemWithDisabled) => (\n <Combobox.Item\n key={item.value}\n value={item}\n disabled={item.disabled}\n >\n <span>\n {item.label}\n {item.reason && (\n <Text variant=\"secondary\" size=\"xs\" as=\"span\">\n {\" — \"}\n {item.reason}\n </Text>\n )}\n </span>\n </Combobox.Item>\n )}\n </Combobox.List>\n </Combobox.Content>\n </Combobox>\n </div>",
2179
2411
  "<div className=\"w-80\">\n <Combobox\n items={databases}\n value={value}\n onValueChange={setValue}\n label=\"Database\"\n error={{ message: \"Please select a database\", match: true }}\n >\n <Combobox.TriggerInput placeholder=\"Select database\" />\n <Combobox.Content>\n <Combobox.Empty />\n <Combobox.List>\n {(item: DatabaseItem) => (\n <Combobox.Item key={item.value} value={item}>\n {item.label}\n </Combobox.Item>\n )}\n </Combobox.List>\n </Combobox.Content>\n </Combobox>\n </div>",
2180
2412
  "<div className=\"flex flex-wrap items-center gap-4\">\n <Combobox\n size=\"sm\"\n value={smValue}\n onValueChange={(v) => setSmValue(v as string | null)}\n items={fruits.slice(0, 8)}\n >\n <Combobox.TriggerInput placeholder=\"Small (sm)\" />\n <Combobox.Content>\n <Combobox.Empty />\n <Combobox.List>\n {(item: string) => (\n <Combobox.Item key={item} value={item}>\n {item}\n </Combobox.Item>\n )}\n </Combobox.List>\n </Combobox.Content>\n </Combobox>\n <Combobox\n size=\"base\"\n value={baseValue}\n onValueChange={(v) => setBaseValue(v as string | null)}\n items={fruits.slice(0, 8)}\n >\n <Combobox.TriggerInput placeholder=\"Base (default)\" />\n <Combobox.Content>\n <Combobox.Empty />\n <Combobox.List>\n {(item: string) => (\n <Combobox.Item key={item} value={item}>\n {item}\n </Combobox.Item>\n )}\n </Combobox.List>\n </Combobox.Content>\n </Combobox>\n </div>",
2181
2413
  "<div className=\"flex flex-wrap items-center gap-4\">\n <Combobox\n size=\"sm\"\n value={smValue}\n onValueChange={(v) => setSmValue(v as Language)}\n items={languages}\n >\n <Combobox.TriggerValue className=\"w-[160px]\" />\n <Combobox.Content>\n <Combobox.Input placeholder=\"Search\" />\n <Combobox.Empty />\n <Combobox.List>\n {(item: Language) => (\n <Combobox.Item key={item.value} value={item}>\n {item.emoji} {item.label}\n </Combobox.Item>\n )}\n </Combobox.List>\n </Combobox.Content>\n </Combobox>\n <Combobox\n size=\"base\"\n value={baseValue}\n onValueChange={(v) => setBaseValue(v as Language)}\n items={languages}\n >\n <Combobox.TriggerValue className=\"w-[180px]\" />\n <Combobox.Content>\n <Combobox.Input placeholder=\"Search\" />\n <Combobox.Empty />\n <Combobox.List>\n {(item: Language) => (\n <Combobox.Item key={item.value} value={item}>\n {item.emoji} {item.label}\n </Combobox.Item>\n )}\n </Combobox.List>\n </Combobox.Content>\n </Combobox>\n </div>"
@@ -2318,6 +2550,7 @@
2318
2550
  "<div className=\"flex flex-col items-start gap-4\">\n <Button onClick={() => setOpen(true)}>Open Command Palette</Button>\n {selectedItem && (\n <p className=\"text-sm text-kumo-subtle\">\n Last selected:{\" \"}\n <span className=\"text-kumo-default\">{selectedItem}</span>\n </p>\n )}\n\n <CommandPalette.Root\n open={open}\n onOpenChange={setOpen}\n items={filteredGroups}\n value={search}\n onValueChange={setSearch}\n itemToStringValue={(group) => group.label}\n onSelect={(item, { newTab }) => {\n console.log(\"Selected:\", item.title, newTab ? \"(new tab)\" : \"\");\n handleSelect(item);\n }}\n getSelectableItems={getSelectableItems}\n >\n <CommandPalette.Input placeholder=\"Type a command or search...\" />\n <CommandPalette.List>\n <CommandPalette.Results>\n {(group: CommandGroup) => (\n <CommandPalette.Group key={group.id} items={group.items}>\n <CommandPalette.GroupLabel>\n {group.label}\n </CommandPalette.GroupLabel>\n <CommandPalette.Items>\n {(item: CommandItem) => (\n <CommandPalette.Item\n key={item.id}\n value={item}\n onClick={() => handleSelect(item)}\n >\n <span className=\"flex items-center gap-3\">\n {item.icon && (\n <span className=\"text-kumo-subtle\">{item.icon}</span>\n )}\n <span>{item.title}</span>\n </span>\n </CommandPalette.Item>\n )}\n </CommandPalette.Items>\n </CommandPalette.Group>\n )}\n </CommandPalette.Results>\n <CommandPalette.Empty>No commands found</CommandPalette.Empty>\n </CommandPalette.List>\n <CommandPalette.Footer>\n <span className=\"flex items-center gap-2\">\n <kbd className=\"rounded border border-kumo-hairline bg-kumo-base px-1.5 py-0.5 text-[10px]\">\n ↑↓\n </kbd>\n <span>Navigate</span>\n </span>\n <span className=\"flex items-center gap-2\">\n <kbd className=\"rounded border border-kumo-hairline bg-kumo-base px-1.5 py-0.5 text-[10px]\">\n ↵\n </kbd>\n <span>Select</span>\n </span>\n </CommandPalette.Footer>\n </CommandPalette.Root>\n </div>",
2319
2551
  "<div>\n <Button onClick={() => setOpen(true)}>Open Simple Palette</Button>\n\n <CommandPalette.Root\n open={open}\n onOpenChange={setOpen}\n items={simpleItems}\n value={search}\n onValueChange={setSearch}\n itemToStringValue={(item) => item.title}\n onSelect={(item) => {\n console.log(\"Selected:\", item.title);\n setOpen(false);\n }}\n getSelectableItems={(items) => items}\n >\n <CommandPalette.Input placeholder=\"Search actions...\" />\n <CommandPalette.List>\n <CommandPalette.Results>\n {(item: SimpleItem) => (\n <CommandPalette.Item\n key={item.id}\n value={item}\n onClick={() => {\n console.log(\"Clicked:\", item.title);\n setOpen(false);\n }}\n >\n {item.title}\n </CommandPalette.Item>\n )}\n </CommandPalette.Results>\n <CommandPalette.Empty>No actions found</CommandPalette.Empty>\n </CommandPalette.List>\n </CommandPalette.Root>\n </div>",
2320
2552
  "<div>\n <Button onClick={handleOpen}>Open with Loading</Button>\n\n <CommandPalette.Root\n open={open}\n onOpenChange={setOpen}\n items={loading ? [] : filteredGroups}\n value={search}\n onValueChange={setSearch}\n itemToStringValue={(group) => group.label}\n getSelectableItems={getSelectableItems}\n >\n <CommandPalette.Input placeholder=\"Search...\" />\n <CommandPalette.List>\n {loading ? (\n <CommandPalette.Loading />\n ) : (\n <>\n <CommandPalette.Results>\n {(group: CommandGroup) => (\n <CommandPalette.Group key={group.id} items={group.items}>\n <CommandPalette.GroupLabel>\n {group.label}\n </CommandPalette.GroupLabel>\n <CommandPalette.Items>\n {(item: CommandItem) => (\n <CommandPalette.Item\n key={item.id}\n value={item}\n onClick={() => setOpen(false)}\n >\n <span className=\"flex items-center gap-3\">\n {item.icon && (\n <span className=\"text-kumo-subtle\">\n {item.icon}\n </span>\n )}\n <span>{item.title}</span>\n </span>\n </CommandPalette.Item>\n )}\n </CommandPalette.Items>\n </CommandPalette.Group>\n )}\n </CommandPalette.Results>\n <CommandPalette.Empty>No results found</CommandPalette.Empty>\n </>\n )}\n </CommandPalette.List>\n </CommandPalette.Root>\n </div>",
2553
+ "<div className=\"flex flex-col items-start gap-4\">\n <Button onClick={() => setOpen(true)}>\n Open Palette (No Autocomplete)\n </Button>\n\n <CommandPalette.Root\n open={open}\n onOpenChange={setOpen}\n items={filteredGroups}\n value={search}\n onValueChange={setSearch}\n itemToStringValue={(group) => group.label}\n onSelect={(item) => {\n console.log(\"Selected:\", item.title);\n setOpen(false);\n setSearch(\"\");\n }}\n getSelectableItems={getSelectableItems}\n >\n <CommandPalette.Input\n placeholder=\"Search commands...\"\n autoComplete=\"off\"\n autoCorrect=\"off\"\n autoCapitalize=\"none\"\n spellCheck={false}\n data-1p-ignore=\"true\"\n data-lpignore=\"true\"\n />\n <CommandPalette.List>\n <CommandPalette.Results>\n {(group: CommandGroup) => (\n <CommandPalette.Group key={group.id} items={group.items}>\n <CommandPalette.GroupLabel>\n {group.label}\n </CommandPalette.GroupLabel>\n <CommandPalette.Items>\n {(item: CommandItem) => (\n <CommandPalette.Item\n key={item.id}\n value={item}\n onClick={() => {\n setOpen(false);\n setSearch(\"\");\n }}\n >\n <span className=\"flex items-center gap-3\">\n {item.icon && (\n <span className=\"text-kumo-subtle\">{item.icon}</span>\n )}\n <span>{item.title}</span>\n </span>\n </CommandPalette.Item>\n )}\n </CommandPalette.Items>\n </CommandPalette.Group>\n )}\n </CommandPalette.Results>\n <CommandPalette.Empty>No commands found</CommandPalette.Empty>\n </CommandPalette.List>\n </CommandPalette.Root>\n </div>",
2321
2554
  "<div>\n <Button onClick={() => setOpen(true)}>Open with ResultItem</Button>\n\n <CommandPalette.Root\n open={open}\n onOpenChange={setOpen}\n items={searchResults}\n value={search}\n onValueChange={setSearch}\n itemToStringValue={(item) => item.title}\n getSelectableItems={(items) => items}\n >\n <CommandPalette.Input placeholder=\"Search documentation...\" />\n <CommandPalette.List>\n <CommandPalette.Results>\n {(item: SearchResult) => (\n <CommandPalette.ResultItem\n key={item.id}\n value={item}\n title={item.title}\n breadcrumbs={item.breadcrumbs}\n icon={item.icon}\n onClick={() => {\n console.log(\"Navigate to:\", item.title);\n setOpen(false);\n }}\n />\n )}\n </CommandPalette.Results>\n <CommandPalette.Empty>No pages found</CommandPalette.Empty>\n </CommandPalette.List>\n <CommandPalette.Footer>\n <span className=\"flex items-center gap-2\">\n <kbd className=\"rounded border border-kumo-hairline bg-kumo-base px-1.5 py-0.5 text-[10px]\">\n ↑↓\n </kbd>\n <span>Navigate</span>\n </span>\n <span className=\"flex items-center gap-2\">\n <kbd className=\"rounded border border-kumo-hairline bg-kumo-base px-1.5 py-0.5 text-[10px]\">\n ⌘↵\n </kbd>\n <span>Open in new tab</span>\n </span>\n </CommandPalette.Footer>\n </CommandPalette.Root>\n </div>"
2322
2555
  ],
2323
2556
  "colors": [
@@ -2325,6 +2558,7 @@
2325
2558
  "bg-kumo-elevated",
2326
2559
  "bg-kumo-overlay",
2327
2560
  "bg-kumo-warning",
2561
+ "ring-kumo-brand",
2328
2562
  "ring-kumo-hairline",
2329
2563
  "text-kumo-default",
2330
2564
  "text-kumo-strong",
@@ -2433,6 +2667,7 @@
2433
2667
  "bg-kumo-fill",
2434
2668
  "bg-kumo-interact",
2435
2669
  "bg-kumo-overlay",
2670
+ "ring-kumo-focus",
2436
2671
  "text-kumo-default",
2437
2672
  "text-kumo-inverse",
2438
2673
  "text-kumo-strong",
@@ -2675,6 +2910,8 @@
2675
2910
  "bg-kumo-hairline",
2676
2911
  "bg-kumo-overlay",
2677
2912
  "bg-kumo-tint",
2913
+ "ring-kumo-brand",
2914
+ "ring-kumo-focus",
2678
2915
  "ring-kumo-line",
2679
2916
  "text-kumo-danger",
2680
2917
  "text-kumo-default"
@@ -3071,15 +3308,15 @@
3071
3308
  "error": "Error state for validation failures"
3072
3309
  },
3073
3310
  "classes": {
3074
- "default": "focus:ring-kumo-hairline",
3075
- "error": "!ring-kumo-danger focus:ring-kumo-danger"
3311
+ "default": "focus:ring-kumo-focus/50 focus:ring-[1.5px]",
3312
+ "error": "!ring-kumo-danger focus:ring-kumo-danger/50 focus:ring-[1.5px]"
3076
3313
  },
3077
3314
  "stateClasses": {
3078
3315
  "default": {
3079
- "focus": "focus:ring-kumo-hairline"
3316
+ "focus": "focus:ring-kumo-focus/50 focus:ring-[1.5px]"
3080
3317
  },
3081
3318
  "error": {
3082
- "focus": "focus:ring-kumo-danger"
3319
+ "focus": "focus:ring-kumo-danger/50 focus:ring-[1.5px]"
3083
3320
  }
3084
3321
  },
3085
3322
  "default": "default"
@@ -3103,7 +3340,8 @@
3103
3340
  "colors": [
3104
3341
  "bg-kumo-control",
3105
3342
  "ring-kumo-danger",
3106
- "ring-kumo-hairline",
3343
+ "ring-kumo-focus",
3344
+ "ring-kumo-line",
3107
3345
  "text-kumo-default",
3108
3346
  "text-kumo-subtle"
3109
3347
  ],
@@ -3158,40 +3396,206 @@
3158
3396
  }
3159
3397
  }
3160
3398
  },
3161
- "Label": {
3162
- "name": "Label",
3399
+ "InputGroup": {
3400
+ "name": "InputGroup",
3163
3401
  "type": "component",
3164
- "description": "Label component for form fields. Provides a standardized way to display labels with optional indicators: - Optional indicator: gray \"(optional)\" text when `showOptional={true}` - Tooltip: info icon with hover tooltip for additional context",
3402
+ "description": "InputGroup component",
3165
3403
  "importPath": "@cloudflare/kumo",
3166
- "category": "Other",
3404
+ "category": "Input",
3167
3405
  "props": {
3168
- "children": {
3406
+ "label": {
3169
3407
  "type": "ReactNode",
3170
3408
  "optional": true,
3171
3409
  "description": "The label content — can be a string or any React node."
3172
3410
  },
3173
- "showOptional": {
3411
+ "description": {
3412
+ "type": "ReactNode",
3413
+ "optional": true,
3414
+ "description": "Helper text displayed below the control (hidden when `error` is present)."
3415
+ },
3416
+ "error": {
3417
+ "type": "object",
3418
+ "optional": true,
3419
+ "description": "Validation error with a message and a browser `ValidityState` match key."
3420
+ },
3421
+ "required": {
3174
3422
  "type": "boolean",
3175
3423
  "optional": true,
3176
- "description": "When `true`, shows gray \"(optional)\" text after the label."
3424
+ "description": "When explicitly `false`, shows gray \"(optional)\" text after the label. When `true` or `undefined`, no indicator is shown."
3177
3425
  },
3178
- "tooltip": {
3426
+ "labelTooltip": {
3179
3427
  "type": "ReactNode",
3180
3428
  "optional": true,
3181
3429
  "description": "Tooltip content displayed next to the label via an info icon."
3182
3430
  },
3431
+ "children": {
3432
+ "type": "ReactNode",
3433
+ "optional": true
3434
+ },
3183
3435
  "className": {
3184
3436
  "type": "string",
3185
- "optional": true,
3186
- "description": "Additional CSS classes merged via `cn()`."
3437
+ "optional": true
3187
3438
  },
3188
- "htmlFor": {
3439
+ "id": {
3189
3440
  "type": "string",
3190
- "optional": true,
3191
- "description": "The id of the form element this label is associated with"
3441
+ "optional": true
3192
3442
  },
3193
- "asContent": {
3194
- "type": "boolean",
3443
+ "lang": {
3444
+ "type": "string",
3445
+ "optional": true
3446
+ },
3447
+ "title": {
3448
+ "type": "string",
3449
+ "optional": true
3450
+ },
3451
+ "size": {
3452
+ "type": "enum",
3453
+ "optional": true,
3454
+ "values": [
3455
+ "xs",
3456
+ "sm",
3457
+ "base",
3458
+ "lg"
3459
+ ],
3460
+ "descriptions": {
3461
+ "xs": "Extra small size.",
3462
+ "sm": "Small size.",
3463
+ "base": "Default size.",
3464
+ "lg": "Large size."
3465
+ },
3466
+ "classes": {
3467
+ "xs": "h-6 text-xs",
3468
+ "sm": "h-7 text-xs",
3469
+ "base": "h-9 text-base",
3470
+ "lg": "h-11 text-base"
3471
+ },
3472
+ "default": "base"
3473
+ },
3474
+ "disabled": {
3475
+ "type": "boolean",
3476
+ "optional": true
3477
+ }
3478
+ },
3479
+ "examples": [
3480
+ "<div className=\"w-full max-w-2xs\">\n <InputGroup>\n <InputGroup.Input\n maxLength={20}\n onChange={handleChange}\n value={value}\n />\n <InputGroup.Suffix>.workers.dev</InputGroup.Suffix>\n {status !== \"idle\" && (\n <InputGroup.Addon align=\"end\">\n {status === \"loading\" ? (\n <Loader />\n ) : (\n <CheckCircleIcon weight=\"duotone\" className=\"text-kumo-success\" />\n )}\n </InputGroup.Addon>\n )}\n </InputGroup>\n </div>",
3481
+ "<InputGroup className=\"w-full max-w-3xs\">\n <InputGroup.Addon>\n <LinkIcon />\n </InputGroup.Addon>\n <InputGroup.Input placeholder=\"Paste a link...\" aria-label=\"Link\" />\n </InputGroup>",
3482
+ "<div className=\"flex flex-col gap-4\">\n <InputGroup className=\"w-full max-w-3xs\">\n <InputGroup.Addon>@</InputGroup.Addon>\n <InputGroup.Input placeholder=\"username\" aria-label=\"Username\" />\n </InputGroup>\n\n <InputGroup className=\"w-full max-w-3xs\">\n <InputGroup.Input placeholder=\"email\" aria-label=\"Email\" />\n <InputGroup.Addon align=\"end\">@example.com</InputGroup.Addon>\n </InputGroup>\n\n <InputGroup className=\"w-full max-w-3xs\">\n <InputGroup.Addon>/api/</InputGroup.Addon>\n <InputGroup.Input placeholder=\"endpoint\" aria-label=\"API path\" />\n <InputGroup.Addon align=\"end\">.json</InputGroup.Addon>\n </InputGroup>\n </div>",
3483
+ "<div className=\"flex flex-col gap-4\">\n <InputGroup className=\"w-full max-w-3xs\">\n <InputGroup.Input\n type={show ? \"text\" : \"password\"}\n defaultValue=\"password\"\n aria-label=\"Password\"\n />\n <InputGroup.Addon align=\"end\">\n <InputGroup.Button\n className=\"text-kumo-subtle\"\n icon={show ? EyeSlashIcon : EyeIcon}\n aria-label={show ? \"Hide password\" : \"Show password\"}\n onClick={() => setShow(!show)}\n />\n </InputGroup.Addon>\n </InputGroup>\n\n <InputGroup className=\"w-full max-w-3xs\">\n <InputGroup.Addon>\n <MagnifyingGlassIcon />\n </InputGroup.Addon>\n <InputGroup.Input\n value={searchValue}\n placeholder=\"Search\"\n aria-label=\"Search\"\n onChange={(e) => setSearchValue(e.target.value)}\n />\n {searchValue && (\n <InputGroup.Addon align=\"end\" className=\"pr-1\">\n <InputGroup.Button\n aria-label=\"Clear search\"\n onClick={() => setSearchValue(\"\")}\n >\n <XIcon />\n </InputGroup.Button>\n </InputGroup.Addon>\n )}\n <InputGroup.Button variant=\"secondary\" onClick={() => {}}>\n Search\n </InputGroup.Button>\n </InputGroup>\n </div>",
3484
+ "<InputGroup className=\"w-full max-w-2xs\">\n <InputGroup.Addon>\n <MagnifyingGlassIcon />\n </InputGroup.Addon>\n <InputGroup.Input\n placeholder=\"Search with query language...\"\n aria-label=\"Search\"\n />\n <InputGroup.Addon align=\"end\">\n <InputGroup.Button\n className=\"text-kumo-subtle\"\n icon={QuestionIcon}\n tooltip=\"Query language help\"\n onClick={() => {}}\n />\n </InputGroup.Addon>\n </InputGroup>",
3485
+ "<InputGroup className=\"w-full max-w-3xs\">\n <InputGroup.Addon>\n <MagnifyingGlassIcon />\n </InputGroup.Addon>\n <InputGroup.Input placeholder=\"Search...\" aria-label=\"Search\" />\n <InputGroup.Addon align=\"end\">\n <kbd className=\"bg-none! border-none!\">⌘K</kbd>\n </InputGroup.Addon>\n </InputGroup>",
3486
+ "<InputGroup className=\"w-full max-w-3xs\">\n <InputGroup.Input defaultValue=\"kumo\" aria-label=\"kumo\" />\n <InputGroup.Addon align=\"end\">\n <Loader />\n </InputGroup.Addon>\n </InputGroup>",
3487
+ "<div className=\"flex w-full max-w-2xs flex-col gap-4\">\n <InputGroup label=\"Subdomain\">\n <InputGroup.Input\n aria-label=\"Subdomain\"\n defaultValue=\"kumo\"\n maxLength={20}\n />\n <InputGroup.Suffix>.workers.dev</InputGroup.Suffix>\n <InputGroup.Addon align=\"end\">\n <CheckCircleIcon weight=\"duotone\" className=\"text-kumo-success\" />\n </InputGroup.Addon>\n </InputGroup>\n\n <InputGroup\n label=\"Subdomain\"\n error={{ message: \"This subdomain is unavailable\", match: true }}\n >\n <InputGroup.Input\n aria-label=\"Subdomain\"\n defaultValue=\"kumo\"\n maxLength={20}\n />\n <InputGroup.Suffix>.workers.dev</InputGroup.Suffix>\n <InputGroup.Addon align=\"end\">\n <XCircleIcon weight=\"duotone\" className=\"text-kumo-danger\" />\n </InputGroup.Addon>\n </InputGroup>\n </div>",
3488
+ "<div className=\"flex w-full max-w-3xs flex-col gap-4\">\n <InputGroup size=\"xs\" label=\"Extra Small\">\n <InputGroup.Addon>\n <MagnifyingGlassIcon />\n </InputGroup.Addon>\n <InputGroup.Input placeholder=\"Extra small input\" />\n <InputGroup.Addon align=\"end\">\n <InputGroup.Button\n className=\"text-kumo-subtle\"\n icon={QuestionIcon}\n shape=\"square\"\n aria-label=\"Help\"\n />\n </InputGroup.Addon>\n </InputGroup>\n\n <InputGroup size=\"sm\" label=\"Small\">\n <InputGroup.Addon>\n <MagnifyingGlassIcon />\n </InputGroup.Addon>\n <InputGroup.Input placeholder=\"Small input\" />\n <InputGroup.Addon align=\"end\">\n <InputGroup.Button\n className=\"text-kumo-subtle\"\n icon={QuestionIcon}\n shape=\"square\"\n aria-label=\"Help\"\n />\n </InputGroup.Addon>\n </InputGroup>\n\n <InputGroup label=\"Base (default)\">\n <InputGroup.Addon>\n <MagnifyingGlassIcon />\n </InputGroup.Addon>\n <InputGroup.Input placeholder=\"Base input\" />\n <InputGroup.Addon align=\"end\">\n <InputGroup.Button\n className=\"text-kumo-subtle\"\n icon={QuestionIcon}\n shape=\"square\"\n aria-label=\"Help\"\n />\n </InputGroup.Addon>\n </InputGroup>\n\n <InputGroup size=\"lg\" label=\"Large\">\n <InputGroup.Addon>\n <MagnifyingGlassIcon />\n </InputGroup.Addon>\n <InputGroup.Input placeholder=\"Large input\" />\n <InputGroup.Addon align=\"end\">\n <InputGroup.Button\n className=\"text-kumo-subtle\"\n icon={QuestionIcon}\n shape=\"square\"\n aria-label=\"Help\"\n />\n </InputGroup.Addon>\n </InputGroup>\n </div>",
3489
+ "<div className=\"flex w-full max-w-3xs flex-col gap-4\">\n <InputGroup\n label=\"Error State\"\n error={{ message: \"Please enter a valid email address\", match: true }}\n >\n <InputGroup.Input type=\"email\" defaultValue=\"invalid-email\" />\n <InputGroup.Addon align=\"end\">@example.com</InputGroup.Addon>\n </InputGroup>\n\n <InputGroup label=\"Disabled\" disabled>\n <InputGroup.Addon>\n <MagnifyingGlassIcon />\n </InputGroup.Addon>\n <InputGroup.Input placeholder=\"Search...\" />\n </InputGroup>\n\n <InputGroup label=\"Optional Field\" required={false}>\n <InputGroup.Addon>$</InputGroup.Addon>\n <InputGroup.Input placeholder=\"0.00\" />\n </InputGroup>\n\n <InputGroup\n label=\"With Description\"\n description=\"Must be at least 8 characters\"\n labelTooltip=\"Your password is stored securely\"\n >\n <InputGroup.Input\n type={show ? \"text\" : \"password\"}\n placeholder=\"Password\"\n />\n <InputGroup.Addon align=\"end\">\n <InputGroup.Button\n className=\"text-kumo-subtle\"\n icon={show ? EyeSlashIcon : EyeIcon}\n aria-label={show ? \"Hide password\" : \"Show password\"}\n onClick={() => setShow(!show)}\n />\n </InputGroup.Addon>\n </InputGroup>\n </div>"
3490
+ ],
3491
+ "colors": [
3492
+ "border-kumo-line",
3493
+ "ring-kumo-danger",
3494
+ "ring-kumo-focus",
3495
+ "ring-kumo-line"
3496
+ ],
3497
+ "subComponents": {
3498
+ "Input": {
3499
+ "name": "Input",
3500
+ "description": "Input sub-component",
3501
+ "props": {}
3502
+ },
3503
+ "Button": {
3504
+ "name": "Button",
3505
+ "description": "Button sub-component",
3506
+ "props": {
3507
+ "tooltip": {
3508
+ "type": "ReactNode",
3509
+ "description": "When provided, wraps the button in a Tooltip. Automatically sets aria-label from a string value."
3510
+ },
3511
+ "tooltipSide": {
3512
+ "type": "\"top\" | \"right\" | \"bottom\" | \"left\"",
3513
+ "description": "Preferred side for the tooltip popup.",
3514
+ "default": "\"bottom\""
3515
+ },
3516
+ "variant": {
3517
+ "type": "\"primary\" | \"secondary\" | \"ghost\" | \"destructive\" | \"secondary-destructive\" | \"outline\"",
3518
+ "description": "Button visual style. Defaults to ghost.",
3519
+ "default": "\"ghost\""
3520
+ },
3521
+ "size": {
3522
+ "type": "\"xs\" | \"sm\" | \"base\" | \"lg\"",
3523
+ "description": "Button size.",
3524
+ "default": "\"sm\""
3525
+ }
3526
+ }
3527
+ },
3528
+ "Addon": {
3529
+ "name": "Addon",
3530
+ "description": "Addon sub-component",
3531
+ "props": {
3532
+ "align": {
3533
+ "type": "\"start\" | \"end\"",
3534
+ "description": "Position relative to the input.",
3535
+ "default": "\"start\""
3536
+ },
3537
+ "className": {
3538
+ "type": "string",
3539
+ "description": "Additional CSS classes."
3540
+ }
3541
+ }
3542
+ },
3543
+ "Suffix": {
3544
+ "name": "Suffix",
3545
+ "description": "Suffix sub-component",
3546
+ "props": {
3547
+ "className": {
3548
+ "type": "string",
3549
+ "description": "Additional CSS classes."
3550
+ }
3551
+ }
3552
+ },
3553
+ "Label": {
3554
+ "name": "Label",
3555
+ "description": "Label sub-component",
3556
+ "props": {}
3557
+ },
3558
+ "Description": {
3559
+ "name": "Description",
3560
+ "description": "Description sub-component",
3561
+ "props": {}
3562
+ }
3563
+ }
3564
+ },
3565
+ "Label": {
3566
+ "name": "Label",
3567
+ "type": "component",
3568
+ "description": "Label component for form fields. Provides a standardized way to display labels with optional indicators: - Optional indicator: gray \"(optional)\" text when `showOptional={true}` - Tooltip: info icon with hover tooltip for additional context",
3569
+ "importPath": "@cloudflare/kumo",
3570
+ "category": "Other",
3571
+ "props": {
3572
+ "children": {
3573
+ "type": "ReactNode",
3574
+ "optional": true,
3575
+ "description": "The label content — can be a string or any React node."
3576
+ },
3577
+ "showOptional": {
3578
+ "type": "boolean",
3579
+ "optional": true,
3580
+ "description": "When `true`, shows gray \"(optional)\" text after the label."
3581
+ },
3582
+ "tooltip": {
3583
+ "type": "ReactNode",
3584
+ "optional": true,
3585
+ "description": "Tooltip content displayed next to the label via an info icon."
3586
+ },
3587
+ "className": {
3588
+ "type": "string",
3589
+ "optional": true,
3590
+ "description": "Additional CSS classes merged via `cn()`."
3591
+ },
3592
+ "htmlFor": {
3593
+ "type": "string",
3594
+ "optional": true,
3595
+ "description": "The id of the form element this label is associated with"
3596
+ },
3597
+ "asContent": {
3598
+ "type": "boolean",
3195
3599
  "optional": true,
3196
3600
  "description": "When true, only renders the inline content (indicators, tooltip) without the outer label element with font styling. Useful when composed inside another label element that already provides the text styling."
3197
3601
  }
@@ -3219,7 +3623,7 @@
3219
3623
  "render": {
3220
3624
  "type": "ReactNode",
3221
3625
  "optional": true,
3222
- "description": "Allows you to replace the components HTML element with a different tag, or compose it with another component.\n\nAccepts a `ReactElement` or a function that returns the element to render."
3626
+ "description": "Allows you to replace the component's HTML element with a different tag, or compose it with another component.\n\nAccepts a `ReactElement` or a function that returns the element to render."
3223
3627
  },
3224
3628
  "children": {
3225
3629
  "type": "ReactNode",
@@ -3387,7 +3791,7 @@
3387
3791
  "render": {
3388
3792
  "type": "ReactNode",
3389
3793
  "optional": true,
3390
- "description": "Allows you to replace the components HTML element with a different tag, or compose it with another component.\n\nAccepts a `ReactElement` or a function that returns the element to render."
3794
+ "description": "Allows you to replace the component's HTML element with a different tag, or compose it with another component.\n\nAccepts a `ReactElement` or a function that returns the element to render."
3391
3795
  }
3392
3796
  },
3393
3797
  "examples": [
@@ -3480,9 +3884,10 @@
3480
3884
  ],
3481
3885
  "colors": [
3482
3886
  "bg-kumo-base",
3483
- "bg-kumo-elevated",
3484
3887
  "bg-kumo-recessed",
3485
3888
  "border-kumo-recessed",
3889
+ "ring-kumo-brand",
3890
+ "ring-kumo-focus",
3486
3891
  "ring-kumo-line"
3487
3892
  ],
3488
3893
  "styling": {
@@ -3805,19 +4210,19 @@
3805
4210
  "Radio": {
3806
4211
  "name": "Radio",
3807
4212
  "type": "component",
3808
- "description": "Radio — radio button group for single-select choices. Compound component: `Radio.Group` (with built-in Fieldset) and `Radio.Item`. Built on `@base-ui/react/radio-group` + `@base-ui/react/radio`.",
4213
+ "description": "Radio — radio button group for single-select choices. Compound component: `Radio.Group` (with built-in Fieldset), `Radio.Item`, and `Radio.Legend`. Built on `@base-ui/react/radio-group` + `@base-ui/react/radio`.",
3809
4214
  "importPath": "@cloudflare/kumo",
3810
4215
  "category": "Input",
3811
4216
  "props": {
3812
4217
  "legend": {
3813
4218
  "type": "string",
3814
- "required": true,
3815
- "description": "Legend text for the group (required for accessibility)"
4219
+ "optional": true,
4220
+ "description": "Legend text for the group (required for accessibility). For more control over legend styling, omit this prop and use `<Radio.Legend>` as a child instead."
3816
4221
  },
3817
4222
  "children": {
3818
4223
  "type": "ReactNode",
3819
4224
  "optional": true,
3820
- "description": "Child Radio.Item components"
4225
+ "description": "Child Radio.Item components (and optionally a Radio.Legend)"
3821
4226
  },
3822
4227
  "orientation": {
3823
4228
  "type": "enum",
@@ -3873,7 +4278,7 @@
3873
4278
  "controlPosition": {
3874
4279
  "type": "enum",
3875
4280
  "optional": true,
3876
- "description": "Position of radio control relative to label: \"start\" (default) puts radio before label, \"end\" puts label before radio. Note: In card appearance, the control is always positioned at the end.",
4281
+ "description": "Position of radio control relative to label: \"start\" puts radio before label, \"end\" puts label before radio. Defaults to \"start\" for default appearance and \"end\" for card appearance.",
3877
4282
  "values": [
3878
4283
  "start",
3879
4284
  "end"
@@ -3899,6 +4304,10 @@
3899
4304
  "<div className=\"grid grid-cols-2 gap-6\">\n <Radio.Group legend=\"Disabled group\" disabled defaultValue=\"a\">\n <Radio.Item label=\"Option A\" value=\"a\" />\n <Radio.Item label=\"Option B\" value=\"b\" />\n </Radio.Group>\n <Radio.Group legend=\"Individual disabled\" defaultValue=\"available\">\n <Radio.Item label=\"Available\" value=\"available\" />\n <Radio.Item label=\"Unavailable\" value=\"unavailable\" disabled />\n </Radio.Group>\n <Radio.Group\n legend=\"Disabled card group\"\n appearance=\"card\"\n disabled\n defaultValue=\"a\"\n >\n <Radio.Item\n label=\"Option A\"\n description=\"This option is disabled.\"\n value=\"a\"\n />\n <Radio.Item\n label=\"Option B\"\n description=\"This option is disabled.\"\n value=\"b\"\n />\n </Radio.Group>\n <Radio.Group\n legend=\"Individual disabled card\"\n appearance=\"card\"\n defaultValue=\"available\"\n >\n <Radio.Item\n label=\"Available\"\n description=\"This option can be selected.\"\n value=\"available\"\n />\n <Radio.Item\n label=\"Unavailable\"\n description=\"This option is not available.\"\n value=\"unavailable\"\n disabled\n />\n </Radio.Group>\n </div>",
3900
4305
  "<Radio.Group legend=\"Preferences\" controlPosition=\"end\" defaultValue=\"a\">\n <Radio.Item label=\"Label before radio\" value=\"a\" />\n <Radio.Item label=\"Another option\" value=\"b\" />\n </Radio.Group>",
3901
4306
  "<Radio.Group\n legend=\"Choose a plan\"\n appearance=\"card\"\n value={value}\n onValueChange={setValue}\n >\n <Radio.Item\n label=\"Free\"\n description=\"For personal or hobby projects that aren't business-critical.\"\n value=\"free\"\n />\n <Radio.Item\n label=\"Pro\"\n description=\"For professional websites that aren't business-critical.\"\n value=\"pro\"\n />\n <Radio.Item\n label=\"Business\"\n description=\"For small businesses operating online.\"\n value=\"business\"\n />\n <Radio.Item\n label=\"Contract\"\n description=\"For mission-critical applications that are core to your business.\"\n value=\"contract\"\n />\n </Radio.Group>",
4307
+ "<Radio.Group defaultValue=\"all\" value={value} onValueChange={setValue}>\n <Radio.Legend className=\"sr-only\">Paths</Radio.Legend>\n <Radio.Item label=\"Allow all paths\" value=\"all\" />\n <Radio.Item label=\"Restrict to specific paths\" value=\"specific\" />\n </Radio.Group>",
4308
+ "<Radio.Group value={value} onValueChange={setValue}>\n <Radio.Legend className=\"text-sm font-normal text-kumo-subtle\">\n Notification preference\n </Radio.Legend>\n <Radio.Item label=\"Email\" value=\"email\" />\n <Radio.Item label=\"SMS\" value=\"sms\" />\n <Radio.Item label=\"Push notification\" value=\"push\" />\n </Radio.Group>",
4309
+ "<Radio.Group\n legend=\"Choose a plan\"\n appearance=\"card\"\n controlPosition=\"start\"\n value={value}\n onValueChange={setValue}\n >\n <Radio.Item\n label=\"Free\"\n description=\"For personal or hobby projects that aren't business-critical.\"\n value=\"free\"\n />\n <Radio.Item\n label=\"Pro\"\n description=\"For professional websites that aren't business-critical.\"\n value=\"pro\"\n />\n </Radio.Group>",
4310
+ "<Radio.Group\n legend=\"Choose a plan\"\n appearance=\"card\"\n value={value}\n onValueChange={setValue}\n >\n <Radio.Item\n label={\n <span className=\"flex items-center gap-2\">\n Free\n <Badge variant=\"neutral\">$0</Badge>\n </span>\n }\n description=\"For personal or hobby projects.\"\n value=\"free\"\n />\n <Radio.Item\n label={\n <span className=\"flex items-center gap-2\">\n Pro\n <Badge variant=\"primary\">Popular</Badge>\n </span>\n }\n description=\"For professional websites.\"\n value=\"pro\"\n />\n </Radio.Group>",
3902
4311
  "<Radio.Group\n legend=\"Choose a plan\"\n appearance=\"card\"\n orientation=\"horizontal\"\n value={value}\n onValueChange={setValue}\n >\n <Radio.Item\n label=\"Free\"\n description=\"For personal or hobby projects that aren't business-critical.\"\n value=\"free\"\n />\n <Radio.Item\n label=\"Pro\"\n description=\"For professional websites that aren't business-critical.\"\n value=\"pro\"\n />\n <Radio.Item\n label=\"Business\"\n description=\"For small businesses operating online.\"\n value=\"business\"\n />\n <Radio.Item\n label=\"Contract\"\n description=\"For mission-critical applications that are core to your business.\"\n value=\"contract\"\n />\n </Radio.Group>"
3903
4312
  ],
3904
4313
  "colors": [
@@ -3908,8 +4317,11 @@
3908
4317
  "border-kumo-danger",
3909
4318
  "border-kumo-hairline",
3910
4319
  "border-kumo-interact",
4320
+ "ring-kumo-brand",
3911
4321
  "ring-kumo-danger",
4322
+ "ring-kumo-focus",
3912
4323
  "ring-kumo-hairline",
4324
+ "ring-kumo-line",
3913
4325
  "text-kumo-danger",
3914
4326
  "text-kumo-default",
3915
4327
  "text-kumo-subtle"
@@ -3926,7 +4338,7 @@
3926
4338
  "props": {
3927
4339
  "legend": {
3928
4340
  "type": "string",
3929
- "required": true
4341
+ "optional": true
3930
4342
  },
3931
4343
  "children": {
3932
4344
  "type": "ReactNode",
@@ -3957,11 +4369,7 @@
3957
4369
  "optional": true
3958
4370
  },
3959
4371
  "label": {
3960
- "type": "\"start\" (default) puts radio before label",
3961
- "required": true
3962
- },
3963
- "Note": {
3964
- "type": "In card appearance",
4372
+ "type": "\"start\" puts radio before label",
3965
4373
  "required": true
3966
4374
  },
3967
4375
  "controlPosition": {
@@ -3977,6 +4385,20 @@
3977
4385
  "optional": true
3978
4386
  }
3979
4387
  }
4388
+ },
4389
+ "Legend": {
4390
+ "name": "Legend",
4391
+ "description": "Legend sub-component",
4392
+ "props": {
4393
+ "children": {
4394
+ "type": "ReactNode",
4395
+ "required": true
4396
+ },
4397
+ "className": {
4398
+ "type": "string",
4399
+ "optional": true
4400
+ }
4401
+ }
3980
4402
  }
3981
4403
  }
3982
4404
  },
@@ -4089,9 +4511,12 @@
4089
4511
  ],
4090
4512
  "colors": [
4091
4513
  "bg-kumo-base",
4514
+ "bg-kumo-elevated",
4092
4515
  "bg-kumo-hairline",
4093
4516
  "bg-kumo-tint",
4094
- "ring-kumo-hairline",
4517
+ "border-kumo-line",
4518
+ "ring-kumo-brand",
4519
+ "ring-kumo-focus",
4095
4520
  "ring-kumo-line",
4096
4521
  "text-kumo-danger",
4097
4522
  "text-kumo-default",
@@ -4125,7 +4550,7 @@
4125
4550
  "height": 36,
4126
4551
  "paddingX": 12,
4127
4552
  "borderRadius": 8,
4128
- "background": "color-secondary",
4553
+ "background": "bg-kumo-elevated",
4129
4554
  "text": "text-color-surface",
4130
4555
  "ring": "color-border",
4131
4556
  "fontSize": 16,
@@ -4150,8 +4575,8 @@
4150
4575
  }
4151
4576
  },
4152
4577
  "popup": {
4153
- "background": "color-secondary",
4154
- "ring": "color-border",
4578
+ "background": "bg-kumo-elevated",
4579
+ "ring": "border-kumo-line",
4155
4580
  "borderRadius": 8,
4156
4581
  "padding": 6
4157
4582
  },
@@ -4292,8 +4717,9 @@
4292
4717
  "colors": [
4293
4718
  "bg-kumo-brand",
4294
4719
  "bg-kumo-control",
4295
- "outline-kumo-hairline",
4296
- "ring-kumo-hairline",
4720
+ "outline-kumo-focus",
4721
+ "ring-kumo-brand",
4722
+ "ring-kumo-focus",
4297
4723
  "text-kumo-default",
4298
4724
  "text-kumo-subtle"
4299
4725
  ]
@@ -4407,6 +4833,7 @@
4407
4833
  "bg-kumo-recessed",
4408
4834
  "bg-kumo-tint",
4409
4835
  "border-kumo-hairline",
4836
+ "ring-kumo-brand",
4410
4837
  "ring-kumo-hairline",
4411
4838
  "text-kumo-default",
4412
4839
  "text-kumo-strong",
@@ -4466,82 +4893,222 @@
4466
4893
  "Header": {
4467
4894
  "name": "Header",
4468
4895
  "description": "Header sub-component",
4469
- "props": {}
4896
+ "props": {
4897
+ "collapsible": {
4898
+ "type": "boolean",
4899
+ "optional": true
4900
+ },
4901
+ "defaultOpen": {
4902
+ "type": "boolean",
4903
+ "optional": true
4904
+ },
4905
+ "open": {
4906
+ "type": "boolean",
4907
+ "optional": true
4908
+ }
4909
+ }
4470
4910
  },
4471
4911
  "Content": {
4472
4912
  "name": "Content",
4473
4913
  "description": "Content sub-component",
4474
- "props": {}
4914
+ "props": {
4915
+ "collapsible": {
4916
+ "type": "boolean",
4917
+ "optional": true
4918
+ },
4919
+ "defaultOpen": {
4920
+ "type": "boolean",
4921
+ "optional": true
4922
+ },
4923
+ "open": {
4924
+ "type": "boolean",
4925
+ "optional": true
4926
+ }
4927
+ }
4475
4928
  },
4476
4929
  "Footer": {
4477
4930
  "name": "Footer",
4478
4931
  "description": "Footer sub-component",
4479
- "props": {}
4932
+ "props": {
4933
+ "collapsible": {
4934
+ "type": "boolean",
4935
+ "optional": true
4936
+ },
4937
+ "defaultOpen": {
4938
+ "type": "boolean",
4939
+ "optional": true
4940
+ },
4941
+ "open": {
4942
+ "type": "boolean",
4943
+ "optional": true
4944
+ }
4945
+ }
4480
4946
  },
4481
4947
  "Group": {
4482
4948
  "name": "Group",
4483
4949
  "description": "Group sub-component",
4484
- "props": {}
4950
+ "props": {
4951
+ "collapsible": {
4952
+ "type": "boolean",
4953
+ "optional": true
4954
+ },
4955
+ "defaultOpen": {
4956
+ "type": "boolean",
4957
+ "optional": true
4958
+ },
4959
+ "open": {
4960
+ "type": "boolean",
4961
+ "optional": true
4962
+ }
4963
+ }
4485
4964
  },
4486
4965
  "GroupLabel": {
4487
4966
  "name": "GroupLabel",
4488
4967
  "description": "GroupLabel sub-component",
4489
- "props": {}
4968
+ "props": {
4969
+ "icon": {
4970
+ "type": "React.ComponentType<{ className?: string",
4971
+ "optional": true
4972
+ }
4973
+ }
4490
4974
  },
4491
4975
  "GroupContent": {
4492
4976
  "name": "GroupContent",
4493
4977
  "description": "GroupContent sub-component",
4494
- "props": {}
4978
+ "props": {
4979
+ "icon": {
4980
+ "type": "React.ComponentType<{ className?: string",
4981
+ "optional": true
4982
+ }
4983
+ }
4495
4984
  },
4496
4985
  "Menu": {
4497
4986
  "name": "Menu",
4498
4987
  "description": "Menu sub-component",
4499
- "props": {}
4988
+ "props": {
4989
+ "icon": {
4990
+ "type": "React.ComponentType<{ className?: string",
4991
+ "optional": true
4992
+ }
4993
+ }
4500
4994
  },
4501
4995
  "MenuItem": {
4502
4996
  "name": "MenuItem",
4503
4997
  "description": "MenuItem sub-component",
4504
- "props": {}
4998
+ "props": {
4999
+ "icon": {
5000
+ "type": "React.ComponentType<{ className?: string",
5001
+ "optional": true
5002
+ }
5003
+ }
4505
5004
  },
4506
5005
  "MenuButton": {
4507
5006
  "name": "MenuButton",
4508
5007
  "description": "MenuButton sub-component",
4509
- "props": {}
5008
+ "props": {
5009
+ "icon": {
5010
+ "type": "React.ComponentType<{ className?: string",
5011
+ "optional": true
5012
+ }
5013
+ }
4510
5014
  },
4511
5015
  "MenuAction": {
4512
5016
  "name": "MenuAction",
4513
5017
  "description": "MenuAction sub-component",
4514
- "props": {}
5018
+ "props": {
5019
+ "active": {
5020
+ "type": "boolean",
5021
+ "optional": true
5022
+ },
5023
+ "href": {
5024
+ "type": "string",
5025
+ "optional": true
5026
+ }
5027
+ }
4515
5028
  },
4516
5029
  "MenuBadge": {
4517
5030
  "name": "MenuBadge",
4518
5031
  "description": "MenuBadge sub-component",
4519
- "props": {}
5032
+ "props": {
5033
+ "active": {
5034
+ "type": "boolean",
5035
+ "optional": true
5036
+ },
5037
+ "href": {
5038
+ "type": "string",
5039
+ "optional": true
5040
+ }
5041
+ }
4520
5042
  },
4521
5043
  "MenuSub": {
4522
5044
  "name": "MenuSub",
4523
5045
  "description": "MenuSub sub-component",
4524
- "props": {}
5046
+ "props": {
5047
+ "active": {
5048
+ "type": "boolean",
5049
+ "optional": true
5050
+ },
5051
+ "href": {
5052
+ "type": "string",
5053
+ "optional": true
5054
+ }
5055
+ }
4525
5056
  },
4526
5057
  "MenuSubItem": {
4527
5058
  "name": "MenuSubItem",
4528
5059
  "description": "MenuSubItem sub-component",
4529
- "props": {}
5060
+ "props": {
5061
+ "active": {
5062
+ "type": "boolean",
5063
+ "optional": true
5064
+ },
5065
+ "href": {
5066
+ "type": "string",
5067
+ "optional": true
5068
+ }
5069
+ }
4530
5070
  },
4531
5071
  "MenuSubButton": {
4532
5072
  "name": "MenuSubButton",
4533
5073
  "description": "MenuSubButton sub-component",
4534
- "props": {}
5074
+ "props": {
5075
+ "active": {
5076
+ "type": "boolean",
5077
+ "optional": true
5078
+ },
5079
+ "href": {
5080
+ "type": "string",
5081
+ "optional": true
5082
+ }
5083
+ }
4535
5084
  },
4536
5085
  "Separator": {
4537
5086
  "name": "Separator",
4538
5087
  "description": "Separator sub-component",
4539
- "props": {}
5088
+ "props": {
5089
+ "placeholder": {
5090
+ "type": "string",
5091
+ "optional": true
5092
+ },
5093
+ "shortcut": {
5094
+ "type": "string",
5095
+ "optional": true
5096
+ }
5097
+ }
4540
5098
  },
4541
5099
  "Input": {
4542
5100
  "name": "Input",
4543
5101
  "description": "Input sub-component",
4544
- "props": {}
5102
+ "props": {
5103
+ "placeholder": {
5104
+ "type": "string",
5105
+ "optional": true
5106
+ },
5107
+ "shortcut": {
5108
+ "type": "string",
5109
+ "optional": true
5110
+ }
5111
+ }
4545
5112
  },
4546
5113
  "Trigger": {
4547
5114
  "name": "Trigger",
@@ -4561,7 +5128,12 @@
4561
5128
  "MenuChevron": {
4562
5129
  "name": "MenuChevron",
4563
5130
  "description": "MenuChevron sub-component",
4564
- "props": {}
5131
+ "props": {
5132
+ "className": {
5133
+ "type": "string",
5134
+ "optional": true
5135
+ }
5136
+ }
4565
5137
  },
4566
5138
  "Collapsible": {
4567
5139
  "name": "Collapsible",
@@ -4603,7 +5175,7 @@
4603
5175
  "render": {
4604
5176
  "type": "ReactNode",
4605
5177
  "optional": true,
4606
- "description": "Allows you to replace the components HTML element with a different tag, or compose it with another component.\n\nAccepts a `ReactElement` or a function that returns the element to render."
5178
+ "description": "Allows you to replace the component's HTML element with a different tag, or compose it with another component.\n\nAccepts a `ReactElement` or a function that returns the element to render."
4607
5179
  },
4608
5180
  "children": {
4609
5181
  "type": "ReactNode",
@@ -4750,11 +5322,15 @@
4750
5322
  "<div className=\"flex flex-col gap-4\">\n <Switch\n label=\"Neutral off\"\n variant=\"neutral\"\n checked={false}\n onCheckedChange={() => {}}\n />\n <Switch\n label=\"Neutral on\"\n variant=\"neutral\"\n checked={true}\n onCheckedChange={() => {}}\n />\n <Switch\n label=\"Neutral disabled\"\n variant=\"neutral\"\n checked={false}\n disabled\n />\n </div>",
4751
5323
  "<div className=\"grid grid-cols-2 gap-x-8 gap-y-4\">\n <Switch label=\"Default off\" checked={false} onCheckedChange={() => {}} />\n <Switch label=\"Default on\" checked={true} onCheckedChange={() => {}} />\n <Switch\n label=\"Neutral off\"\n variant=\"neutral\"\n checked={false}\n onCheckedChange={() => {}}\n />\n <Switch\n label=\"Neutral on\"\n variant=\"neutral\"\n checked={true}\n onCheckedChange={() => {}}\n />\n </div>",
4752
5324
  "<Switch\n id=\"my-custom-switch\"\n label=\"Custom ID\"\n checked={checked}\n onCheckedChange={setChecked}\n />",
5325
+ "<Switch.Group legend=\"Notification settings\">\n <Switch.Item label=\"Email notifications\" />\n <Switch.Item label=\"SMS notifications\" />\n <Switch.Item label=\"Push notifications\" />\n </Switch.Group>",
5326
+ "<Switch.Group>\n <Switch.Legend className=\"sr-only\">Notification settings</Switch.Legend>\n <Switch.Item label=\"Email notifications\" />\n <Switch.Item label=\"SMS notifications\" />\n <Switch.Item label=\"Push notifications\" />\n </Switch.Group>",
5327
+ "<Switch.Group>\n <Switch.Legend className=\"text-sm font-normal text-kumo-subtle\">\n Notification settings\n </Switch.Legend>\n <Switch.Item label=\"Email notifications\" />\n <Switch.Item label=\"SMS notifications\" />\n <Switch.Item label=\"Push notifications\" />\n </Switch.Group>",
4753
5328
  "<div className=\"flex flex-col gap-4\">\n <Switch\n label=\"Small\"\n size=\"sm\"\n checked={true}\n onCheckedChange={() => {}}\n />\n <Switch\n label=\"Base (default)\"\n size=\"base\"\n checked={true}\n onCheckedChange={() => {}}\n />\n <Switch\n label=\"Large\"\n size=\"lg\"\n checked={true}\n onCheckedChange={() => {}}\n />\n </div>"
4754
5329
  ],
4755
5330
  "colors": [
4756
5331
  "bg-kumo-base",
4757
- "border-kumo-hairline",
5332
+ "ring-kumo-brand",
5333
+ "ring-kumo-focus",
4758
5334
  "ring-kumo-hairline",
4759
5335
  "text-kumo-danger",
4760
5336
  "text-kumo-default",
@@ -4772,7 +5348,7 @@
4772
5348
  "props": {
4773
5349
  "legend": {
4774
5350
  "type": "string",
4775
- "required": true
5351
+ "optional": true
4776
5352
  },
4777
5353
  "children": {
4778
5354
  "type": "ReactNode",
@@ -4799,6 +5375,20 @@
4799
5375
  "optional": true
4800
5376
  }
4801
5377
  }
5378
+ },
5379
+ "Legend": {
5380
+ "name": "Legend",
5381
+ "description": "Legend sub-component",
5382
+ "props": {
5383
+ "children": {
5384
+ "type": "ReactNode",
5385
+ "required": true
5386
+ },
5387
+ "className": {
5388
+ "type": "string",
5389
+ "optional": true
5390
+ }
5391
+ }
4802
5392
  }
4803
5393
  }
4804
5394
  },
@@ -4865,13 +5455,13 @@
4865
5455
  },
4866
5456
  "examples": [
4867
5457
  "<LayerCard className=\"p-0\">\n <Table>\n <Table.Header>\n <Table.Row>\n <Table.Head>Subject</Table.Head>\n <Table.Head>From</Table.Head>\n <Table.Head>Date</Table.Head>\n </Table.Row>\n </Table.Header>\n <Table.Body>\n {emailData.slice(0, 3).map((row) => (\n <Table.Row key={row.id}>\n <Table.Cell>{row.subject}</Table.Cell>\n <Table.Cell>{row.from}</Table.Cell>\n <Table.Cell>{row.date}</Table.Cell>\n </Table.Row>\n ))}\n </Table.Body>\n </Table>\n </LayerCard>",
4868
- "<LayerCard className=\"p-0\">\n <Table>\n <Table.Header>\n <Table.Row>\n <Table.CheckHead\n checked={selectedIds.size === rows.length}\n indeterminate={\n selectedIds.size > 0 && selectedIds.size < rows.length\n }\n onValueChange={toggleAll}\n aria-label=\"Select all rows\"\n />\n <Table.Head>Subject</Table.Head>\n <Table.Head>From</Table.Head>\n <Table.Head>Date</Table.Head>\n </Table.Row>\n </Table.Header>\n <Table.Body>\n {rows.map((row) => (\n <Table.Row key={row.id}>\n <Table.CheckCell\n checked={selectedIds.has(row.id)}\n onValueChange={() => toggleRow(row.id)}\n aria-label={`Select ${row.subject}`}\n />\n <Table.Cell>{row.subject}</Table.Cell>\n <Table.Cell>{row.from}</Table.Cell>\n <Table.Cell>{row.date}</Table.Cell>\n </Table.Row>\n ))}\n </Table.Body>\n </Table>\n </LayerCard>",
5458
+ "<LayerCard className=\"p-0\">\n <Table>\n <Table.Header>\n <Table.Row>\n <Table.CheckHead\n checked={selectedIds.size === rows.length}\n indeterminate={\n selectedIds.size > 0 && selectedIds.size < rows.length\n }\n onCheckedChange={toggleAll}\n aria-label=\"Select all rows\"\n />\n <Table.Head>Subject</Table.Head>\n <Table.Head>From</Table.Head>\n <Table.Head>Date</Table.Head>\n </Table.Row>\n </Table.Header>\n <Table.Body>\n {rows.map((row) => (\n <Table.Row key={row.id}>\n <Table.CheckCell\n checked={selectedIds.has(row.id)}\n onCheckedChange={() => toggleRow(row.id)}\n aria-label={`Select ${row.subject}`}\n />\n <Table.Cell>{row.subject}</Table.Cell>\n <Table.Cell>{row.from}</Table.Cell>\n <Table.Cell>{row.date}</Table.Cell>\n </Table.Row>\n ))}\n </Table.Body>\n </Table>\n </LayerCard>",
4869
5459
  "<LayerCard className=\"p-0\">\n <Table>\n <Table.Header variant=\"compact\">\n <Table.Row>\n <Table.Head>Subject</Table.Head>\n <Table.Head>From</Table.Head>\n <Table.Head>Date</Table.Head>\n </Table.Row>\n </Table.Header>\n <Table.Body>\n {emailData.slice(0, 3).map((row) => (\n <Table.Row key={row.id}>\n <Table.Cell>{row.subject}</Table.Cell>\n <Table.Cell>{row.from}</Table.Cell>\n <Table.Cell>{row.date}</Table.Cell>\n </Table.Row>\n ))}\n </Table.Body>\n </Table>\n </LayerCard>",
4870
- "<LayerCard className=\"p-0\">\n <Table>\n <Table.Header>\n <Table.Row>\n <Table.CheckHead\n checked={selectedIds.size === rows.length}\n indeterminate={\n selectedIds.size > 0 && selectedIds.size < rows.length\n }\n onValueChange={toggleAll}\n aria-label=\"Select all rows\"\n />\n <Table.Head>Subject</Table.Head>\n <Table.Head>From</Table.Head>\n <Table.Head>Date</Table.Head>\n </Table.Row>\n </Table.Header>\n <Table.Body>\n {rows.map((row) => (\n <Table.Row\n key={row.id}\n variant={selectedIds.has(row.id) ? \"selected\" : \"default\"}\n >\n <Table.CheckCell\n checked={selectedIds.has(row.id)}\n onValueChange={() => toggleRow(row.id)}\n aria-label={`Select ${row.subject}`}\n />\n <Table.Cell>{row.subject}</Table.Cell>\n <Table.Cell>{row.from}</Table.Cell>\n <Table.Cell>{row.date}</Table.Cell>\n </Table.Row>\n ))}\n </Table.Body>\n </Table>\n </LayerCard>",
5460
+ "<LayerCard className=\"p-0\">\n <Table>\n <Table.Header>\n <Table.Row>\n <Table.CheckHead\n checked={selectedIds.size === rows.length}\n indeterminate={\n selectedIds.size > 0 && selectedIds.size < rows.length\n }\n onCheckedChange={toggleAll}\n aria-label=\"Select all rows\"\n />\n <Table.Head>Subject</Table.Head>\n <Table.Head>From</Table.Head>\n <Table.Head>Date</Table.Head>\n </Table.Row>\n </Table.Header>\n <Table.Body>\n {rows.map((row) => (\n <Table.Row\n key={row.id}\n variant={selectedIds.has(row.id) ? \"selected\" : \"default\"}\n >\n <Table.CheckCell\n checked={selectedIds.has(row.id)}\n onCheckedChange={() => toggleRow(row.id)}\n aria-label={`Select ${row.subject}`}\n />\n <Table.Cell>{row.subject}</Table.Cell>\n <Table.Cell>{row.from}</Table.Cell>\n <Table.Cell>{row.date}</Table.Cell>\n </Table.Row>\n ))}\n </Table.Body>\n </Table>\n </LayerCard>",
4871
5461
  "<LayerCard className=\"p-0\">\n <Table layout=\"fixed\">\n <colgroup>\n <col />\n <col className=\"w-[150px]\" />\n <col className=\"w-[150px]\" />\n </colgroup>\n <Table.Header>\n <Table.Row>\n <Table.Head>Subject</Table.Head>\n <Table.Head>From</Table.Head>\n <Table.Head>Date</Table.Head>\n </Table.Row>\n </Table.Header>\n <Table.Body>\n {emailData.map((row) => (\n <Table.Row key={row.id}>\n <Table.Cell>{row.subject}</Table.Cell>\n <Table.Cell>{row.from}</Table.Cell>\n <Table.Cell>{row.date}</Table.Cell>\n </Table.Row>\n ))}\n </Table.Body>\n </Table>\n </LayerCard>",
4872
5462
  "<LayerCard className=\"w-full max-w-md overflow-x-auto p-0\">\n <Table>\n <Table.Header variant=\"compact\">\n <Table.Row>\n <Table.Head>Subject</Table.Head>\n <Table.Head>From</Table.Head>\n <Table.Head>Date</Table.Head>\n <Table.Head>Tags</Table.Head>\n <Table.Head sticky=\"right\">\n <span className=\"sr-only\">Actions</span>\n </Table.Head>\n </Table.Row>\n </Table.Header>\n <Table.Body>\n {emailData.map((row) => (\n <Table.Row key={row.id}>\n <Table.Cell className=\"whitespace-nowrap\">\n {row.subject}\n </Table.Cell>\n <Table.Cell className=\"whitespace-nowrap\">\n {row.from}\n </Table.Cell>\n <Table.Cell className=\"whitespace-nowrap\">\n {row.date}\n </Table.Cell>\n <Table.Cell className=\"whitespace-nowrap\">\n {row.tags ? (\n <div className=\"inline-flex gap-1\">\n {row.tags.map((tag) => (\n <Badge key={tag}>{tag}</Badge>\n ))}\n </div>\n ) : (\n \"—\"\n )}\n </Table.Cell>\n <Table.Cell sticky=\"right\" className=\"text-right\">\n <DropdownMenu>\n <DropdownMenu.Trigger\n render={\n <Button\n variant=\"ghost\"\n size=\"sm\"\n shape=\"square\"\n aria-label=\"More options\"\n >\n <DotsThree weight=\"bold\" size={16} />\n </Button>\n }\n />\n <DropdownMenu.Content>\n <DropdownMenu.Item icon={Eye}>View</DropdownMenu.Item>\n <DropdownMenu.Item icon={PencilSimple}>\n Edit\n </DropdownMenu.Item>\n <DropdownMenu.Separator />\n <DropdownMenu.Item icon={Trash} variant=\"danger\">\n Delete\n </DropdownMenu.Item>\n </DropdownMenu.Content>\n </DropdownMenu>\n </Table.Cell>\n </Table.Row>\n ))}\n </Table.Body>\n </Table>\n </LayerCard>",
4873
5463
  "<LayerCard className=\"w-full max-w-md overflow-x-auto p-0\">\n <Table>\n <Table.Header>\n <Table.Row>\n <Table.Head>Subject</Table.Head>\n <Table.Head>From</Table.Head>\n <Table.Head>Date</Table.Head>\n <Table.Head>Tags</Table.Head>\n <Table.Head sticky=\"right\">\n <span className=\"sr-only\">Actions</span>\n </Table.Head>\n </Table.Row>\n </Table.Header>\n <Table.Body>\n {emailData.map((row) => (\n <Table.Row key={row.id}>\n <Table.Cell className=\"whitespace-nowrap\">\n {row.subject}\n </Table.Cell>\n <Table.Cell className=\"whitespace-nowrap\">\n {row.from}\n </Table.Cell>\n <Table.Cell className=\"whitespace-nowrap\">\n {row.date}\n </Table.Cell>\n <Table.Cell className=\"whitespace-nowrap\">\n {row.tags ? (\n <div className=\"inline-flex gap-1\">\n {row.tags.map((tag) => (\n <Badge key={tag}>{tag}</Badge>\n ))}\n </div>\n ) : (\n \"—\"\n )}\n </Table.Cell>\n <Table.Cell sticky=\"right\" className=\"text-right\">\n <DropdownMenu>\n <DropdownMenu.Trigger\n render={\n <Button\n variant=\"ghost\"\n size=\"sm\"\n shape=\"square\"\n aria-label=\"More options\"\n >\n <DotsThree weight=\"bold\" size={16} />\n </Button>\n }\n />\n <DropdownMenu.Content>\n <DropdownMenu.Item icon={Eye}>View</DropdownMenu.Item>\n <DropdownMenu.Item icon={PencilSimple}>\n Edit\n </DropdownMenu.Item>\n <DropdownMenu.Separator />\n <DropdownMenu.Item icon={Trash} variant=\"danger\">\n Delete\n </DropdownMenu.Item>\n </DropdownMenu.Content>\n </DropdownMenu>\n </Table.Cell>\n </Table.Row>\n ))}\n </Table.Body>\n </Table>\n </LayerCard>",
4874
- "<LayerCard className=\"w-full overflow-x-auto p-0\">\n <Table layout=\"fixed\">\n <colgroup>\n <col />{\" \"}\n {/* Checkbox column - width handled by Table.CheckHead/CheckCell */}\n <col />\n <col style={{ width: \"150px\" }} />\n <col style={{ width: \"120px\" }} />\n <col style={{ width: \"50px\" }} />\n </colgroup>\n <Table.Header>\n <Table.Row>\n <Table.CheckHead\n checked={selectedIds.size === emailData.length}\n indeterminate={\n selectedIds.size > 0 && selectedIds.size < emailData.length\n }\n onValueChange={toggleAll}\n aria-label=\"Select all rows\"\n />\n <Table.Head>Subject</Table.Head>\n <Table.Head>From</Table.Head>\n <Table.Head>Date</Table.Head>\n <Table.Head></Table.Head>\n </Table.Row>\n </Table.Header>\n <Table.Body>\n {emailData.map((row) => (\n <Table.Row\n key={row.id}\n variant={selectedIds.has(row.id) ? \"selected\" : \"default\"}\n >\n <Table.CheckCell\n checked={selectedIds.has(row.id)}\n onValueChange={() => toggleRow(row.id)}\n aria-label={`Select ${row.subject}`}\n />\n <Table.Cell>\n <div className=\"flex items-center gap-2\">\n <EnvelopeSimple size={16} />\n <span className=\"truncate\">{row.subject}</span>\n {row.tags && (\n <div className=\"ml-2 inline-flex gap-1\">\n {row.tags.map((tag) => (\n <Badge key={tag}>{tag}</Badge>\n ))}\n </div>\n )}\n </div>\n </Table.Cell>\n <Table.Cell>\n <span className=\"truncate\">{row.from}</span>\n </Table.Cell>\n <Table.Cell>\n <span className=\"truncate\">{row.date}</span>\n </Table.Cell>\n <Table.Cell className=\"text-right\">\n <DropdownMenu>\n <DropdownMenu.Trigger\n render={\n <Button\n variant=\"ghost\"\n size=\"sm\"\n shape=\"square\"\n aria-label=\"More options\"\n >\n <DotsThree weight=\"bold\" size={16} />\n </Button>\n }\n />\n <DropdownMenu.Content>\n <DropdownMenu.Item icon={Eye}>View</DropdownMenu.Item>\n <DropdownMenu.Item icon={PencilSimple}>\n Edit\n </DropdownMenu.Item>\n <DropdownMenu.Separator />\n <DropdownMenu.Item icon={Trash} variant=\"danger\">\n Delete\n </DropdownMenu.Item>\n </DropdownMenu.Content>\n </DropdownMenu>\n </Table.Cell>\n </Table.Row>\n ))}\n </Table.Body>\n </Table>\n </LayerCard>"
5464
+ "<LayerCard className=\"w-full overflow-x-auto p-0\">\n <Table layout=\"fixed\">\n <colgroup>\n <col />{\" \"}\n {/* Checkbox column - width handled by Table.CheckHead/CheckCell */}\n <col />\n <col style={{ width: \"150px\" }} />\n <col style={{ width: \"120px\" }} />\n <col style={{ width: \"50px\" }} />\n </colgroup>\n <Table.Header>\n <Table.Row>\n <Table.CheckHead\n checked={selectedIds.size === emailData.length}\n indeterminate={\n selectedIds.size > 0 && selectedIds.size < emailData.length\n }\n onCheckedChange={toggleAll}\n aria-label=\"Select all rows\"\n />\n <Table.Head>Subject</Table.Head>\n <Table.Head>From</Table.Head>\n <Table.Head>Date</Table.Head>\n <Table.Head></Table.Head>\n </Table.Row>\n </Table.Header>\n <Table.Body>\n {emailData.map((row) => (\n <Table.Row\n key={row.id}\n variant={selectedIds.has(row.id) ? \"selected\" : \"default\"}\n >\n <Table.CheckCell\n checked={selectedIds.has(row.id)}\n onCheckedChange={() => toggleRow(row.id)}\n aria-label={`Select ${row.subject}`}\n />\n <Table.Cell>\n <div className=\"flex items-center gap-2\">\n <EnvelopeSimple size={16} />\n <span className=\"truncate\">{row.subject}</span>\n {row.tags && (\n <div className=\"ml-2 inline-flex gap-1\">\n {row.tags.map((tag) => (\n <Badge key={tag}>{tag}</Badge>\n ))}\n </div>\n )}\n </div>\n </Table.Cell>\n <Table.Cell>\n <span className=\"truncate\">{row.from}</span>\n </Table.Cell>\n <Table.Cell>\n <span className=\"truncate\">{row.date}</span>\n </Table.Cell>\n <Table.Cell className=\"text-right\">\n <DropdownMenu>\n <DropdownMenu.Trigger\n render={\n <Button\n variant=\"ghost\"\n size=\"sm\"\n shape=\"square\"\n aria-label=\"More options\"\n >\n <DotsThree weight=\"bold\" size={16} />\n </Button>\n }\n />\n <DropdownMenu.Content>\n <DropdownMenu.Item icon={Eye}>View</DropdownMenu.Item>\n <DropdownMenu.Item icon={PencilSimple}>\n Edit\n </DropdownMenu.Item>\n <DropdownMenu.Separator />\n <DropdownMenu.Item icon={Trash} variant=\"danger\">\n Delete\n </DropdownMenu.Item>\n </DropdownMenu.Content>\n </DropdownMenu>\n </Table.Cell>\n </Table.Row>\n ))}\n </Table.Body>\n </Table>\n </LayerCard>"
4875
5465
  ],
4876
5466
  "colors": [
4877
5467
  "bg-kumo-base",
@@ -4879,6 +5469,7 @@
4879
5469
  "bg-kumo-hairline",
4880
5470
  "bg-kumo-tint",
4881
5471
  "border-kumo-fill",
5472
+ "ring-kumo-brand",
4882
5473
  "text-kumo-default",
4883
5474
  "text-kumo-strong"
4884
5475
  ],
@@ -4962,14 +5553,14 @@
4962
5553
  "<DemoWrapper>\n <TableOfContents>\n <TableOfContents.Title>On this page</TableOfContents.Title>\n <TableOfContents.List>\n {headings.map((heading) => (\n <TableOfContents.Item\n key={heading.text}\n active={heading.text === \"Usage\"}\n className=\"cursor-pointer\"\n >\n {heading.text}\n </TableOfContents.Item>\n ))}\n </TableOfContents.List>\n </TableOfContents>\n </DemoWrapper>",
4963
5554
  "<DemoWrapper>\n <TableOfContents>\n <TableOfContents.Title>On this page</TableOfContents.Title>\n <TableOfContents.List>\n {headings.map((heading) => (\n <TableOfContents.Item\n key={heading.text}\n active={heading.text === active}\n onClick={() => setActive(heading.text)}\n className=\"cursor-pointer\"\n >\n {heading.text}\n </TableOfContents.Item>\n ))}\n </TableOfContents.List>\n </TableOfContents>\n </DemoWrapper>",
4964
5555
  "<DemoWrapper>\n <TableOfContents>\n <TableOfContents.Title>On this page</TableOfContents.Title>\n <TableOfContents.List>\n {headings.map((heading) => (\n <TableOfContents.Item key={heading.text} className=\"cursor-pointer\">\n {heading.text}\n </TableOfContents.Item>\n ))}\n </TableOfContents.List>\n </TableOfContents>\n </DemoWrapper>",
4965
- "<DemoWrapper>\n <TableOfContents>\n <TableOfContents.Title>On this page</TableOfContents.Title>\n <TableOfContents.List>\n <TableOfContents.Item active className=\"cursor-pointer\">\n Overview\n </TableOfContents.Item>\n <TableOfContents.Group label=\"Getting Started\">\n <TableOfContents.Item className=\"cursor-pointer\">\n Installation\n </TableOfContents.Item>\n <TableOfContents.Item className=\"cursor-pointer\">\n Configuration\n </TableOfContents.Item>\n </TableOfContents.Group>\n <TableOfContents.Group label=\"API\">\n <TableOfContents.Item className=\"cursor-pointer\">\n Props\n </TableOfContents.Item>\n <TableOfContents.Item className=\"cursor-pointer\">\n Events\n </TableOfContents.Item>\n </TableOfContents.Group>\n </TableOfContents.List>\n </TableOfContents>\n </DemoWrapper>",
5556
+ "<DemoWrapper>\n <TableOfContents>\n <TableOfContents.Title>On this page</TableOfContents.Title>\n <TableOfContents.List>\n <TableOfContents.Item active className=\"cursor-pointer\">\n Overview\n </TableOfContents.Item>\n <TableOfContents.Group label=\"Examples\" href=\"#examples-demo\">\n <TableOfContents.Item className=\"cursor-pointer\">\n Basic example\n </TableOfContents.Item>\n <TableOfContents.Item className=\"cursor-pointer\">\n Advanced example\n </TableOfContents.Item>\n </TableOfContents.Group>\n <TableOfContents.Group label=\"Getting Started\">\n <TableOfContents.Item className=\"cursor-pointer\">\n Installation\n </TableOfContents.Item>\n <TableOfContents.Item className=\"cursor-pointer\">\n Configuration\n </TableOfContents.Item>\n </TableOfContents.Group>\n <TableOfContents.Group label=\"API\" href=\"#api-demo\">\n <TableOfContents.Item className=\"cursor-pointer\">\n Props\n </TableOfContents.Item>\n <TableOfContents.Item className=\"cursor-pointer\">\n Events\n </TableOfContents.Item>\n </TableOfContents.Group>\n </TableOfContents.List>\n </TableOfContents>\n </DemoWrapper>",
4966
5557
  "<DemoWrapper>\n <TableOfContents>\n <TableOfContents.List>\n {headings.slice(0, 3).map((heading) => (\n <TableOfContents.Item\n key={heading.text}\n active={heading.text === \"Introduction\"}\n className=\"cursor-pointer\"\n >\n {heading.text}\n </TableOfContents.Item>\n ))}\n </TableOfContents.List>\n </TableOfContents>\n </DemoWrapper>",
4967
5558
  "<DemoWrapper>\n <div className=\"space-y-3\">\n <TableOfContents>\n <TableOfContents.List>\n {[\"Introduction\", \"Installation\", \"Usage\"].map((text) => (\n <TableOfContents.Item\n key={text}\n render={<button type=\"button\" />}\n onClick={() => setClicked(text)}\n active={text === \"Introduction\"}\n >\n {text}\n </TableOfContents.Item>\n ))}\n </TableOfContents.List>\n </TableOfContents>\n {clicked && (\n <p className=\"text-xs text-kumo-subtle\">Clicked: {clicked}</p>\n )}\n </div>\n </DemoWrapper>"
4968
5559
  ],
4969
5560
  "colors": [
4970
- "bg-kumo-brand",
4971
- "bg-kumo-line",
4972
- "bg-kumo-tint",
5561
+ "border-kumo-brand",
5562
+ "border-kumo-hairline",
5563
+ "border-kumo-line",
4973
5564
  "text-kumo-default",
4974
5565
  "text-kumo-subtle"
4975
5566
  ],
@@ -4987,12 +5578,30 @@
4987
5578
  "Item": {
4988
5579
  "name": "Item",
4989
5580
  "description": "Item sub-component",
4990
- "props": {}
5581
+ "props": {
5582
+ "active": {
5583
+ "type": "boolean",
5584
+ "optional": true
5585
+ }
5586
+ }
4991
5587
  },
4992
5588
  "Group": {
4993
5589
  "name": "Group",
4994
5590
  "description": "Group sub-component",
4995
- "props": {}
5591
+ "props": {
5592
+ "label": {
5593
+ "type": "string",
5594
+ "required": true
5595
+ },
5596
+ "href": {
5597
+ "type": "string",
5598
+ "optional": true
5599
+ },
5600
+ "active": {
5601
+ "type": "boolean",
5602
+ "optional": true
5603
+ }
5604
+ }
4996
5605
  }
4997
5606
  }
4998
5607
  },
@@ -5067,6 +5676,8 @@
5067
5676
  "bg-kumo-recessed",
5068
5677
  "bg-kumo-tint",
5069
5678
  "border-kumo-hairline",
5679
+ "ring-kumo-brand",
5680
+ "ring-kumo-focus",
5070
5681
  "ring-kumo-hairline",
5071
5682
  "ring-kumo-line",
5072
5683
  "text-kumo-default",
@@ -5178,9 +5789,32 @@
5178
5789
  "description": "Whether to truncate overflowing text with an ellipsis. Adds `truncate min-w-0` classes."
5179
5790
  },
5180
5791
  "as": {
5181
- "type": "React.ElementType",
5792
+ "type": "enum",
5182
5793
  "optional": true,
5183
- "description": "The HTML element type to render as (e.g. `\"span\"`, `\"p\"`, `\"h1\"`). Auto-selected based on variant if omitted."
5794
+ "description": "The HTML element to render. Accepts headings (`\"h1\"`–`\"h6\"`), block text (`\"p\"`, `\"pre\"`), inline text (`\"span\"`, `\"code\"`, `\"em\"`, `\"strong\"`, `\"small\"`, `\"abbr\"`, `\"time\"`), form-related (`\"label\"`, `\"legend\"`), list/definition (`\"dt\"`, `\"dd\"`, `\"li\"`), and `\"figcaption\"`.\n\n- **Required** for heading variants (`\"heading1\"`, `\"heading2\"`, `\"heading3\"`) — pick the element that reflects this text's place in the document outline, or `\"span\"` for decorative heading-styled text that is not a section heading.\n- **Optional** for body variants (defaults to `\"p\"`) and monospace variants (defaults to `\"span\"`).",
5795
+ "values": [
5796
+ "h1",
5797
+ "h2",
5798
+ "h3",
5799
+ "h4",
5800
+ "h5",
5801
+ "h6",
5802
+ "p",
5803
+ "span",
5804
+ "label",
5805
+ "dt",
5806
+ "dd",
5807
+ "li",
5808
+ "figcaption",
5809
+ "legend",
5810
+ "pre",
5811
+ "code",
5812
+ "em",
5813
+ "strong",
5814
+ "small",
5815
+ "abbr",
5816
+ "time"
5817
+ ]
5184
5818
  },
5185
5819
  "children": {
5186
5820
  "type": "ReactNode",
@@ -5189,7 +5823,7 @@
5189
5823
  }
5190
5824
  },
5191
5825
  "examples": [
5192
- "<div className=\"grid w-full grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3\">\n <div className=\"flex flex-col justify-end gap-1 rounded-lg border border-kumo-hairline bg-kumo-base p-4\">\n <Text variant=\"heading1\">Heading 1</Text>\n <Text variant=\"mono-secondary\">text-3xl (30px)</Text>\n </div>\n <div className=\"flex flex-col justify-end gap-1 rounded-lg border border-kumo-hairline bg-kumo-base p-4\">\n <Text variant=\"heading2\">Heading 2</Text>\n <Text variant=\"mono-secondary\">text-2xl (24px)</Text>\n </div>\n <div className=\"flex flex-col justify-end gap-1 rounded-lg border border-kumo-hairline bg-kumo-base p-4\">\n <Text variant=\"heading3\">Heading 3</Text>\n <Text variant=\"mono-secondary\">text-lg (16px)</Text>\n </div>\n <div className=\"flex flex-col justify-end gap-1 rounded-lg border border-kumo-hairline bg-kumo-base p-4\">\n <Text>Body</Text>\n <Text variant=\"mono-secondary\">text-base (14px)</Text>\n </div>\n <div className=\"flex flex-col justify-end gap-1 rounded-lg border border-kumo-hairline bg-kumo-base p-4\">\n <Text bold>Body bold</Text>\n <Text variant=\"mono-secondary\">text-base (14px)</Text>\n </div>\n <div className=\"flex flex-col justify-end gap-1 rounded-lg border border-kumo-hairline bg-kumo-base p-4\">\n <Text size=\"lg\">Body lg</Text>\n <Text variant=\"mono-secondary\">text-lg (16px)</Text>\n </div>\n <div className=\"flex flex-col justify-end gap-1 rounded-lg border border-kumo-hairline bg-kumo-base p-4\">\n <Text size=\"sm\">Body sm</Text>\n <Text variant=\"mono-secondary\">text-sm (13px)</Text>\n </div>\n <div className=\"flex flex-col justify-end gap-1 rounded-lg border border-kumo-hairline bg-kumo-base p-4\">\n <Text size=\"xs\">Body xs</Text>\n <Text variant=\"mono-secondary\">text-xs (12px)</Text>\n </div>\n <div className=\"flex flex-col justify-end gap-1 rounded-lg border border-kumo-hairline bg-kumo-base p-4\">\n <Text variant=\"secondary\">Body secondary</Text>\n <Text variant=\"mono-secondary\">text-base (14px)</Text>\n </div>\n <div className=\"flex flex-col justify-end gap-1 rounded-lg border border-kumo-hairline bg-kumo-base p-4\">\n <Text variant=\"mono\">Monospace</Text>\n <Text variant=\"mono-secondary\">text-sm (13px)</Text>\n </div>\n <div className=\"flex flex-col justify-end gap-1 rounded-lg border border-kumo-hairline bg-kumo-base p-4\">\n <Text variant=\"mono\" size=\"lg\">\n Monospace lg\n </Text>\n <Text variant=\"mono-secondary\">text-base (14px)</Text>\n </div>\n <div className=\"flex flex-col justify-end gap-1 rounded-lg border border-kumo-hairline bg-kumo-base p-4\">\n <Text variant=\"mono-secondary\">Monospace secondary</Text>\n <Text variant=\"mono-secondary\">text-sm (13px)</Text>\n </div>\n <div className=\"flex flex-col justify-end gap-1 rounded-lg border border-kumo-hairline bg-kumo-base p-4\">\n <Text variant=\"success\">Success</Text>\n <Text variant=\"mono-secondary\">text-base (14px)</Text>\n </div>\n <div className=\"flex flex-col justify-end gap-1 rounded-lg border border-kumo-hairline bg-kumo-base p-4\">\n <Text variant=\"error\">Error</Text>\n <Text variant=\"mono-secondary\">text-base (14px)</Text>\n </div>\n </div>",
5826
+ "<div className=\"grid w-full grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3\">\n <div className=\"flex flex-col justify-end gap-1 rounded-lg border border-kumo-hairline bg-kumo-base p-4\">\n <Text variant=\"heading1\" as=\"h1\">\n Heading 1\n </Text>\n <Text variant=\"mono-secondary\">text-3xl (30px)</Text>\n </div>\n <div className=\"flex flex-col justify-end gap-1 rounded-lg border border-kumo-hairline bg-kumo-base p-4\">\n <Text variant=\"heading2\" as=\"h2\">\n Heading 2\n </Text>\n <Text variant=\"mono-secondary\">text-2xl (24px)</Text>\n </div>\n <div className=\"flex flex-col justify-end gap-1 rounded-lg border border-kumo-hairline bg-kumo-base p-4\">\n <Text variant=\"heading3\" as=\"h3\">\n Heading 3\n </Text>\n <Text variant=\"mono-secondary\">text-lg (16px)</Text>\n </div>\n <div className=\"flex flex-col justify-end gap-1 rounded-lg border border-kumo-hairline bg-kumo-base p-4\">\n <Text>Body</Text>\n <Text variant=\"mono-secondary\">text-base (14px)</Text>\n </div>\n <div className=\"flex flex-col justify-end gap-1 rounded-lg border border-kumo-hairline bg-kumo-base p-4\">\n <Text bold>Body bold</Text>\n <Text variant=\"mono-secondary\">text-base (14px)</Text>\n </div>\n <div className=\"flex flex-col justify-end gap-1 rounded-lg border border-kumo-hairline bg-kumo-base p-4\">\n <Text size=\"lg\">Body lg</Text>\n <Text variant=\"mono-secondary\">text-lg (16px)</Text>\n </div>\n <div className=\"flex flex-col justify-end gap-1 rounded-lg border border-kumo-hairline bg-kumo-base p-4\">\n <Text size=\"sm\">Body sm</Text>\n <Text variant=\"mono-secondary\">text-sm (13px)</Text>\n </div>\n <div className=\"flex flex-col justify-end gap-1 rounded-lg border border-kumo-hairline bg-kumo-base p-4\">\n <Text size=\"xs\">Body xs</Text>\n <Text variant=\"mono-secondary\">text-xs (12px)</Text>\n </div>\n <div className=\"flex flex-col justify-end gap-1 rounded-lg border border-kumo-hairline bg-kumo-base p-4\">\n <Text variant=\"secondary\">Body secondary</Text>\n <Text variant=\"mono-secondary\">text-base (14px)</Text>\n </div>\n <div className=\"flex flex-col justify-end gap-1 rounded-lg border border-kumo-hairline bg-kumo-base p-4\">\n <Text variant=\"mono\">Monospace</Text>\n <Text variant=\"mono-secondary\">text-sm (13px)</Text>\n </div>\n <div className=\"flex flex-col justify-end gap-1 rounded-lg border border-kumo-hairline bg-kumo-base p-4\">\n <Text variant=\"mono\" size=\"lg\">\n Monospace lg\n </Text>\n <Text variant=\"mono-secondary\">text-base (14px)</Text>\n </div>\n <div className=\"flex flex-col justify-end gap-1 rounded-lg border border-kumo-hairline bg-kumo-base p-4\">\n <Text variant=\"mono-secondary\">Monospace secondary</Text>\n <Text variant=\"mono-secondary\">text-sm (13px)</Text>\n </div>\n <div className=\"flex flex-col justify-end gap-1 rounded-lg border border-kumo-hairline bg-kumo-base p-4\">\n <Text variant=\"success\">Success</Text>\n <Text variant=\"mono-secondary\">text-base (14px)</Text>\n </div>\n <div className=\"flex flex-col justify-end gap-1 rounded-lg border border-kumo-hairline bg-kumo-base p-4\">\n <Text variant=\"error\">Error</Text>\n <Text variant=\"mono-secondary\">text-base (14px)</Text>\n </div>\n </div>",
5193
5827
  "<div className=\"w-64 rounded-lg border border-kumo-hairline bg-kumo-base p-4\">\n <Text truncate>\n This is a long piece of text that will be truncated with an ellipsis\n when it overflows its container.\n </Text>\n </div>"
5194
5828
  ],
5195
5829
  "colors": [
@@ -5624,6 +6258,18 @@
5624
6258
  },
5625
6259
  "search": {
5626
6260
  "byCategory": {
6261
+ "Other": [
6262
+ "Autocomplete",
6263
+ "CloudflareLogo",
6264
+ "DatePicker",
6265
+ "Label",
6266
+ "Link",
6267
+ "SensitiveInput",
6268
+ "Sidebar",
6269
+ "Table",
6270
+ "TableOfContents",
6271
+ "DeleteResource"
6272
+ ],
5627
6273
  "Display": [
5628
6274
  "Badge",
5629
6275
  "Breadcrumbs",
@@ -5649,21 +6295,11 @@
5649
6295
  "DateRangePicker",
5650
6296
  "Field",
5651
6297
  "Input",
6298
+ "InputGroup",
5652
6299
  "Radio",
5653
6300
  "Select",
5654
6301
  "Switch"
5655
6302
  ],
5656
- "Other": [
5657
- "CloudflareLogo",
5658
- "DatePicker",
5659
- "Label",
5660
- "Link",
5661
- "SensitiveInput",
5662
- "Sidebar",
5663
- "Table",
5664
- "TableOfContents",
5665
- "DeleteResource"
5666
- ],
5667
6303
  "Navigation": [
5668
6304
  "CommandPalette",
5669
6305
  "MenuBar",
@@ -5684,6 +6320,7 @@
5684
6320
  ]
5685
6321
  },
5686
6322
  "byName": [
6323
+ "Autocomplete",
5687
6324
  "Badge",
5688
6325
  "Banner",
5689
6326
  "Breadcrumbs",
@@ -5704,6 +6341,7 @@
5704
6341
  "Field",
5705
6342
  "Grid",
5706
6343
  "Input",
6344
+ "InputGroup",
5707
6345
  "Label",
5708
6346
  "LayerCard",
5709
6347
  "Link",
@@ -5729,6 +6367,7 @@
5729
6367
  ],
5730
6368
  "byType": {
5731
6369
  "component": [
6370
+ "Autocomplete",
5732
6371
  "Badge",
5733
6372
  "Banner",
5734
6373
  "Breadcrumbs",
@@ -5748,6 +6387,7 @@
5748
6387
  "Field",
5749
6388
  "Grid",
5750
6389
  "Input",
6390
+ "InputGroup",
5751
6391
  "Label",
5752
6392
  "LayerCard",
5753
6393
  "Link",