@cloudflare/kumo 1.18.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (330) hide show
  1. package/CHANGELOG.md +329 -0
  2. package/ai/component-registry.json +907 -159
  3. package/ai/component-registry.md +1929 -598
  4. package/ai/schemas.ts +58 -14
  5. package/dist/.build-complete +1 -1
  6. package/dist/ai/schemas.d.ts +206 -27
  7. package/dist/ai/schemas.d.ts.map +1 -1
  8. package/dist/ai/schemas.js +2003 -1948
  9. package/dist/ai/schemas.js.map +1 -1
  10. package/dist/chunks/Legend-ibjxhfm9pn2vrb6f.js +430 -0
  11. package/dist/chunks/Legend-ibjxhfm9pn2vrb6f.js.map +1 -0
  12. package/dist/chunks/autocomplete-cs3fwy6lwzlyirpq.js +174 -0
  13. package/dist/chunks/autocomplete-cs3fwy6lwzlyirpq.js.map +1 -0
  14. package/dist/chunks/{breadcrumbs-k39s28qx05vbxxth.js → breadcrumbs-cxcwf2l1ki3ffg5d.js} +2 -2
  15. package/dist/chunks/{breadcrumbs-k39s28qx05vbxxth.js.map → breadcrumbs-cxcwf2l1ki3ffg5d.js.map} +1 -1
  16. package/dist/chunks/{button-cdxnqcgzwko8ooha.js → button-6by9ntsa3nj553mq.js} +18 -19
  17. package/dist/chunks/button-6by9ntsa3nj553mq.js.map +1 -0
  18. package/dist/chunks/checkbox-eren6w2csum1xghg.js +210 -0
  19. package/dist/chunks/checkbox-eren6w2csum1xghg.js.map +1 -0
  20. package/dist/chunks/{clipboard-text-vcbvmtne4zjk4b18.js → clipboard-text-f9q753udny1uyxr5.js} +47 -43
  21. package/dist/chunks/{clipboard-text-vcbvmtne4zjk4b18.js.map → clipboard-text-f9q753udny1uyxr5.js.map} +1 -1
  22. package/dist/chunks/{cloudflare-logo-bgts2jgsdh7sslw4.js → cloudflare-logo-pbavoe1wu8nr5c4n.js} +9 -9
  23. package/dist/chunks/{cloudflare-logo-bgts2jgsdh7sslw4.js.map → cloudflare-logo-pbavoe1wu8nr5c4n.js.map} +1 -1
  24. package/dist/chunks/collapsible-k8urhi16pg90jvxa.js +71 -0
  25. package/dist/chunks/collapsible-k8urhi16pg90jvxa.js.map +1 -0
  26. package/dist/chunks/{combobox-he2hd9e2ruknq5mp.js → combobox-n9qht9h9ag6kh5sn.js} +142 -118
  27. package/dist/chunks/combobox-n9qht9h9ag6kh5sn.js.map +1 -0
  28. package/dist/chunks/{command-palette-jc1w07jwakxvj23a.js → command-palette-gk9m34ymp2b3hfc5.js} +130 -130
  29. package/dist/chunks/command-palette-gk9m34ymp2b3hfc5.js.map +1 -0
  30. package/dist/chunks/{date-range-picker-j318zxjyqz4o3dak.js → date-range-picker-c9wnx9tbwohai7jy.js} +26 -26
  31. package/dist/chunks/{date-range-picker-j318zxjyqz4o3dak.js.map → date-range-picker-c9wnx9tbwohai7jy.js.map} +1 -1
  32. package/dist/chunks/{dialog-oqh8l3l3zutpibxx.js → dialog-94v7wiz7j3in6528.js} +25 -25
  33. package/dist/chunks/dialog-94v7wiz7j3in6528.js.map +1 -0
  34. package/dist/chunks/dropdown-zbax0zowy6m9zhmt.js +302 -0
  35. package/dist/chunks/dropdown-zbax0zowy6m9zhmt.js.map +1 -0
  36. package/dist/chunks/{empty-cj898km1r8xwuw44.js → empty-kpymw59thjf2ip8g.js} +9 -9
  37. package/dist/chunks/{empty-cj898km1r8xwuw44.js.map → empty-kpymw59thjf2ip8g.js.map} +1 -1
  38. package/dist/chunks/{field-krp6z6vfbkrvufz2.js → field-lnj619xpe8zjd26r.js} +7 -7
  39. package/dist/chunks/{field-krp6z6vfbkrvufz2.js.map → field-lnj619xpe8zjd26r.js.map} +1 -1
  40. package/dist/chunks/{grid-m9r71jxo2b8q1972.js → grid-hj1ylz16p7g5uelh.js} +2 -2
  41. package/dist/chunks/{grid-m9r71jxo2b8q1972.js.map → grid-hj1ylz16p7g5uelh.js.map} +1 -1
  42. package/dist/chunks/{input-area-no30c09udyjxshu5.js → input-area-h8xbqturegdfm1mi.js} +4 -4
  43. package/dist/chunks/{input-area-no30c09udyjxshu5.js.map → input-area-h8xbqturegdfm1mi.js.map} +1 -1
  44. package/dist/chunks/input-group-dh4pg8p20rh4mdi0.js +505 -0
  45. package/dist/chunks/input-group-dh4pg8p20rh4mdi0.js.map +1 -0
  46. package/dist/chunks/{input-h48k3uagzrgb98au.js → input-lpa5fc75tgrraafv.js} +45 -45
  47. package/dist/chunks/input-lpa5fc75tgrraafv.js.map +1 -0
  48. package/dist/chunks/label-be8m7qzlakzig2sl.js +68 -0
  49. package/dist/chunks/{label-latndvb1ngem7we8.js.map → label-be8m7qzlakzig2sl.js.map} +1 -1
  50. package/dist/chunks/layer-card-hvivdirwwnyq88wa.js +46 -0
  51. package/dist/chunks/layer-card-hvivdirwwnyq88wa.js.map +1 -0
  52. package/dist/chunks/{link-hn5ejal7nhh0o0b4.js → link-kt74pxkud4olmcer.js} +4 -4
  53. package/dist/chunks/{link-hn5ejal7nhh0o0b4.js.map → link-kt74pxkud4olmcer.js.map} +1 -1
  54. package/dist/chunks/menubar-hwev159bm4rw9ixk.js +96 -0
  55. package/dist/chunks/menubar-hwev159bm4rw9ixk.js.map +1 -0
  56. package/dist/chunks/{meter-gfa1hz9fhjnvx784.js → meter-bqetlujwg8gm2u7m.js} +2 -2
  57. package/dist/chunks/{meter-gfa1hz9fhjnvx784.js.map → meter-bqetlujwg8gm2u7m.js.map} +1 -1
  58. package/dist/chunks/pagination-ho8zesqfyp6ckmrl.js +266 -0
  59. package/dist/chunks/pagination-ho8zesqfyp6ckmrl.js.map +1 -0
  60. package/dist/chunks/{popover-h300w4vit0s2ayej.js → popover-iayd9ya5yhujz6ve.js} +69 -73
  61. package/dist/chunks/popover-iayd9ya5yhujz6ve.js.map +1 -0
  62. package/dist/chunks/{radio-jouttv89lbvhs55r.js → radio-datzh3pilz8ojak1.js} +87 -75
  63. package/dist/chunks/radio-datzh3pilz8ojak1.js.map +1 -0
  64. package/dist/chunks/select-kpfbib9l8xrrmzpz.js +215 -0
  65. package/dist/chunks/select-kpfbib9l8xrrmzpz.js.map +1 -0
  66. package/dist/chunks/{sensitive-input-hd4tpqkzifad1yca.js → sensitive-input-i1upqytzaw2pus8v.js} +42 -42
  67. package/dist/chunks/sensitive-input-i1upqytzaw2pus8v.js.map +1 -0
  68. package/dist/chunks/{sidebar-hljy3ssm8itc0ucx.js → sidebar-kh37grvfxto14ek6.js} +146 -147
  69. package/dist/chunks/sidebar-kh37grvfxto14ek6.js.map +1 -0
  70. package/dist/chunks/surface-o63tktyrifcjejyb.js +29 -0
  71. package/dist/chunks/surface-o63tktyrifcjejyb.js.map +1 -0
  72. package/dist/chunks/{switch-ihaydbzem62bey4p.js → switch-lclhiplr9zqf73tj.js} +89 -81
  73. package/dist/chunks/switch-lclhiplr9zqf73tj.js.map +1 -0
  74. package/dist/chunks/table-fyy8gl875yyevqs3.js +207 -0
  75. package/dist/chunks/table-fyy8gl875yyevqs3.js.map +1 -0
  76. package/dist/chunks/table-of-contents-fzyv7uhnnyr13dqu.js +102 -0
  77. package/dist/chunks/table-of-contents-fzyv7uhnnyr13dqu.js.map +1 -0
  78. package/dist/chunks/{tabs-e7eh7l3mpk3xgmwq.js → tabs-jywwt8ebjqjkux75.js} +21 -21
  79. package/dist/chunks/{tabs-e7eh7l3mpk3xgmwq.js.map → tabs-jywwt8ebjqjkux75.js.map} +1 -1
  80. package/dist/chunks/{text-nmyi1rkwdj37f30f.js → text-f7t467waymhb30sx.js} +8 -8
  81. package/dist/chunks/text-f7t467waymhb30sx.js.map +1 -0
  82. package/dist/chunks/{toast-bpz6iaq54u9jmuu8.js → toast-h573o0tc7tefivk2.js} +12 -12
  83. package/dist/chunks/{toast-bpz6iaq54u9jmuu8.js.map → toast-h573o0tc7tefivk2.js.map} +1 -1
  84. package/dist/chunks/{tooltip-belkznz8t8333h5f.js → tooltip-odudhkxe282wxinq.js} +38 -37
  85. package/dist/chunks/tooltip-odudhkxe282wxinq.js.map +1 -0
  86. package/dist/chunks/vendor-base-ui-ie71jahf0czyf58j.js +24638 -0
  87. package/dist/chunks/vendor-base-ui-ie71jahf0czyf58j.js.map +1 -0
  88. package/dist/chunks/vendor-floating-ui-dwag5e88viikh2zs.js +1311 -0
  89. package/dist/chunks/vendor-floating-ui-dwag5e88viikh2zs.js.map +1 -0
  90. package/dist/chunks/vendor-utils-ixnhxmehwihk5tr7.js +534 -0
  91. package/dist/chunks/vendor-utils-ixnhxmehwihk5tr7.js.map +1 -0
  92. package/dist/code.js +1 -1
  93. package/dist/components/autocomplete.js +9 -0
  94. package/dist/components/autocomplete.js.map +1 -0
  95. package/dist/components/breadcrumbs.js +1 -1
  96. package/dist/components/button.js +1 -1
  97. package/dist/components/chart.js +1 -1
  98. package/dist/components/checkbox.js +1 -1
  99. package/dist/components/clipboard-text.js +1 -1
  100. package/dist/components/cloudflare-logo.js +1 -1
  101. package/dist/components/collapsible.js +1 -1
  102. package/dist/components/combobox.js +1 -1
  103. package/dist/components/command-palette.js +1 -1
  104. package/dist/components/date-range-picker.js +1 -1
  105. package/dist/components/dialog.js +1 -1
  106. package/dist/components/dropdown.js +1 -1
  107. package/dist/components/empty.js +1 -1
  108. package/dist/components/field.js +1 -1
  109. package/dist/components/flow.js +2 -2
  110. package/dist/components/flow.js.map +1 -1
  111. package/dist/components/grid.js +1 -1
  112. package/dist/components/input-group.js +8 -0
  113. package/dist/components/input-group.js.map +1 -0
  114. package/dist/components/input.js +9 -7
  115. package/dist/components/label.js +1 -1
  116. package/dist/components/layer-card.js +1 -1
  117. package/dist/components/link.js +1 -1
  118. package/dist/components/menubar.js +1 -1
  119. package/dist/components/meter.js +1 -1
  120. package/dist/components/pagination.js +1 -1
  121. package/dist/components/popover.js +1 -1
  122. package/dist/components/radio.js +1 -1
  123. package/dist/components/select.js +1 -1
  124. package/dist/components/sensitive-input.js +1 -1
  125. package/dist/components/sidebar.js +1 -1
  126. package/dist/components/surface.js +1 -1
  127. package/dist/components/switch.js +1 -1
  128. package/dist/components/table-of-contents.js +8 -0
  129. package/dist/components/table-of-contents.js.map +1 -0
  130. package/dist/components/table.js +1 -1
  131. package/dist/components/tabs.js +1 -1
  132. package/dist/components/text.js +1 -1
  133. package/dist/components/toast.js +2 -2
  134. package/dist/components/tooltip.js +1 -1
  135. package/dist/index.js +148 -139
  136. package/dist/index.js.map +1 -1
  137. package/dist/primitives/accordion.js +1 -1
  138. package/dist/primitives/alert-dialog.js +1 -1
  139. package/dist/primitives/autocomplete.js +1 -1
  140. package/dist/primitives/avatar.js +1 -1
  141. package/dist/primitives/button.js +1 -1
  142. package/dist/primitives/checkbox-group.js +1 -1
  143. package/dist/primitives/checkbox.js +1 -1
  144. package/dist/primitives/collapsible.js +1 -1
  145. package/dist/primitives/combobox.js +1 -1
  146. package/dist/primitives/context-menu.js +1 -1
  147. package/dist/primitives/csp-provider.js +1 -1
  148. package/dist/primitives/dialog.js +1 -1
  149. package/dist/primitives/direction-provider.js +1 -1
  150. package/dist/primitives/drawer.js +2 -2
  151. package/dist/primitives/field.js +1 -1
  152. package/dist/primitives/fieldset.js +1 -1
  153. package/dist/primitives/form.js +1 -1
  154. package/dist/primitives/input.js +1 -1
  155. package/dist/primitives/menu.js +1 -1
  156. package/dist/primitives/menubar.js +1 -1
  157. package/dist/primitives/meter.js +1 -1
  158. package/dist/primitives/navigation-menu.js +1 -1
  159. package/dist/primitives/number-field.js +1 -1
  160. package/dist/primitives/otp-field.js +6 -0
  161. package/dist/primitives/otp-field.js.map +1 -0
  162. package/dist/primitives/popover.js +1 -1
  163. package/dist/primitives/preview-card.js +2 -2
  164. package/dist/primitives/progress.js +1 -1
  165. package/dist/primitives/radio-group.js +1 -1
  166. package/dist/primitives/radio.js +1 -1
  167. package/dist/primitives/scroll-area.js +1 -1
  168. package/dist/primitives/select.js +1 -1
  169. package/dist/primitives/separator.js +1 -1
  170. package/dist/primitives/slider.js +1 -1
  171. package/dist/primitives/switch.js +1 -1
  172. package/dist/primitives/tabs.js +1 -1
  173. package/dist/primitives/toast.js +1 -1
  174. package/dist/primitives/toggle-group.js +1 -1
  175. package/dist/primitives/toggle.js +1 -1
  176. package/dist/primitives/toolbar.js +1 -1
  177. package/dist/primitives/tooltip.js +1 -1
  178. package/dist/primitives.js +22 -21
  179. package/dist/scripts/theme-generator/config.d.ts.map +1 -1
  180. package/dist/scripts/theme-generator/config.js +13 -3
  181. package/dist/scripts/theme-generator/config.js.map +1 -1
  182. package/dist/src/components/autocomplete/autocomplete.d.ts +180 -0
  183. package/dist/src/components/autocomplete/autocomplete.d.ts.map +1 -0
  184. package/dist/src/components/autocomplete/index.d.ts +2 -0
  185. package/dist/src/components/autocomplete/index.d.ts.map +1 -0
  186. package/dist/src/components/button/button.d.ts +3 -3
  187. package/dist/src/components/button/button.d.ts.map +1 -1
  188. package/dist/src/components/chart/Color.d.ts +36 -52
  189. package/dist/src/components/chart/Color.d.ts.map +1 -1
  190. package/dist/src/components/chart/EChart.d.ts +18 -2
  191. package/dist/src/components/chart/EChart.d.ts.map +1 -1
  192. package/dist/src/components/chart/TimeseriesChart.d.ts.map +1 -1
  193. package/dist/src/components/chart/index.d.ts +1 -1
  194. package/dist/src/components/chart/index.d.ts.map +1 -1
  195. package/dist/src/components/checkbox/checkbox.d.ts +37 -14
  196. package/dist/src/components/checkbox/checkbox.d.ts.map +1 -1
  197. package/dist/src/components/checkbox/index.d.ts +1 -1
  198. package/dist/src/components/checkbox/index.d.ts.map +1 -1
  199. package/dist/src/components/clipboard-text/clipboard-text.d.ts.map +1 -1
  200. package/dist/src/components/collapsible/collapsible.d.ts +77 -40
  201. package/dist/src/components/collapsible/collapsible.d.ts.map +1 -1
  202. package/dist/src/components/collapsible/index.d.ts +1 -1
  203. package/dist/src/components/collapsible/index.d.ts.map +1 -1
  204. package/dist/src/components/combobox/combobox.d.ts +19 -3
  205. package/dist/src/components/combobox/combobox.d.ts.map +1 -1
  206. package/dist/src/components/command-palette/command-palette.d.ts +2 -11
  207. package/dist/src/components/command-palette/command-palette.d.ts.map +1 -1
  208. package/dist/src/components/command-palette/index.d.ts +1 -1
  209. package/dist/src/components/command-palette/index.d.ts.map +1 -1
  210. package/dist/src/components/command-palette/types.d.ts +13 -1
  211. package/dist/src/components/command-palette/types.d.ts.map +1 -1
  212. package/dist/src/components/dropdown/dropdown.d.ts.map +1 -1
  213. package/dist/src/components/input/index.d.ts +16 -1
  214. package/dist/src/components/input/index.d.ts.map +1 -1
  215. package/dist/src/components/input/input.d.ts +2 -2
  216. package/dist/src/components/input/input.d.ts.map +1 -1
  217. package/dist/src/components/input-group/context.d.ts +96 -0
  218. package/dist/src/components/input-group/context.d.ts.map +1 -0
  219. package/dist/src/components/input-group/index.d.ts +2 -0
  220. package/dist/src/components/input-group/index.d.ts.map +1 -0
  221. package/dist/src/components/input-group/input-group-addon.d.ts +15 -0
  222. package/dist/src/components/input-group/input-group-addon.d.ts.map +1 -0
  223. package/dist/src/components/input-group/input-group-button.d.ts +36 -0
  224. package/dist/src/components/input-group/input-group-button.d.ts.map +1 -0
  225. package/dist/src/components/input-group/input-group-input.d.ts +9 -0
  226. package/dist/src/components/input-group/input-group-input.d.ts.map +1 -0
  227. package/dist/src/components/input-group/input-group-suffix.d.ts +13 -0
  228. package/dist/src/components/input-group/input-group-suffix.d.ts.map +1 -0
  229. package/dist/src/components/input-group/input-group.d.ts +43 -0
  230. package/dist/src/components/input-group/input-group.d.ts.map +1 -0
  231. package/dist/src/components/label/label.d.ts.map +1 -1
  232. package/dist/src/components/layer-card/layer-card.d.ts +39 -5
  233. package/dist/src/components/layer-card/layer-card.d.ts.map +1 -1
  234. package/dist/src/components/menubar/menubar.d.ts.map +1 -1
  235. package/dist/src/components/pagination/pagination.d.ts +51 -1
  236. package/dist/src/components/pagination/pagination.d.ts.map +1 -1
  237. package/dist/src/components/popover/popover.d.ts +35 -8
  238. package/dist/src/components/popover/popover.d.ts.map +1 -1
  239. package/dist/src/components/radio/index.d.ts +1 -1
  240. package/dist/src/components/radio/index.d.ts.map +1 -1
  241. package/dist/src/components/radio/radio.d.ts +44 -8
  242. package/dist/src/components/radio/radio.d.ts.map +1 -1
  243. package/dist/src/components/select/select.d.ts +52 -8
  244. package/dist/src/components/select/select.d.ts.map +1 -1
  245. package/dist/src/components/sensitive-input/sensitive-input.d.ts +2 -2
  246. package/dist/src/components/sidebar/sidebar.d.ts +2 -2
  247. package/dist/src/components/sidebar/sidebar.d.ts.map +1 -1
  248. package/dist/src/components/surface/index.d.ts +3 -0
  249. package/dist/src/components/surface/index.d.ts.map +1 -1
  250. package/dist/src/components/surface/surface.d.ts +14 -10
  251. package/dist/src/components/surface/surface.d.ts.map +1 -1
  252. package/dist/src/components/switch/index.d.ts +1 -1
  253. package/dist/src/components/switch/index.d.ts.map +1 -1
  254. package/dist/src/components/switch/switch.d.ts +31 -3
  255. package/dist/src/components/switch/switch.d.ts.map +1 -1
  256. package/dist/src/components/table/table.d.ts +17 -2
  257. package/dist/src/components/table/table.d.ts.map +1 -1
  258. package/dist/src/components/table-of-contents/index.d.ts +2 -0
  259. package/dist/src/components/table-of-contents/index.d.ts.map +1 -0
  260. package/dist/src/components/table-of-contents/table-of-contents.d.ts +72 -0
  261. package/dist/src/components/table-of-contents/table-of-contents.d.ts.map +1 -0
  262. package/dist/src/components/text/text.d.ts +34 -6
  263. package/dist/src/components/text/text.d.ts.map +1 -1
  264. package/dist/src/components/text/text.type-spec.d.ts +44 -0
  265. package/dist/src/components/text/text.type-spec.d.ts.map +1 -0
  266. package/dist/src/components/toast/toast.d.ts +1 -1
  267. package/dist/src/components/toast/toast.d.ts.map +1 -1
  268. package/dist/src/components/tooltip/tooltip.d.ts +15 -6
  269. package/dist/src/components/tooltip/tooltip.d.ts.map +1 -1
  270. package/dist/src/index.d.ts +14 -8
  271. package/dist/src/index.d.ts.map +1 -1
  272. package/dist/src/primitives/index.d.ts +1 -0
  273. package/dist/src/primitives/index.d.ts.map +1 -1
  274. package/dist/src/primitives/otp-field.d.ts +13 -0
  275. package/dist/src/primitives/otp-field.d.ts.map +1 -0
  276. package/dist/styles/kumo-binding.css +19 -0
  277. package/dist/styles/kumo-standalone.css +1 -1
  278. package/dist/styles/kumo.css +2 -2
  279. package/dist/styles/theme-kumo.css +13 -6
  280. package/package.json +18 -2
  281. package/scripts/component-registry/discovery.ts +1 -0
  282. package/scripts/component-registry/index.test.ts +265 -0
  283. package/scripts/component-registry/index.ts +14 -0
  284. package/scripts/component-registry/metadata.ts +55 -7
  285. package/scripts/component-registry/sub-components.ts +81 -50
  286. package/scripts/component-registry/types.ts +2 -0
  287. package/scripts/theme-generator/config.ts +18 -6
  288. package/dist/chunks/Legend-o0ntojbaplmszwk0.js +0 -421
  289. package/dist/chunks/Legend-o0ntojbaplmszwk0.js.map +0 -1
  290. package/dist/chunks/button-cdxnqcgzwko8ooha.js.map +0 -1
  291. package/dist/chunks/checkbox-kt1uojk2f9e0d0h1.js +0 -211
  292. package/dist/chunks/checkbox-kt1uojk2f9e0d0h1.js.map +0 -1
  293. package/dist/chunks/collapsible-jhzee3ks51d3xowb.js +0 -58
  294. package/dist/chunks/collapsible-jhzee3ks51d3xowb.js.map +0 -1
  295. package/dist/chunks/combobox-he2hd9e2ruknq5mp.js.map +0 -1
  296. package/dist/chunks/command-palette-jc1w07jwakxvj23a.js.map +0 -1
  297. package/dist/chunks/dialog-oqh8l3l3zutpibxx.js.map +0 -1
  298. package/dist/chunks/dropdown-ncwhcd912vmone8k.js +0 -300
  299. package/dist/chunks/dropdown-ncwhcd912vmone8k.js.map +0 -1
  300. package/dist/chunks/input-group-lxdd09p60cf27pe1.js +0 -111
  301. package/dist/chunks/input-group-lxdd09p60cf27pe1.js.map +0 -1
  302. package/dist/chunks/input-h48k3uagzrgb98au.js.map +0 -1
  303. package/dist/chunks/label-latndvb1ngem7we8.js +0 -62
  304. package/dist/chunks/layer-card-l5yjvrxry1dhte57.js +0 -44
  305. package/dist/chunks/layer-card-l5yjvrxry1dhte57.js.map +0 -1
  306. package/dist/chunks/menubar-f1pilzooe5mue7c4.js +0 -92
  307. package/dist/chunks/menubar-f1pilzooe5mue7c4.js.map +0 -1
  308. package/dist/chunks/pagination-cu5lm6p5dxuycta4.js +0 -243
  309. package/dist/chunks/pagination-cu5lm6p5dxuycta4.js.map +0 -1
  310. package/dist/chunks/popover-h300w4vit0s2ayej.js.map +0 -1
  311. package/dist/chunks/radio-jouttv89lbvhs55r.js.map +0 -1
  312. package/dist/chunks/select-kva5ru5f673kah1m.js +0 -179
  313. package/dist/chunks/select-kva5ru5f673kah1m.js.map +0 -1
  314. package/dist/chunks/sensitive-input-hd4tpqkzifad1yca.js.map +0 -1
  315. package/dist/chunks/sidebar-hljy3ssm8itc0ucx.js.map +0 -1
  316. package/dist/chunks/surface-cilvbyhmyujz1bee.js +0 -36
  317. package/dist/chunks/surface-cilvbyhmyujz1bee.js.map +0 -1
  318. package/dist/chunks/switch-ihaydbzem62bey4p.js.map +0 -1
  319. package/dist/chunks/table-inweecadl3her7pd.js +0 -183
  320. package/dist/chunks/table-inweecadl3her7pd.js.map +0 -1
  321. package/dist/chunks/text-nmyi1rkwdj37f30f.js.map +0 -1
  322. package/dist/chunks/tooltip-belkznz8t8333h5f.js.map +0 -1
  323. package/dist/chunks/vendor-base-ui-k7bzesq81ie36nya.js +0 -22813
  324. package/dist/chunks/vendor-base-ui-k7bzesq81ie36nya.js.map +0 -1
  325. package/dist/chunks/vendor-floating-ui-gr9m6tsa1cpqwn99.js +0 -1286
  326. package/dist/chunks/vendor-floating-ui-gr9m6tsa1cpqwn99.js.map +0 -1
  327. package/dist/chunks/vendor-utils-fxk97j6xi1g42z2v.js +0 -740
  328. package/dist/chunks/vendor-utils-fxk97j6xi1g42z2v.js.map +0 -1
  329. package/dist/src/components/input/input-group.d.ts +0 -39
  330. package/dist/src/components/input/input-group.d.ts.map +0 -1
@@ -2,6 +2,266 @@
2
2
 
3
3
  > Auto-generated component metadata for AI/agent consumption.
4
4
 
5
+ ---
6
+
7
+ ### Autocomplete
8
+
9
+ 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.
10
+
11
+ **Type:** component
12
+
13
+ **Import:** `import { Autocomplete } from "@cloudflare/kumo";`
14
+
15
+ **Category:** Other
16
+
17
+ **Props:**
18
+
19
+ - `items`: unknown[] (required)
20
+ Array of items to display in the dropdown
21
+ - `value`: string | number | string[]
22
+ The controlled input value
23
+ - `open`: boolean
24
+ Whether the popup is open (controlled)
25
+ - `children`: ReactNode
26
+ Autocomplete content (input group, popup content)
27
+ - `className`: string
28
+ Additional CSS classes
29
+ - `label`: ReactNode
30
+ Label content (enables Field wrapper)
31
+ - `required`: boolean
32
+ Whether the field is required
33
+ - `labelTooltip`: ReactNode
34
+ Tooltip content to display next to the label
35
+ - `description`: ReactNode
36
+ Helper text displayed below the field
37
+ - `error`: string | object
38
+ Error message or validation error object
39
+
40
+ **Colors (kumo tokens used):**
41
+
42
+ `bg-kumo-control`, `bg-kumo-line`, `bg-kumo-overlay`, `border-kumo-line`, `ring-kumo-line`, `text-kumo-default`, `text-kumo-strong`
43
+
44
+ **Sub-Components:**
45
+
46
+ This is a compound component. Use these sub-components:
47
+
48
+ #### Autocomplete.InputGroup
49
+
50
+ InputGroup sub-component
51
+
52
+ Props:
53
+ - `className`: string
54
+ - `size`: KumoAutocompleteSize
55
+ - `placeholder`: string
56
+
57
+ #### Autocomplete.Content
58
+
59
+ Content sub-component
60
+
61
+ Props:
62
+ - `children`: ReactNode
63
+ - `className`: string
64
+ - `align`: AutocompleteBase.Positioner.Props["align"]
65
+ - `alignOffset`: AutocompleteBase.Positioner.Props["alignOffset"]
66
+ - `side`: AutocompleteBase.Positioner.Props["side"]
67
+ - `sideOffset`: AutocompleteBase.Positioner.Props["sideOffset"]
68
+
69
+ #### Autocomplete.Item
70
+
71
+ Item sub-component
72
+
73
+ #### Autocomplete.GroupLabel
74
+
75
+ GroupLabel sub-component
76
+
77
+ #### Autocomplete.Group
78
+
79
+ Group sub-component
80
+
81
+ #### Autocomplete.Separator
82
+
83
+ Separator sub-component
84
+
85
+ #### Autocomplete.List
86
+
87
+ List sub-component
88
+
89
+ #### Autocomplete.Empty
90
+
91
+ Empty sub-component (wraps AutocompleteBase)
92
+
93
+ #### Autocomplete.Collection
94
+
95
+ Collection sub-component (wraps AutocompleteBase)
96
+
97
+
98
+ **Examples:**
99
+
100
+ ```tsx
101
+ <Autocomplete items={fruits}>
102
+ <Autocomplete.InputGroup placeholder="Search fruits…" />
103
+ <Autocomplete.Content>
104
+ <Autocomplete.List>
105
+ {(item: string) => (
106
+ <Autocomplete.Item key={item} value={item}>
107
+ {item}
108
+ </Autocomplete.Item>
109
+ )}
110
+ </Autocomplete.List>
111
+ </Autocomplete.Content>
112
+ </Autocomplete>
113
+ ```
114
+
115
+ ```tsx
116
+ <div className="w-80">
117
+ <Autocomplete
118
+ items={countries}
119
+ label="Country"
120
+ description="Start typing to filter countries"
121
+ filter={(item: Country, query: string) =>
122
+ item.label.toLowerCase().includes(query.toLowerCase())
123
+ }
124
+ >
125
+ <Autocomplete.InputGroup placeholder="Search countries…" />
126
+ <Autocomplete.Content>
127
+ <Autocomplete.List>
128
+ {(item: Country) => (
129
+ <Autocomplete.Item key={item.code} value={item}>
130
+ {item.label}
131
+ </Autocomplete.Item>
132
+ )}
133
+ </Autocomplete.List>
134
+ </Autocomplete.Content>
135
+ </Autocomplete>
136
+ </div>
137
+ ```
138
+
139
+ ```tsx
140
+ <div className="w-80">
141
+ <Autocomplete
142
+ items={countries}
143
+ label="Country"
144
+ error={{ message: "Please enter a valid country", match: true }}
145
+ filter={(item: Country, query: string) =>
146
+ item.label.toLowerCase().includes(query.toLowerCase())
147
+ }
148
+ >
149
+ <Autocomplete.InputGroup placeholder="Search countries…" />
150
+ <Autocomplete.Content>
151
+ <Autocomplete.List>
152
+ {(item: Country) => (
153
+ <Autocomplete.Item key={item.code} value={item}>
154
+ {item.label}
155
+ </Autocomplete.Item>
156
+ )}
157
+ </Autocomplete.List>
158
+ </Autocomplete.Content>
159
+ </Autocomplete>
160
+ </div>
161
+ ```
162
+
163
+ ```tsx
164
+ <Autocomplete items={servers}>
165
+ <Autocomplete.InputGroup placeholder="Select region…" />
166
+ <Autocomplete.Content>
167
+ <Autocomplete.List>
168
+ {(group: ServerGroup) => (
169
+ <Autocomplete.Group key={group.value} items={group.items}>
170
+ <Autocomplete.GroupLabel>{group.value}</Autocomplete.GroupLabel>
171
+ <Autocomplete.Collection>
172
+ {(item: ServerLocation) => (
173
+ <Autocomplete.Item key={item.value} value={item}>
174
+ {item.label}
175
+ </Autocomplete.Item>
176
+ )}
177
+ </Autocomplete.Collection>
178
+ </Autocomplete.Group>
179
+ )}
180
+ </Autocomplete.List>
181
+ </Autocomplete.Content>
182
+ </Autocomplete>
183
+ ```
184
+
185
+ ```tsx
186
+ <div className="flex flex-wrap items-center gap-4">
187
+ <Autocomplete items={fruits.slice(0, 10)}>
188
+ <Autocomplete.InputGroup size="xs" placeholder="xs" />
189
+ <Autocomplete.Content>
190
+ <Autocomplete.List>
191
+ {(item: string) => (
192
+ <Autocomplete.Item key={item} value={item}>
193
+ {item}
194
+ </Autocomplete.Item>
195
+ )}
196
+ </Autocomplete.List>
197
+ </Autocomplete.Content>
198
+ </Autocomplete>
199
+ <Autocomplete items={fruits.slice(0, 10)}>
200
+ <Autocomplete.InputGroup size="sm" placeholder="sm" />
201
+ <Autocomplete.Content>
202
+ <Autocomplete.List>
203
+ {(item: string) => (
204
+ <Autocomplete.Item key={item} value={item}>
205
+ {item}
206
+ </Autocomplete.Item>
207
+ )}
208
+ </Autocomplete.List>
209
+ </Autocomplete.Content>
210
+ </Autocomplete>
211
+ <Autocomplete items={fruits.slice(0, 10)}>
212
+ <Autocomplete.InputGroup size="base" placeholder="base (default)" />
213
+ <Autocomplete.Content>
214
+ <Autocomplete.List>
215
+ {(item: string) => (
216
+ <Autocomplete.Item key={item} value={item}>
217
+ {item}
218
+ </Autocomplete.Item>
219
+ )}
220
+ </Autocomplete.List>
221
+ </Autocomplete.Content>
222
+ </Autocomplete>
223
+ <Autocomplete items={fruits.slice(0, 10)}>
224
+ <Autocomplete.InputGroup size="lg" placeholder="lg" />
225
+ <Autocomplete.Content>
226
+ <Autocomplete.List>
227
+ {(item: string) => (
228
+ <Autocomplete.Item key={item} value={item}>
229
+ {item}
230
+ </Autocomplete.Item>
231
+ )}
232
+ </Autocomplete.List>
233
+ </Autocomplete.Content>
234
+ </Autocomplete>
235
+ </div>
236
+ ```
237
+
238
+ ```tsx
239
+ <div className="flex flex-col gap-3 w-80">
240
+ <Autocomplete
241
+ items={fruits}
242
+ value={value}
243
+ onValueChange={(v) => setValue(v)}
244
+ >
245
+ <Autocomplete.InputGroup placeholder="Type a fruit…" />
246
+ <Autocomplete.Content>
247
+ <Autocomplete.List>
248
+ {(item: string) => (
249
+ <Autocomplete.Item key={item} value={item}>
250
+ {item}
251
+ </Autocomplete.Item>
252
+ )}
253
+ </Autocomplete.List>
254
+ </Autocomplete.Content>
255
+ </Autocomplete>
256
+ {value && (
257
+ <p className="text-sm text-kumo-subtle">
258
+ Value: <span className="text-kumo-default font-medium">{value}</span>
259
+ </p>
260
+ )}
261
+ </div>
262
+ ```
263
+
264
+
5
265
  ---
6
266
 
7
267
  ### Badge
@@ -353,10 +613,9 @@ Primary action trigger. Supports multiple variants, sizes, shapes, icons, and lo
353
613
  **State Classes:**
354
614
  - `"primary"`:
355
615
  - `hover`: `hover:bg-kumo-brand-hover`
356
- - `focus`: `focus:bg-kumo-brand-hover`
357
616
  - `disabled`: `disabled:bg-kumo-brand/50`
358
617
  - `"secondary"`:
359
- - `not-disabled`: `not-disabled:hover:border-secondary! not-disabled:hover:bg-kumo-tint`
618
+ - `not-disabled`: `not-disabled:hover:bg-kumo-tint`
360
619
  - `disabled`: `disabled:bg-kumo-base/50 disabled:!text-kumo-default/70`
361
620
  - `data-state`: `data-[state=open]:bg-kumo-base`
362
621
  - `"ghost"`:
@@ -364,7 +623,7 @@ Primary action trigger. Supports multiple variants, sizes, shapes, icons, and lo
364
623
  - `"destructive"`:
365
624
  - `hover`: `hover:bg-kumo-danger/70`
366
625
  - `"secondary-destructive"`:
367
- - `not-disabled`: `not-disabled:hover:border-secondary! not-disabled:hover:bg-kumo-base`
626
+ - `not-disabled`: `not-disabled:hover:bg-kumo-base`
368
627
  - `disabled`: `disabled:bg-kumo-base/50 disabled:!text-kumo-danger/70`
369
628
  - `data-state`: `data-[state=open]:bg-kumo-base`
370
629
  - `children`: ReactNode
@@ -383,7 +642,7 @@ Primary action trigger. Supports multiple variants, sizes, shapes, icons, and lo
383
642
 
384
643
  **Colors (kumo tokens used):**
385
644
 
386
- `bg-kumo-base`, `bg-kumo-brand`, `bg-kumo-brand-hover`, `bg-kumo-danger`, `bg-kumo-tint`, `ring-kumo-hairline`, `ring-kumo-line`, `text-kumo-danger`, `text-kumo-default`, `text-kumo-subtle`
645
+ `bg-kumo-base`, `bg-kumo-brand`, `bg-kumo-brand-hover`, `bg-kumo-danger`, `bg-kumo-tint`, `ring-kumo-brand`, `ring-kumo-focus`, `ring-kumo-hairline`, `text-kumo-danger`, `text-kumo-default`, `text-kumo-subtle`
387
646
 
388
647
  **Examples:**
389
648
 
@@ -479,7 +738,7 @@ Checkbox component
479
738
 
480
739
  **State Classes:**
481
740
  - `"default"`:
482
- - `focus`: `[&:focus-within>span]:ring-kumo-hairline`
741
+ - `focus`: `[&:focus-within>span]:ring-kumo-focus`
483
742
  - `hover`: `[&:hover>span]:ring-kumo-hairline`
484
743
  - `label`: ReactNode
485
744
  Label content for the checkbox (enables built-in Field wrapper) - can be a string or any React node
@@ -499,12 +758,10 @@ Checkbox component
499
758
  Whether the field is required
500
759
  - `className`: string
501
760
  Additional class name
502
- - `onValueChange`: (checked: boolean) => void
503
- Callback when checkbox value changes
504
761
 
505
762
  **Colors (kumo tokens used):**
506
763
 
507
- `bg-kumo-base`, `bg-kumo-contrast`, `ring-kumo-contrast`, `ring-kumo-danger`, `ring-kumo-hairline`, `ring-kumo-line`, `text-kumo-danger`, `text-kumo-default`, `text-kumo-inverse`, `text-kumo-subtle`
764
+ `bg-kumo-base`, `bg-kumo-contrast`, `ring-kumo-brand`, `ring-kumo-contrast`, `ring-kumo-danger`, `ring-kumo-focus`, `ring-kumo-hairline`, `text-kumo-danger`, `text-kumo-default`, `text-kumo-inverse`, `text-kumo-subtle`
508
765
 
509
766
  **Styling:**
510
767
 
@@ -535,7 +792,7 @@ Item sub-component
535
792
  Group sub-component
536
793
 
537
794
  Props:
538
- - `legend`: string (required)
795
+ - `legend`: string
539
796
  - `children`: ReactNode (required)
540
797
  - `error`: string
541
798
  - `description`: ReactNode
@@ -545,6 +802,14 @@ Props:
545
802
  - `controlFirst`: boolean
546
803
  - `className`: string
547
804
 
805
+ #### Checkbox.Legend
806
+
807
+ Legend sub-component
808
+
809
+ Props:
810
+ - `children`: ReactNode (required)
811
+ - `className`: string
812
+
548
813
 
549
814
  **Examples:**
550
815
 
@@ -594,6 +859,17 @@ Props:
594
859
  </Checkbox.Group>
595
860
  ```
596
861
 
862
+ ```tsx
863
+ <Checkbox.Group value={preferences} onValueChange={setPreferences}>
864
+ <Checkbox.Legend className="sr-only">
865
+ Notification preferences
866
+ </Checkbox.Legend>
867
+ <Checkbox.Item value="email" label="Email notifications" />
868
+ <Checkbox.Item value="sms" label="SMS notifications" />
869
+ <Checkbox.Item value="push" label="Push notifications" />
870
+ </Checkbox.Group>
871
+ ```
872
+
597
873
  ```tsx
598
874
  <Checkbox.Group
599
875
  legend="Required preferences"
@@ -638,7 +914,7 @@ Read-only text field with a one-click copy-to-clipboard button.
638
914
 
639
915
  **Colors (kumo tokens used):**
640
916
 
641
- `bg-kumo-base`, `border-kumo-line`, `outline-kumo-fill`, `text-kumo-default`
917
+ `bg-kumo-base`, `border-kumo-line`, `outline-kumo-fill`, `ring-kumo-brand`, `ring-kumo-focus`, `text-kumo-default`
642
918
 
643
919
  **Styling:**
644
920
 
@@ -980,7 +1256,7 @@ Cloudflare logo component.
980
1256
 
981
1257
  **Colors (kumo tokens used):**
982
1258
 
983
- `bg-kumo-base`, `ring-kumo-line`, `text-kumo-default`
1259
+ `bg-kumo-base`, `ring-kumo-hairline`, `text-kumo-default`
984
1260
 
985
1261
  **Examples:**
986
1262
 
@@ -1108,7 +1384,7 @@ Cloudflare logo component.
1108
1384
  ```
1109
1385
 
1110
1386
  ```tsx
1111
- <footer className="flex w-full items-center justify-between rounded-lg border border-kumo-line bg-kumo-elevated px-6 py-4">
1387
+ <footer className="flex w-full items-center justify-between rounded-lg border border-kumo-hairline bg-kumo-elevated px-6 py-4">
1112
1388
  <span className="text-sm text-kumo-subtle">
1113
1389
  &copy; 2026 Your Company. All rights reserved.
1114
1390
  </span>
@@ -1170,7 +1446,7 @@ Props:
1170
1446
 
1171
1447
  ### Collapsible
1172
1448
 
1173
- 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
1449
+ 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> ))} ```
1174
1450
 
1175
1451
  **Type:** component
1176
1452
 
@@ -1180,13 +1456,8 @@ Collapsible component for showing/hiding content. Features: - Animated chevron
1180
1456
 
1181
1457
  **Props:**
1182
1458
 
1183
- - `children`: ReactNode
1184
- - `label`: string (required)
1185
- Text label displayed in the trigger button
1186
- - `open`: boolean
1187
- Whether the collapsible content is visible
1188
1459
  - `className`: string
1189
- Additional CSS classes for the content panel
1460
+ Additional CSS classes
1190
1461
  - `onOpenChange`: (open: boolean) => void
1191
1462
  Callback when collapsed state changes
1192
1463
 
@@ -1194,35 +1465,115 @@ Collapsible component for showing/hiding content. Features: - Animated chevron
1194
1465
 
1195
1466
  `border-kumo-fill`, `text-kumo-link`
1196
1467
 
1468
+ **Sub-Components:**
1469
+
1470
+ This is a compound component. Use these sub-components:
1471
+
1472
+ #### Collapsible.Root
1473
+
1474
+ Root sub-component
1475
+
1476
+ Props:
1477
+ - `className`: string
1478
+
1479
+ #### Collapsible.Trigger
1480
+
1481
+ Trigger sub-component
1482
+
1483
+ Props:
1484
+ - `className`: string
1485
+
1486
+ #### Collapsible.Panel
1487
+
1488
+ Panel sub-component
1489
+
1490
+ Props:
1491
+ - `className`: string
1492
+
1493
+ #### Collapsible.DefaultTrigger
1494
+
1495
+ DefaultTrigger sub-component
1496
+
1497
+ Props:
1498
+ - `children`: ReactNode (required)
1499
+ - `className`: string
1500
+
1501
+ #### Collapsible.DefaultPanel
1502
+
1503
+ DefaultPanel sub-component
1504
+
1505
+ Props:
1506
+ - `children`: ReactNode (required)
1507
+ - `className`: string
1508
+
1509
+
1197
1510
  **Examples:**
1198
1511
 
1199
1512
  ```tsx
1200
1513
  <div className="w-full">
1201
- <Collapsible label="What is Kumo?" open={isOpen} onOpenChange={setIsOpen}>
1202
- Kumo is Cloudflare's new design system.
1203
- </Collapsible>
1514
+ <Collapsible.Root open={isOpen} onOpenChange={setIsOpen}>
1515
+ <Collapsible.DefaultTrigger>What is Kumo?</Collapsible.DefaultTrigger>
1516
+ <Collapsible.DefaultPanel>
1517
+ <Text>Kumo is Cloudflare's new design system.</Text>
1518
+ </Collapsible.DefaultPanel>
1519
+ </Collapsible.Root>
1204
1520
  </div>
1205
1521
  ```
1206
1522
 
1207
1523
  ```tsx
1208
1524
  <div className="w-full space-y-2">
1209
- <Collapsible label="What is Kumo?" open={open1} onOpenChange={setOpen1}>
1210
- Kumo is Cloudflare's new design system.
1211
- </Collapsible>
1212
- <Collapsible
1213
- label="How do I use it?"
1214
- open={open2}
1215
- onOpenChange={setOpen2}
1216
- >
1217
- Install the components and import them into your project.
1218
- </Collapsible>
1219
- <Collapsible
1220
- label="Is it open source?"
1221
- open={open3}
1222
- onOpenChange={setOpen3}
1223
- >
1224
- Check the repository for license information.
1225
- </Collapsible>
1525
+ <Collapsible.Root open={open1} onOpenChange={setOpen1}>
1526
+ <Collapsible.DefaultTrigger>What is Kumo?</Collapsible.DefaultTrigger>
1527
+ <Collapsible.DefaultPanel>
1528
+ <Text>Kumo is Cloudflare's new design system.</Text>
1529
+ </Collapsible.DefaultPanel>
1530
+ </Collapsible.Root>
1531
+ <Collapsible.Root open={open2} onOpenChange={setOpen2}>
1532
+ <Collapsible.DefaultTrigger>How do I use it?</Collapsible.DefaultTrigger>
1533
+ <Collapsible.DefaultPanel>
1534
+ <Text>Install the components and import them into your project.</Text>
1535
+ </Collapsible.DefaultPanel>
1536
+ </Collapsible.Root>
1537
+ <Collapsible.Root open={open3} onOpenChange={setOpen3}>
1538
+ <Collapsible.DefaultTrigger>Is it open source?</Collapsible.DefaultTrigger>
1539
+ <Collapsible.DefaultPanel>
1540
+ <Text>Check the repository for license information.</Text>
1541
+ </Collapsible.DefaultPanel>
1542
+ </Collapsible.Root>
1543
+ </div>
1544
+ ```
1545
+
1546
+ ```tsx
1547
+ <div className="w-full">
1548
+ <Collapsible.Root open={isOpen} onOpenChange={setIsOpen}>
1549
+ <Collapsible.Trigger
1550
+ render={<Button variant="secondary" size="sm" />}
1551
+ >
1552
+ {isOpen ? "Hide details" : "Show details"}
1553
+ </Collapsible.Trigger>
1554
+ <Collapsible.Panel className="mt-3 rounded-lg bg-kumo-tint p-4">
1555
+ <Text>
1556
+ This panel uses custom styling instead of the default border-left accent.
1557
+ </Text>
1558
+ </Collapsible.Panel>
1559
+ </Collapsible.Root>
1560
+ </div>
1561
+ ```
1562
+
1563
+ ```tsx
1564
+ <div className="w-full space-y-2">
1565
+ {items.map((item, i) => (
1566
+ <Collapsible.Root
1567
+ key={i}
1568
+ open={activeIndex === i}
1569
+ onOpenChange={(open) => setActiveIndex(open ? i : null)}
1570
+ >
1571
+ <Collapsible.DefaultTrigger>{item.title}</Collapsible.DefaultTrigger>
1572
+ <Collapsible.DefaultPanel>
1573
+ <Text>{item.content}</Text>
1574
+ </Collapsible.DefaultPanel>
1575
+ </Collapsible.Root>
1576
+ ))}
1226
1577
  </div>
1227
1578
  ```
1228
1579
 
@@ -1277,7 +1628,7 @@ Combobox — autocomplete input with filterable dropdown list. Compound compone
1277
1628
 
1278
1629
  **Colors (kumo tokens used):**
1279
1630
 
1280
- `bg-kumo-base`, `bg-kumo-fill-hover`, `bg-kumo-overlay`, `bg-kumo-tint`, `border-kumo-line`, `ring-kumo-line`, `text-kumo-default`, `text-kumo-strong`, `text-kumo-subtle`
1631
+ `bg-kumo-base`, `bg-kumo-fill-hover`, `bg-kumo-overlay`, `bg-kumo-tint`, `border-kumo-hairline`, `ring-kumo-hairline`, `ring-kumo-line`, `text-kumo-default`, `text-kumo-strong`, `text-kumo-subtle`
1281
1632
 
1282
1633
  **Sub-Components:**
1283
1634
 
@@ -1524,6 +1875,36 @@ Usage:
1524
1875
  </div>
1525
1876
  ```
1526
1877
 
1878
+ ```tsx
1879
+ <div className="w-80">
1880
+ <Combobox value={value} onValueChange={setValue} items={items}>
1881
+ <Combobox.TriggerInput placeholder="Select database" />
1882
+ <Combobox.Content>
1883
+ <Combobox.Empty />
1884
+ <Combobox.List>
1885
+ {(item: DatabaseItemWithDisabled) => (
1886
+ <Combobox.Item
1887
+ key={item.value}
1888
+ value={item}
1889
+ disabled={item.disabled}
1890
+ >
1891
+ <span>
1892
+ {item.label}
1893
+ {item.reason && (
1894
+ <Text variant="secondary" size="xs" as="span">
1895
+ {" — "}
1896
+ {item.reason}
1897
+ </Text>
1898
+ )}
1899
+ </span>
1900
+ </Combobox.Item>
1901
+ )}
1902
+ </Combobox.List>
1903
+ </Combobox.Content>
1904
+ </Combobox>
1905
+ </div>
1906
+ ```
1907
+
1527
1908
  ```tsx
1528
1909
  <div className="w-80">
1529
1910
  <Combobox
@@ -1656,7 +2037,7 @@ CommandPalette — accessible command palette / spotlight search overlay. Compo
1656
2037
 
1657
2038
  **Colors (kumo tokens used):**
1658
2039
 
1659
- `bg-kumo-base`, `bg-kumo-elevated`, `bg-kumo-overlay`, `bg-kumo-warning`, `ring-kumo-line`, `text-kumo-default`, `text-kumo-strong`, `text-kumo-subtle`
2040
+ `bg-kumo-base`, `bg-kumo-elevated`, `bg-kumo-overlay`, `bg-kumo-warning`, `ring-kumo-brand`, `ring-kumo-hairline`, `text-kumo-default`, `text-kumo-strong`, `text-kumo-subtle`
1660
2041
 
1661
2042
  **Examples:**
1662
2043
 
@@ -1714,13 +2095,13 @@ CommandPalette — accessible command palette / spotlight search overlay. Compo
1714
2095
  </CommandPalette.List>
1715
2096
  <CommandPalette.Footer>
1716
2097
  <span className="flex items-center gap-2">
1717
- <kbd className="rounded border border-kumo-line bg-kumo-base px-1.5 py-0.5 text-[10px]">
2098
+ <kbd className="rounded border border-kumo-hairline bg-kumo-base px-1.5 py-0.5 text-[10px]">
1718
2099
  ↑↓
1719
2100
  </kbd>
1720
2101
  <span>Navigate</span>
1721
2102
  </span>
1722
2103
  <span className="flex items-center gap-2">
1723
- <kbd className="rounded border border-kumo-line bg-kumo-base px-1.5 py-0.5 text-[10px]">
2104
+ <kbd className="rounded border border-kumo-hairline bg-kumo-base px-1.5 py-0.5 text-[10px]">
1724
2105
 
1725
2106
  </kbd>
1726
2107
  <span>Select</span>
@@ -1824,52 +2205,116 @@ CommandPalette — accessible command palette / spotlight search overlay. Compo
1824
2205
  ```
1825
2206
 
1826
2207
  ```tsx
1827
- <div>
1828
- <Button onClick={() => setOpen(true)}>Open with ResultItem</Button>
2208
+ <div className="flex flex-col items-start gap-4">
2209
+ <Button onClick={() => setOpen(true)}>
2210
+ Open Palette (No Autocomplete)
2211
+ </Button>
1829
2212
 
1830
2213
  <CommandPalette.Root
1831
2214
  open={open}
1832
2215
  onOpenChange={setOpen}
1833
- items={searchResults}
2216
+ items={filteredGroups}
1834
2217
  value={search}
1835
2218
  onValueChange={setSearch}
1836
- itemToStringValue={(item) => item.title}
1837
- getSelectableItems={(items) => items}
2219
+ itemToStringValue={(group) => group.label}
2220
+ onSelect={(item) => {
2221
+ console.log("Selected:", item.title);
2222
+ setOpen(false);
2223
+ setSearch("");
2224
+ }}
2225
+ getSelectableItems={getSelectableItems}
1838
2226
  >
1839
- <CommandPalette.Input placeholder="Search documentation..." />
2227
+ <CommandPalette.Input
2228
+ placeholder="Search commands..."
2229
+ autoComplete="off"
2230
+ autoCorrect="off"
2231
+ autoCapitalize="none"
2232
+ spellCheck={false}
2233
+ data-1p-ignore="true"
2234
+ data-lpignore="true"
2235
+ />
1840
2236
  <CommandPalette.List>
1841
2237
  <CommandPalette.Results>
1842
- {(item: SearchResult) => (
1843
- <CommandPalette.ResultItem
1844
- key={item.id}
1845
- value={item}
1846
- title={item.title}
1847
- breadcrumbs={item.breadcrumbs}
1848
- icon={item.icon}
1849
- onClick={() => {
1850
- console.log("Navigate to:", item.title);
1851
- setOpen(false);
1852
- }}
1853
- />
1854
- )}
1855
- </CommandPalette.Results>
1856
- <CommandPalette.Empty>No pages found</CommandPalette.Empty>
1857
- </CommandPalette.List>
1858
- <CommandPalette.Footer>
1859
- <span className="flex items-center gap-2">
1860
- <kbd className="rounded border border-kumo-line bg-kumo-base px-1.5 py-0.5 text-[10px]">
1861
- ↑↓
1862
- </kbd>
1863
- <span>Navigate</span>
1864
- </span>
1865
- <span className="flex items-center gap-2">
1866
- <kbd className="rounded border border-kumo-line bg-kumo-base px-1.5 py-0.5 text-[10px]">
1867
- ⌘↵
1868
- </kbd>
1869
- <span>Open in new tab</span>
1870
- </span>
1871
- </CommandPalette.Footer>
1872
- </CommandPalette.Root>
2238
+ {(group: CommandGroup) => (
2239
+ <CommandPalette.Group key={group.id} items={group.items}>
2240
+ <CommandPalette.GroupLabel>
2241
+ {group.label}
2242
+ </CommandPalette.GroupLabel>
2243
+ <CommandPalette.Items>
2244
+ {(item: CommandItem) => (
2245
+ <CommandPalette.Item
2246
+ key={item.id}
2247
+ value={item}
2248
+ onClick={() => {
2249
+ setOpen(false);
2250
+ setSearch("");
2251
+ }}
2252
+ >
2253
+ <span className="flex items-center gap-3">
2254
+ {item.icon && (
2255
+ <span className="text-kumo-subtle">{item.icon}</span>
2256
+ )}
2257
+ <span>{item.title}</span>
2258
+ </span>
2259
+ </CommandPalette.Item>
2260
+ )}
2261
+ </CommandPalette.Items>
2262
+ </CommandPalette.Group>
2263
+ )}
2264
+ </CommandPalette.Results>
2265
+ <CommandPalette.Empty>No commands found</CommandPalette.Empty>
2266
+ </CommandPalette.List>
2267
+ </CommandPalette.Root>
2268
+ </div>
2269
+ ```
2270
+
2271
+ ```tsx
2272
+ <div>
2273
+ <Button onClick={() => setOpen(true)}>Open with ResultItem</Button>
2274
+
2275
+ <CommandPalette.Root
2276
+ open={open}
2277
+ onOpenChange={setOpen}
2278
+ items={searchResults}
2279
+ value={search}
2280
+ onValueChange={setSearch}
2281
+ itemToStringValue={(item) => item.title}
2282
+ getSelectableItems={(items) => items}
2283
+ >
2284
+ <CommandPalette.Input placeholder="Search documentation..." />
2285
+ <CommandPalette.List>
2286
+ <CommandPalette.Results>
2287
+ {(item: SearchResult) => (
2288
+ <CommandPalette.ResultItem
2289
+ key={item.id}
2290
+ value={item}
2291
+ title={item.title}
2292
+ breadcrumbs={item.breadcrumbs}
2293
+ icon={item.icon}
2294
+ onClick={() => {
2295
+ console.log("Navigate to:", item.title);
2296
+ setOpen(false);
2297
+ }}
2298
+ />
2299
+ )}
2300
+ </CommandPalette.Results>
2301
+ <CommandPalette.Empty>No pages found</CommandPalette.Empty>
2302
+ </CommandPalette.List>
2303
+ <CommandPalette.Footer>
2304
+ <span className="flex items-center gap-2">
2305
+ <kbd className="rounded border border-kumo-hairline bg-kumo-base px-1.5 py-0.5 text-[10px]">
2306
+ ↑↓
2307
+ </kbd>
2308
+ <span>Navigate</span>
2309
+ </span>
2310
+ <span className="flex items-center gap-2">
2311
+ <kbd className="rounded border border-kumo-hairline bg-kumo-base px-1.5 py-0.5 text-[10px]">
2312
+ ⌘↵
2313
+ </kbd>
2314
+ <span>Open in new tab</span>
2315
+ </span>
2316
+ </CommandPalette.Footer>
2317
+ </CommandPalette.Root>
1873
2318
  </div>
1874
2319
  ```
1875
2320
 
@@ -1901,11 +2346,15 @@ DatePicker — a date selection calendar. Built on [react-day-picker](https://d
1901
2346
 
1902
2347
  ```tsx
1903
2348
  <div className="flex flex-col gap-4">
1904
- <DatePicker mode="single" selected={date} onChange={d => {
1905
- if (d) {
1906
- setDate(d);
1907
- }
1908
- }} />
2349
+ <DatePicker
2350
+ mode="single"
2351
+ selected={date}
2352
+ onChange={(d) => {
2353
+ if (d) {
2354
+ setDate(d);
2355
+ }
2356
+ }}
2357
+ />
1909
2358
  <p className="text-sm text-kumo-subtle">
1910
2359
  Selected: {date ? date.toLocaleDateString() : "None"}
1911
2360
  </p>
@@ -1960,10 +2409,10 @@ DatePicker — a date selection calendar. Built on [react-day-picker](https://d
1960
2409
 
1961
2410
  ```tsx
1962
2411
  <Popover>
1963
- <Popover.Trigger asChild>
1964
- <Button variant="outline" icon={CalendarDotsIcon}>
1965
- {date ? date.toLocaleDateString() : "Pick a date"}
1966
- </Button>
2412
+ <Popover.Trigger
2413
+ render={<Button variant="outline" icon={CalendarDotsIcon} />}
2414
+ >
2415
+ {date ? date.toLocaleDateString() : "Pick a date"}
1967
2416
  </Popover.Trigger>
1968
2417
  <Popover.Content className="p-3">
1969
2418
  <DatePicker mode="single" selected={date} onChange={setDate} />
@@ -1973,10 +2422,10 @@ DatePicker — a date selection calendar. Built on [react-day-picker](https://d
1973
2422
 
1974
2423
  ```tsx
1975
2424
  <Popover>
1976
- <Popover.Trigger asChild>
1977
- <Button variant="outline" icon={CalendarDotsIcon}>
1978
- {formatRange()}
1979
- </Button>
2425
+ <Popover.Trigger
2426
+ render={<Button variant="outline" icon={CalendarDotsIcon} />}
2427
+ >
2428
+ {formatRange()}
1980
2429
  </Popover.Trigger>
1981
2430
  <Popover.Content className="p-3">
1982
2431
  <DatePicker
@@ -1991,14 +2440,14 @@ DatePicker — a date selection calendar. Built on [react-day-picker](https://d
1991
2440
 
1992
2441
  ```tsx
1993
2442
  <Popover>
1994
- <Popover.Trigger asChild>
1995
- <Button variant="outline" icon={CalendarDotsIcon}>
1996
- {formatRange()}
1997
- </Button>
2443
+ <Popover.Trigger
2444
+ render={<Button variant="outline" icon={CalendarDotsIcon} />}
2445
+ >
2446
+ {formatRange()}
1998
2447
  </Popover.Trigger>
1999
2448
  <Popover.Content className="p-0">
2000
2449
  <div className="flex">
2001
- <div className="flex flex-col gap-1 border-r border-kumo-line p-2 text-sm">
2450
+ <div className="flex flex-col gap-1 border-r border-kumo-hairline p-2 text-sm">
2002
2451
  {presets.map((preset) => {
2003
2452
  const isActive = isPresetActive(preset);
2004
2453
  return (
@@ -2006,10 +2455,11 @@ DatePicker — a date selection calendar. Built on [react-day-picker](https://d
2006
2455
  key={preset.label}
2007
2456
  type="button"
2008
2457
  onClick={() => handlePresetClick(preset)}
2009
- className={`rounded-md px-3 py-1.5 text-left whitespace-nowrap ${isActive
2010
- ? "bg-kumo-bg-inverse text-kumo-text-inverse"
2011
- : "text-kumo-strong hover:bg-kumo-control"
2012
- }`}
2458
+ className={`rounded-md px-3 py-1.5 text-left whitespace-nowrap ${
2459
+ isActive
2460
+ ? "bg-kumo-bg-inverse text-kumo-text-inverse"
2461
+ : "text-kumo-strong hover:bg-kumo-control"
2462
+ }`}
2013
2463
  >
2014
2464
  {preset.label}
2015
2465
  </button>
@@ -2080,7 +2530,7 @@ DateRangePicker — dual-calendar date range selector. Renders two side-by-side
2080
2530
 
2081
2531
  **Colors (kumo tokens used):**
2082
2532
 
2083
- `bg-kumo-base`, `bg-kumo-contrast`, `bg-kumo-fill`, `bg-kumo-interact`, `bg-kumo-overlay`, `text-kumo-default`, `text-kumo-inverse`, `text-kumo-strong`, `text-kumo-subtle`
2533
+ `bg-kumo-base`, `bg-kumo-contrast`, `bg-kumo-fill`, `bg-kumo-interact`, `bg-kumo-overlay`, `ring-kumo-focus`, `text-kumo-default`, `text-kumo-inverse`, `text-kumo-strong`, `text-kumo-subtle`
2084
2534
 
2085
2535
  **Styling:**
2086
2536
 
@@ -2144,7 +2594,7 @@ Dialog component
2144
2594
 
2145
2595
  **Colors (kumo tokens used):**
2146
2596
 
2147
- `bg-kumo-base`, `bg-kumo-recessed`, `text-kumo-default`
2597
+ `bg-kumo-base`, `bg-kumo-recessed`, `ring-kumo-line`, `text-kumo-default`
2148
2598
 
2149
2599
  **Styling:**
2150
2600
 
@@ -2460,7 +2910,7 @@ DropdownMenu — accessible dropdown menu anchored to a trigger. Compound compo
2460
2910
 
2461
2911
  **Colors (kumo tokens used):**
2462
2912
 
2463
- `bg-kumo-control`, `bg-kumo-danger`, `bg-kumo-line`, `bg-kumo-overlay`, `bg-kumo-tint`, `ring-kumo-line`, `text-kumo-danger`, `text-kumo-default`
2913
+ `bg-kumo-control`, `bg-kumo-danger`, `bg-kumo-hairline`, `bg-kumo-overlay`, `bg-kumo-tint`, `ring-kumo-brand`, `ring-kumo-focus`, `ring-kumo-line`, `text-kumo-danger`, `text-kumo-default`
2464
2914
 
2465
2915
  **Sub-Components:**
2466
2916
 
@@ -2726,7 +3176,7 @@ Responsive CSS grid layout container with preset column configurations.
2726
3176
 
2727
3177
  **Colors (kumo tokens used):**
2728
3178
 
2729
- `border-kumo-line`
3179
+ `border-kumo-hairline`
2730
3180
 
2731
3181
  **Examples:**
2732
3182
 
@@ -3007,13 +3457,13 @@ Input component
3007
3457
 
3008
3458
  **State Classes:**
3009
3459
  - `"default"`:
3010
- - `focus`: `focus:ring-kumo-hairline`
3460
+ - `focus`: `focus:ring-kumo-focus/50 focus:ring-[1.5px]`
3011
3461
  - `"error"`:
3012
- - `focus`: `focus:ring-kumo-danger`
3462
+ - `focus`: `focus:ring-kumo-danger/50 focus:ring-[1.5px]`
3013
3463
 
3014
3464
  **Colors (kumo tokens used):**
3015
3465
 
3016
- `bg-kumo-control`, `ring-kumo-danger`, `ring-kumo-hairline`, `ring-kumo-line`, `text-kumo-default`, `text-kumo-subtle`
3466
+ `bg-kumo-control`, `ring-kumo-danger`, `ring-kumo-focus`, `ring-kumo-line`, `text-kumo-default`, `text-kumo-subtle`
3017
3467
 
3018
3468
  **Styling:**
3019
3469
 
@@ -3102,6 +3552,386 @@ Input component
3102
3552
  />
3103
3553
  ```
3104
3554
 
3555
+ ```tsx
3556
+ <Input
3557
+ label="With onChange"
3558
+ placeholder="Type something..."
3559
+ description={value ? `Value: ${value}` : "Uses e.target.value"}
3560
+ value={value}
3561
+ onChange={(e) => setValue(e.target.value)}
3562
+ />
3563
+ ```
3564
+
3565
+ ```tsx
3566
+ <Input
3567
+ label="With onValueChange"
3568
+ placeholder="Type something..."
3569
+ description={value ? `Value: ${value}` : "Receives the value directly"}
3570
+ value={value}
3571
+ onValueChange={(v) => setValue(v)}
3572
+ />
3573
+ ```
3574
+
3575
+
3576
+ ---
3577
+
3578
+ ### InputGroup
3579
+
3580
+ InputGroup component
3581
+
3582
+ **Type:** component
3583
+
3584
+ **Import:** `import { InputGroup } from "@cloudflare/kumo";`
3585
+
3586
+ **Category:** Input
3587
+
3588
+ **Props:**
3589
+
3590
+ - `label`: ReactNode
3591
+ The label content — can be a string or any React node.
3592
+ - `description`: ReactNode
3593
+ Helper text displayed below the control (hidden when `error` is present).
3594
+ - `error`: object
3595
+ Validation error with a message and a browser `ValidityState` match key.
3596
+ - `required`: boolean
3597
+ When explicitly `false`, shows gray "(optional)" text after the label. When `true` or `undefined`, no indicator is shown.
3598
+ - `labelTooltip`: ReactNode
3599
+ Tooltip content displayed next to the label via an info icon.
3600
+ - `children`: ReactNode
3601
+ - `className`: string
3602
+ - `id`: string
3603
+ - `lang`: string
3604
+ - `title`: string
3605
+ - `size`: enum [default: base]
3606
+ - `"xs"`: Extra small size.
3607
+ - `"sm"`: Small size.
3608
+ - `"base"`: Default size.
3609
+ - `"lg"`: Large size.
3610
+ - `disabled`: boolean
3611
+
3612
+ **Colors (kumo tokens used):**
3613
+
3614
+ `border-kumo-line`, `ring-kumo-danger`, `ring-kumo-focus`, `ring-kumo-line`
3615
+
3616
+ **Sub-Components:**
3617
+
3618
+ This is a compound component. Use these sub-components:
3619
+
3620
+ #### InputGroup.Input
3621
+
3622
+ Input sub-component
3623
+
3624
+ #### InputGroup.Button
3625
+
3626
+ Button sub-component
3627
+
3628
+ Props:
3629
+ - `tooltip`: ReactNode - When provided, wraps the button in a Tooltip. Automatically sets aria-label from a string value.
3630
+ - `tooltipSide`: "top" | "right" | "bottom" | "left" [default: "bottom"] - Preferred side for the tooltip popup.
3631
+ - `variant`: "primary" | "secondary" | "ghost" | "destructive" | "secondary-destructive" | "outline" [default: "ghost"] - Button visual style. Defaults to ghost.
3632
+ - `size`: "xs" | "sm" | "base" | "lg" [default: "sm"] - Button size.
3633
+
3634
+ #### InputGroup.Addon
3635
+
3636
+ Addon sub-component
3637
+
3638
+ Props:
3639
+ - `align`: "start" | "end" [default: "start"] - Position relative to the input.
3640
+ - `className`: string - Additional CSS classes.
3641
+
3642
+ #### InputGroup.Suffix
3643
+
3644
+ Suffix sub-component
3645
+
3646
+ Props:
3647
+ - `className`: string - Additional CSS classes.
3648
+
3649
+ #### InputGroup.Label
3650
+
3651
+ Label sub-component
3652
+
3653
+ #### InputGroup.Description
3654
+
3655
+ Description sub-component
3656
+
3657
+
3658
+ **Examples:**
3659
+
3660
+ ```tsx
3661
+ <div className="w-full max-w-2xs">
3662
+ <InputGroup>
3663
+ <InputGroup.Input
3664
+ maxLength={20}
3665
+ onChange={handleChange}
3666
+ value={value}
3667
+ />
3668
+ <InputGroup.Suffix>.workers.dev</InputGroup.Suffix>
3669
+ {status !== "idle" && (
3670
+ <InputGroup.Addon align="end">
3671
+ {status === "loading" ? (
3672
+ <Loader />
3673
+ ) : (
3674
+ <CheckCircleIcon weight="duotone" className="text-kumo-success" />
3675
+ )}
3676
+ </InputGroup.Addon>
3677
+ )}
3678
+ </InputGroup>
3679
+ </div>
3680
+ ```
3681
+
3682
+ ```tsx
3683
+ <InputGroup className="w-full max-w-3xs">
3684
+ <InputGroup.Addon>
3685
+ <LinkIcon />
3686
+ </InputGroup.Addon>
3687
+ <InputGroup.Input placeholder="Paste a link..." aria-label="Link" />
3688
+ </InputGroup>
3689
+ ```
3690
+
3691
+ ```tsx
3692
+ <div className="flex flex-col gap-4">
3693
+ <InputGroup className="w-full max-w-3xs">
3694
+ <InputGroup.Addon>@</InputGroup.Addon>
3695
+ <InputGroup.Input placeholder="username" aria-label="Username" />
3696
+ </InputGroup>
3697
+
3698
+ <InputGroup className="w-full max-w-3xs">
3699
+ <InputGroup.Input placeholder="email" aria-label="Email" />
3700
+ <InputGroup.Addon align="end">@example.com</InputGroup.Addon>
3701
+ </InputGroup>
3702
+
3703
+ <InputGroup className="w-full max-w-3xs">
3704
+ <InputGroup.Addon>/api/</InputGroup.Addon>
3705
+ <InputGroup.Input placeholder="endpoint" aria-label="API path" />
3706
+ <InputGroup.Addon align="end">.json</InputGroup.Addon>
3707
+ </InputGroup>
3708
+ </div>
3709
+ ```
3710
+
3711
+ ```tsx
3712
+ <div className="flex flex-col gap-4">
3713
+ <InputGroup className="w-full max-w-3xs">
3714
+ <InputGroup.Input
3715
+ type={show ? "text" : "password"}
3716
+ defaultValue="password"
3717
+ aria-label="Password"
3718
+ />
3719
+ <InputGroup.Addon align="end">
3720
+ <InputGroup.Button
3721
+ className="text-kumo-subtle"
3722
+ icon={show ? EyeSlashIcon : EyeIcon}
3723
+ aria-label={show ? "Hide password" : "Show password"}
3724
+ onClick={() => setShow(!show)}
3725
+ />
3726
+ </InputGroup.Addon>
3727
+ </InputGroup>
3728
+
3729
+ <InputGroup className="w-full max-w-3xs">
3730
+ <InputGroup.Addon>
3731
+ <MagnifyingGlassIcon />
3732
+ </InputGroup.Addon>
3733
+ <InputGroup.Input
3734
+ value={searchValue}
3735
+ placeholder="Search"
3736
+ aria-label="Search"
3737
+ onChange={(e) => setSearchValue(e.target.value)}
3738
+ />
3739
+ {searchValue && (
3740
+ <InputGroup.Addon align="end" className="pr-1">
3741
+ <InputGroup.Button
3742
+ aria-label="Clear search"
3743
+ onClick={() => setSearchValue("")}
3744
+ >
3745
+ <XIcon />
3746
+ </InputGroup.Button>
3747
+ </InputGroup.Addon>
3748
+ )}
3749
+ <InputGroup.Button variant="secondary" onClick={() => {}}>
3750
+ Search
3751
+ </InputGroup.Button>
3752
+ </InputGroup>
3753
+ </div>
3754
+ ```
3755
+
3756
+ ```tsx
3757
+ <InputGroup className="w-full max-w-2xs">
3758
+ <InputGroup.Addon>
3759
+ <MagnifyingGlassIcon />
3760
+ </InputGroup.Addon>
3761
+ <InputGroup.Input
3762
+ placeholder="Search with query language..."
3763
+ aria-label="Search"
3764
+ />
3765
+ <InputGroup.Addon align="end">
3766
+ <InputGroup.Button
3767
+ className="text-kumo-subtle"
3768
+ icon={QuestionIcon}
3769
+ tooltip="Query language help"
3770
+ onClick={() => {}}
3771
+ />
3772
+ </InputGroup.Addon>
3773
+ </InputGroup>
3774
+ ```
3775
+
3776
+ ```tsx
3777
+ <InputGroup className="w-full max-w-3xs">
3778
+ <InputGroup.Addon>
3779
+ <MagnifyingGlassIcon />
3780
+ </InputGroup.Addon>
3781
+ <InputGroup.Input placeholder="Search..." aria-label="Search" />
3782
+ <InputGroup.Addon align="end">
3783
+ <kbd className="bg-none! border-none!">⌘K</kbd>
3784
+ </InputGroup.Addon>
3785
+ </InputGroup>
3786
+ ```
3787
+
3788
+ ```tsx
3789
+ <InputGroup className="w-full max-w-3xs">
3790
+ <InputGroup.Input defaultValue="kumo" aria-label="kumo" />
3791
+ <InputGroup.Addon align="end">
3792
+ <Loader />
3793
+ </InputGroup.Addon>
3794
+ </InputGroup>
3795
+ ```
3796
+
3797
+ ```tsx
3798
+ <div className="flex w-full max-w-2xs flex-col gap-4">
3799
+ <InputGroup label="Subdomain">
3800
+ <InputGroup.Input
3801
+ aria-label="Subdomain"
3802
+ defaultValue="kumo"
3803
+ maxLength={20}
3804
+ />
3805
+ <InputGroup.Suffix>.workers.dev</InputGroup.Suffix>
3806
+ <InputGroup.Addon align="end">
3807
+ <CheckCircleIcon weight="duotone" className="text-kumo-success" />
3808
+ </InputGroup.Addon>
3809
+ </InputGroup>
3810
+
3811
+ <InputGroup
3812
+ label="Subdomain"
3813
+ error={{ message: "This subdomain is unavailable", match: true }}
3814
+ >
3815
+ <InputGroup.Input
3816
+ aria-label="Subdomain"
3817
+ defaultValue="kumo"
3818
+ maxLength={20}
3819
+ />
3820
+ <InputGroup.Suffix>.workers.dev</InputGroup.Suffix>
3821
+ <InputGroup.Addon align="end">
3822
+ <XCircleIcon weight="duotone" className="text-kumo-danger" />
3823
+ </InputGroup.Addon>
3824
+ </InputGroup>
3825
+ </div>
3826
+ ```
3827
+
3828
+ ```tsx
3829
+ <div className="flex w-full max-w-3xs flex-col gap-4">
3830
+ <InputGroup size="xs" label="Extra Small">
3831
+ <InputGroup.Addon>
3832
+ <MagnifyingGlassIcon />
3833
+ </InputGroup.Addon>
3834
+ <InputGroup.Input placeholder="Extra small input" />
3835
+ <InputGroup.Addon align="end">
3836
+ <InputGroup.Button
3837
+ className="text-kumo-subtle"
3838
+ icon={QuestionIcon}
3839
+ shape="square"
3840
+ aria-label="Help"
3841
+ />
3842
+ </InputGroup.Addon>
3843
+ </InputGroup>
3844
+
3845
+ <InputGroup size="sm" label="Small">
3846
+ <InputGroup.Addon>
3847
+ <MagnifyingGlassIcon />
3848
+ </InputGroup.Addon>
3849
+ <InputGroup.Input placeholder="Small input" />
3850
+ <InputGroup.Addon align="end">
3851
+ <InputGroup.Button
3852
+ className="text-kumo-subtle"
3853
+ icon={QuestionIcon}
3854
+ shape="square"
3855
+ aria-label="Help"
3856
+ />
3857
+ </InputGroup.Addon>
3858
+ </InputGroup>
3859
+
3860
+ <InputGroup label="Base (default)">
3861
+ <InputGroup.Addon>
3862
+ <MagnifyingGlassIcon />
3863
+ </InputGroup.Addon>
3864
+ <InputGroup.Input placeholder="Base input" />
3865
+ <InputGroup.Addon align="end">
3866
+ <InputGroup.Button
3867
+ className="text-kumo-subtle"
3868
+ icon={QuestionIcon}
3869
+ shape="square"
3870
+ aria-label="Help"
3871
+ />
3872
+ </InputGroup.Addon>
3873
+ </InputGroup>
3874
+
3875
+ <InputGroup size="lg" label="Large">
3876
+ <InputGroup.Addon>
3877
+ <MagnifyingGlassIcon />
3878
+ </InputGroup.Addon>
3879
+ <InputGroup.Input placeholder="Large input" />
3880
+ <InputGroup.Addon align="end">
3881
+ <InputGroup.Button
3882
+ className="text-kumo-subtle"
3883
+ icon={QuestionIcon}
3884
+ shape="square"
3885
+ aria-label="Help"
3886
+ />
3887
+ </InputGroup.Addon>
3888
+ </InputGroup>
3889
+ </div>
3890
+ ```
3891
+
3892
+ ```tsx
3893
+ <div className="flex w-full max-w-3xs flex-col gap-4">
3894
+ <InputGroup
3895
+ label="Error State"
3896
+ error={{ message: "Please enter a valid email address", match: true }}
3897
+ >
3898
+ <InputGroup.Input type="email" defaultValue="invalid-email" />
3899
+ <InputGroup.Addon align="end">@example.com</InputGroup.Addon>
3900
+ </InputGroup>
3901
+
3902
+ <InputGroup label="Disabled" disabled>
3903
+ <InputGroup.Addon>
3904
+ <MagnifyingGlassIcon />
3905
+ </InputGroup.Addon>
3906
+ <InputGroup.Input placeholder="Search..." />
3907
+ </InputGroup>
3908
+
3909
+ <InputGroup label="Optional Field" required={false}>
3910
+ <InputGroup.Addon>$</InputGroup.Addon>
3911
+ <InputGroup.Input placeholder="0.00" />
3912
+ </InputGroup>
3913
+
3914
+ <InputGroup
3915
+ label="With Description"
3916
+ description="Must be at least 8 characters"
3917
+ labelTooltip="Your password is stored securely"
3918
+ >
3919
+ <InputGroup.Input
3920
+ type={show ? "text" : "password"}
3921
+ placeholder="Password"
3922
+ />
3923
+ <InputGroup.Addon align="end">
3924
+ <InputGroup.Button
3925
+ className="text-kumo-subtle"
3926
+ icon={show ? EyeSlashIcon : EyeIcon}
3927
+ aria-label={show ? "Hide password" : "Show password"}
3928
+ onClick={() => setShow(!show)}
3929
+ />
3930
+ </InputGroup.Addon>
3931
+ </InputGroup>
3932
+ </div>
3933
+ ```
3934
+
3105
3935
 
3106
3936
  ---
3107
3937
 
@@ -3201,13 +4031,19 @@ LayerCard component
3201
4031
 
3202
4032
  **Props:**
3203
4033
 
4034
+ - `render`: ReactNode
4035
+ Allows you to replace the component's HTML element with a different tag, or compose it with another component.
4036
+
4037
+ Accepts a `ReactElement` or a function that returns the element to render.
3204
4038
  - `children`: ReactNode
3205
4039
  - `className`: string
3206
- Additional CSS classes merged via `cn()`.
4040
+ - `id`: string
4041
+ - `lang`: string
4042
+ - `title`: string
3207
4043
 
3208
4044
  **Colors (kumo tokens used):**
3209
4045
 
3210
- `bg-kumo-base`, `bg-kumo-elevated`, `ring-kumo-fill`, `ring-kumo-line`, `text-kumo-strong`
4046
+ `bg-kumo-base`, `bg-kumo-elevated`, `ring-kumo-fill`, `ring-kumo-hairline`, `ring-kumo-line`, `text-kumo-strong`
3211
4047
 
3212
4048
  **Styling:**
3213
4049
 
@@ -3307,7 +4143,7 @@ Link component
3307
4143
  - `type`: string
3308
4144
  - `referrerPolicy`: enum
3309
4145
  - `render`: ReactNode
3310
- Allows you to replace the components HTML element with a different tag, or compose it with another component.
4146
+ Allows you to replace the component's HTML element with a different tag, or compose it with another component.
3311
4147
 
3312
4148
  Accepts a `ReactElement` or a function that returns the element to render.
3313
4149
 
@@ -3453,7 +4289,7 @@ MenuBar — horizontal icon-button toolbar with keyboard arrow-key navigation.
3453
4289
 
3454
4290
  **Colors (kumo tokens used):**
3455
4291
 
3456
- `bg-kumo-base`, `bg-kumo-recessed`, `border-kumo-fill`, `border-kumo-recessed`
4292
+ `bg-kumo-base`, `bg-kumo-recessed`, `border-kumo-recessed`, `ring-kumo-brand`, `ring-kumo-focus`, `ring-kumo-line`
3457
4293
 
3458
4294
  **Styling:**
3459
4295
 
@@ -3564,6 +4400,12 @@ Pagination component
3564
4400
  Total number of items across all pages.
3565
4401
  - `className`: string
3566
4402
  Additional CSS classes for the container
4403
+ - `labels`: PaginationLabels
4404
+ Labels for internationalization of aria-labels. All labels have English defaults.
4405
+
4406
+ For visible text like "Showing X of Y", use render props on sub-components:
4407
+ - `Pagination.Info` children for the info text
4408
+ - `Pagination.PageSize` label prop for the "Per page:" text
3567
4409
  - `children`: ReactNode
3568
4410
  Compound component children for custom layouts. Use Pagination.Info, Pagination.PageSize, Pagination.Controls, and Pagination.Separator.
3569
4411
  - `controls`: enum [default: full]
@@ -3573,7 +4415,7 @@ Pagination component
3573
4415
 
3574
4416
  **Colors (kumo tokens used):**
3575
4417
 
3576
- `border-kumo-line`, `ring-kumo-line`, `text-kumo-strong`
4418
+ `border-kumo-hairline`, `ring-kumo-hairline`, `text-kumo-strong`
3577
4419
 
3578
4420
  **Styling:**
3579
4421
 
@@ -3600,6 +4442,7 @@ PageSize sub-component
3600
4442
  Props:
3601
4443
  - `value`: number (required)
3602
4444
  - `options`: number[]
4445
+ - `page`: " (required)
3603
4446
  - `label`: ReactNode
3604
4447
  - `className`: string
3605
4448
 
@@ -3731,6 +4574,34 @@ Props:
3731
4574
  </Pagination>
3732
4575
  ```
3733
4576
 
4577
+ ```tsx
4578
+ <Pagination
4579
+ page={page}
4580
+ setPage={setPage}
4581
+ perPage={10}
4582
+ totalCount={100}
4583
+ labels={{
4584
+ firstPage: "Première page",
4585
+ previousPage: "Page précédente",
4586
+ nextPage: "Page suivante",
4587
+ lastPage: "Dernière page",
4588
+ pageNumber: "Numéro de page",
4589
+ pageSize: "Taille de page",
4590
+ }}
4591
+ >
4592
+ <Pagination.Info>
4593
+ {({ pageShowingRange, totalCount }) => (
4594
+ <>
4595
+ Affichage de{" "}
4596
+ <span className="tabular-nums">{pageShowingRange}</span> sur{" "}
4597
+ <span className="tabular-nums">{totalCount}</span>
4598
+ </>
4599
+ )}
4600
+ </Pagination.Info>
4601
+ <Pagination.Controls />
4602
+ </Pagination>
4603
+ ```
4604
+
3734
4605
 
3735
4606
  ---
3736
4607
 
@@ -3785,9 +4656,11 @@ Close sub-component
3785
4656
 
3786
4657
  ```tsx
3787
4658
  <Popover>
3788
- <Popover.Trigger asChild>
3789
- <Button shape="square" icon={BellIcon} aria-label="Notifications" />
3790
- </Popover.Trigger>
4659
+ <Popover.Trigger
4660
+ render={
4661
+ <Button shape="square" icon={BellIcon} aria-label="Notifications" />
4662
+ }
4663
+ />
3791
4664
  <Popover.Content>
3792
4665
  <Popover.Title>Notifications</Popover.Title>
3793
4666
  <Popover.Description>
@@ -3799,9 +4672,7 @@ Close sub-component
3799
4672
 
3800
4673
  ```tsx
3801
4674
  <Popover>
3802
- <Popover.Trigger asChild>
3803
- <Button>Open Popover</Button>
3804
- </Popover.Trigger>
4675
+ <Popover.Trigger render={<Button />}>Open Popover</Popover.Trigger>
3805
4676
  <Popover.Content>
3806
4677
  <Popover.Title>Popover Title</Popover.Title>
3807
4678
  <Popover.Description>
@@ -3813,19 +4684,15 @@ Close sub-component
3813
4684
 
3814
4685
  ```tsx
3815
4686
  <Popover>
3816
- <Popover.Trigger asChild>
3817
- <Button>Open Settings</Button>
3818
- </Popover.Trigger>
4687
+ <Popover.Trigger render={<Button />}>Open Settings</Popover.Trigger>
3819
4688
  <Popover.Content>
3820
4689
  <Popover.Title>Settings</Popover.Title>
3821
4690
  <Popover.Description>
3822
4691
  Configure your preferences below.
3823
4692
  </Popover.Description>
3824
4693
  <div className="mt-3">
3825
- <Popover.Close asChild>
3826
- <Button variant="secondary" size="sm">
3827
- Close
3828
- </Button>
4694
+ <Popover.Close render={<Button variant="secondary" size="sm" />}>
4695
+ Close
3829
4696
  </Popover.Close>
3830
4697
  </div>
3831
4698
  </Popover.Content>
@@ -3835,8 +4702,8 @@ Close sub-component
3835
4702
  ```tsx
3836
4703
  <div className="flex flex-wrap gap-4">
3837
4704
  <Popover>
3838
- <Popover.Trigger asChild>
3839
- <Button variant="secondary">Bottom</Button>
4705
+ <Popover.Trigger render={<Button variant="secondary" />}>
4706
+ Bottom
3840
4707
  </Popover.Trigger>
3841
4708
  <Popover.Content side="bottom">
3842
4709
  <Popover.Title>Bottom</Popover.Title>
@@ -3847,8 +4714,8 @@ Close sub-component
3847
4714
  </Popover>
3848
4715
 
3849
4716
  <Popover>
3850
- <Popover.Trigger asChild>
3851
- <Button variant="secondary">Top</Button>
4717
+ <Popover.Trigger render={<Button variant="secondary" />}>
4718
+ Top
3852
4719
  </Popover.Trigger>
3853
4720
  <Popover.Content side="top">
3854
4721
  <Popover.Title>Top</Popover.Title>
@@ -3857,8 +4724,8 @@ Close sub-component
3857
4724
  </Popover>
3858
4725
 
3859
4726
  <Popover>
3860
- <Popover.Trigger asChild>
3861
- <Button variant="secondary">Left</Button>
4727
+ <Popover.Trigger render={<Button variant="secondary" />}>
4728
+ Left
3862
4729
  </Popover.Trigger>
3863
4730
  <Popover.Content side="left">
3864
4731
  <Popover.Title>Left</Popover.Title>
@@ -3867,8 +4734,8 @@ Close sub-component
3867
4734
  </Popover>
3868
4735
 
3869
4736
  <Popover>
3870
- <Popover.Trigger asChild>
3871
- <Button variant="secondary">Right</Button>
4737
+ <Popover.Trigger render={<Button variant="secondary" />}>
4738
+ Right
3872
4739
  </Popover.Trigger>
3873
4740
  <Popover.Content side="right">
3874
4741
  <Popover.Title>Right</Popover.Title>
@@ -3880,9 +4747,7 @@ Close sub-component
3880
4747
 
3881
4748
  ```tsx
3882
4749
  <Popover>
3883
- <Popover.Trigger asChild>
3884
- <Button>User Profile</Button>
3885
- </Popover.Trigger>
4750
+ <Popover.Trigger render={<Button />}>User Profile</Popover.Trigger>
3886
4751
  <Popover.Content className="w-64">
3887
4752
  <div className="flex items-center gap-3">
3888
4753
  <div className="size-10 rounded-full bg-kumo-recessed" />
@@ -3891,14 +4756,14 @@ Close sub-component
3891
4756
  <p className="text-sm text-kumo-subtle">jane@example.com</p>
3892
4757
  </div>
3893
4758
  </div>
3894
- <div className="mt-3 flex gap-2 border-t border-kumo-line pt-3">
4759
+ <div className="mt-3 flex gap-2 border-t border-kumo-hairline pt-3">
3895
4760
  <Button variant="secondary" size="sm" className="flex-1">
3896
4761
  Profile
3897
4762
  </Button>
3898
- <Popover.Close asChild>
3899
- <Button variant="ghost" size="sm" className="flex-1">
3900
- Sign Out
3901
- </Button>
4763
+ <Popover.Close
4764
+ render={<Button variant="ghost" size="sm" className="flex-1" />}
4765
+ >
4766
+ Sign Out
3902
4767
  </Popover.Close>
3903
4768
  </div>
3904
4769
  </Popover.Content>
@@ -3907,8 +4772,12 @@ Close sub-component
3907
4772
 
3908
4773
  ```tsx
3909
4774
  <Popover>
3910
- <Popover.Trigger openOnHover delay={200} asChild>
3911
- <Button variant="secondary">Hover Me</Button>
4775
+ <Popover.Trigger
4776
+ openOnHover
4777
+ delay={200}
4778
+ render={<Button variant="secondary" />}
4779
+ >
4780
+ Hover Me
3912
4781
  </Popover.Trigger>
3913
4782
  <Popover.Content>
3914
4783
  <Popover.Title>Hover Triggered</Popover.Title>
@@ -3917,22 +4786,85 @@ Close sub-component
3917
4786
  interactive content like buttons and links.
3918
4787
  </Popover.Description>
3919
4788
  <div className="mt-3">
3920
- <Popover.Close asChild>
3921
- <Button variant="secondary" size="sm">
3922
- Got it
3923
- </Button>
4789
+ <Popover.Close render={<Button variant="secondary" size="sm" />}>
4790
+ Got it
3924
4791
  </Popover.Close>
3925
4792
  </div>
3926
4793
  </Popover.Content>
3927
4794
  </Popover>
3928
4795
  ```
3929
4796
 
3930
-
3931
- ---
3932
-
4797
+ ```tsx
4798
+ <div className="w-full">
4799
+ <div className="overflow-hidden rounded-lg border border-kumo-hairline">
4800
+ <table className="w-full text-sm">
4801
+ <thead className="bg-kumo-elevated">
4802
+ <tr>
4803
+ <th className="px-4 py-2 text-left font-medium">Name</th>
4804
+ <th className="px-4 py-2 text-left font-medium">Status</th>
4805
+ <th className="w-12 px-4 py-2"></th>
4806
+ </tr>
4807
+ </thead>
4808
+ <tbody className="divide-y divide-kumo-hairline">
4809
+ {rows.map((row) => (
4810
+ <tr
4811
+ key={row.id}
4812
+ ref={(el) => {
4813
+ if (el) rowRefs.current.set(row.id, el);
4814
+ }}
4815
+ className={
4816
+ selectedRow === row.id ? "bg-kumo-recessed" : "bg-kumo-base"
4817
+ }
4818
+ >
4819
+ <td className="px-4 py-2 font-mono">{row.name}</td>
4820
+ <td className="px-4 py-2 text-kumo-subtle">{row.status}</td>
4821
+ <td className="px-4 py-2">
4822
+ <Button
4823
+ size="xs"
4824
+ variant="ghost"
4825
+ shape="square"
4826
+ icon={DotsThree}
4827
+ aria-label={`Actions for ${row.name}`}
4828
+ onClick={() => handleEdit(row.id)}
4829
+ />
4830
+ </td>
4831
+ </tr>
4832
+ ))}
4833
+ </tbody>
4834
+ </table>
4835
+ </div>
4836
+ <Popover
4837
+ open={!!selectedRow}
4838
+ onOpenChange={(open) => !open && setSelectedRow(null)}
4839
+ >
4840
+ <Popover.Content
4841
+ side="left"
4842
+ anchor={
4843
+ anchorRect ? { getBoundingClientRect: () => anchorRect } : undefined
4844
+ }
4845
+ >
4846
+ <Popover.Title>
4847
+ Edit {rows.find((r) => r.id === selectedRow)?.name}
4848
+ </Popover.Title>
4849
+ <Popover.Description>
4850
+ The popover anchors to the selected row, not the icon button.
4851
+ </Popover.Description>
4852
+ <div className="mt-3">
4853
+ <Popover.Close render={<Button size="sm" variant="secondary" />}>
4854
+ Close
4855
+ </Popover.Close>
4856
+ </div>
4857
+ </Popover.Content>
4858
+ </Popover>
4859
+ </div>
4860
+ ```
4861
+
4862
+
4863
+ ---
4864
+
3933
4865
  ### Radio
3934
4866
 
3935
- 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`.
4867
+ 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`.
3936
4868
 
3937
4869
  **Type:** component
3938
4870
 
@@ -3942,10 +4874,10 @@ Radio — radio button group for single-select choices. Compound component: `Ra
3942
4874
 
3943
4875
  **Props:**
3944
4876
 
3945
- - `legend`: string (required)
3946
- Legend text for the group (required for accessibility)
4877
+ - `legend`: string
4878
+ 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.
3947
4879
  - `children`: ReactNode
3948
- Child Radio.Item components
4880
+ Child Radio.Item components (and optionally a Radio.Legend)
3949
4881
  - `orientation`: enum
3950
4882
  Layout direction of the radio items
3951
4883
  - `appearance`: enum [default: default]
@@ -3964,7 +4896,7 @@ Radio — radio button group for single-select choices. Compound component: `Ra
3964
4896
  - `disabled`: boolean
3965
4897
  Whether all radios in the group are disabled
3966
4898
  - `controlPosition`: enum
3967
- 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.
4899
+ 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.
3968
4900
  - `name`: string
3969
4901
  Form submission name for the radio group
3970
4902
  - `className`: string
@@ -3972,7 +4904,7 @@ Radio — radio button group for single-select choices. Compound component: `Ra
3972
4904
 
3973
4905
  **Colors (kumo tokens used):**
3974
4906
 
3975
- `bg-kumo-base`, `bg-kumo-contrast`, `bg-kumo-tint`, `border-kumo-danger`, `border-kumo-hairline`, `border-kumo-interact`, `ring-kumo-danger`, `ring-kumo-hairline`, `ring-kumo-line`, `text-kumo-danger`, `text-kumo-default`, `text-kumo-subtle`
4907
+ `bg-kumo-base`, `bg-kumo-contrast`, `bg-kumo-tint`, `border-kumo-danger`, `border-kumo-hairline`, `border-kumo-interact`, `ring-kumo-brand`, `ring-kumo-danger`, `ring-kumo-focus`, `ring-kumo-hairline`, `ring-kumo-line`, `text-kumo-danger`, `text-kumo-default`, `text-kumo-subtle`
3976
4908
 
3977
4909
  **Sub-Components:**
3978
4910
 
@@ -3987,7 +4919,7 @@ Item sub-component
3987
4919
  Group sub-component
3988
4920
 
3989
4921
  Props:
3990
- - `legend`: string (required)
4922
+ - `legend`: string
3991
4923
  - `children`: ReactNode (required)
3992
4924
  - `orientation`: "vertical" | "horizontal"
3993
4925
  - `appearance`: KumoRadioAppearance
@@ -3995,12 +4927,19 @@ Props:
3995
4927
  - `description`: ReactNode
3996
4928
  - `value`: string
3997
4929
  - `disabled`: boolean
3998
- - `label`: "start" (default) puts radio before label (required)
3999
- - `Note`: In card appearance (required)
4930
+ - `label`: "start" puts radio before label (required)
4000
4931
  - `controlPosition`: RadioControlPosition
4001
4932
  - `name`: string
4002
4933
  - `className`: string
4003
4934
 
4935
+ #### Radio.Legend
4936
+
4937
+ Legend sub-component
4938
+
4939
+ Props:
4940
+ - `children`: ReactNode (required)
4941
+ - `className`: string
4942
+
4004
4943
 
4005
4944
  **Examples:**
4006
4945
 
@@ -4156,6 +5095,76 @@ Props:
4156
5095
  </Radio.Group>
4157
5096
  ```
4158
5097
 
5098
+ ```tsx
5099
+ <Radio.Group defaultValue="all" value={value} onValueChange={setValue}>
5100
+ <Radio.Legend className="sr-only">Paths</Radio.Legend>
5101
+ <Radio.Item label="Allow all paths" value="all" />
5102
+ <Radio.Item label="Restrict to specific paths" value="specific" />
5103
+ </Radio.Group>
5104
+ ```
5105
+
5106
+ ```tsx
5107
+ <Radio.Group value={value} onValueChange={setValue}>
5108
+ <Radio.Legend className="text-sm font-normal text-kumo-subtle">
5109
+ Notification preference
5110
+ </Radio.Legend>
5111
+ <Radio.Item label="Email" value="email" />
5112
+ <Radio.Item label="SMS" value="sms" />
5113
+ <Radio.Item label="Push notification" value="push" />
5114
+ </Radio.Group>
5115
+ ```
5116
+
5117
+ ```tsx
5118
+ <Radio.Group
5119
+ legend="Choose a plan"
5120
+ appearance="card"
5121
+ controlPosition="start"
5122
+ value={value}
5123
+ onValueChange={setValue}
5124
+ >
5125
+ <Radio.Item
5126
+ label="Free"
5127
+ description="For personal or hobby projects that aren't business-critical."
5128
+ value="free"
5129
+ />
5130
+ <Radio.Item
5131
+ label="Pro"
5132
+ description="For professional websites that aren't business-critical."
5133
+ value="pro"
5134
+ />
5135
+ </Radio.Group>
5136
+ ```
5137
+
5138
+ ```tsx
5139
+ <Radio.Group
5140
+ legend="Choose a plan"
5141
+ appearance="card"
5142
+ value={value}
5143
+ onValueChange={setValue}
5144
+ >
5145
+ <Radio.Item
5146
+ label={
5147
+ <span className="flex items-center gap-2">
5148
+ Free
5149
+ <Badge variant="neutral">$0</Badge>
5150
+ </span>
5151
+ }
5152
+ description="For personal or hobby projects."
5153
+ value="free"
5154
+ />
5155
+ <Radio.Item
5156
+ label={
5157
+ <span className="flex items-center gap-2">
5158
+ Pro
5159
+ <Badge variant="primary">Popular</Badge>
5160
+ </span>
5161
+ }
5162
+ description="For professional websites."
5163
+ value="pro"
5164
+ />
5165
+ </Radio.Group>
5166
+ ```
5167
+
4159
5168
  ```tsx
4160
5169
  <Radio.Group
4161
5170
  legend="Choose a plan"
@@ -4204,6 +5213,8 @@ Select component
4204
5213
 
4205
5214
  - `className`: string
4206
5215
  Additional CSS classes merged via `cn()`.
5216
+ - `size`: enum [default: base]
5217
+ Size of the select trigger. Matches Input component sizes.
4207
5218
  - `label`: ReactNode
4208
5219
  Label content for the select. When provided, enables the Field wrapper with a visible label above the select. For accessibility without a visible label, use `aria-label` instead.
4209
5220
  - `hideLabel`: boolean
@@ -4232,7 +5243,7 @@ Select component
4232
5243
 
4233
5244
  **Colors (kumo tokens used):**
4234
5245
 
4235
- `bg-kumo-base`, `bg-kumo-line`, `bg-kumo-tint`, `ring-kumo-hairline`, `text-kumo-danger`, `text-kumo-default`, `text-kumo-subtle`
5246
+ `bg-kumo-base`, `bg-kumo-elevated`, `bg-kumo-hairline`, `bg-kumo-tint`, `border-kumo-line`, `ring-kumo-brand`, `ring-kumo-focus`, `ring-kumo-line`, `text-kumo-danger`, `text-kumo-default`, `text-kumo-placeholder`, `text-kumo-subtle`
4236
5247
 
4237
5248
  **Styling:**
4238
5249
 
@@ -4270,6 +5281,51 @@ Separator sub-component
4270
5281
  />
4271
5282
  ```
4272
5283
 
5284
+ ```tsx
5285
+ <div className="grid gap-4">
5286
+ <div className="flex items-center gap-3">
5287
+ <span className="w-10 text-sm text-kumo-subtle">xs</span>
5288
+ <Select
5289
+ aria-label="Select size xs"
5290
+ size="xs"
5291
+ className="w-[200px]"
5292
+ placeholder="Choose..."
5293
+ items={{ a: "Option A", b: "Option B" }}
5294
+ />
5295
+ </div>
5296
+ <div className="flex items-center gap-3">
5297
+ <span className="w-10 text-sm text-kumo-subtle">sm</span>
5298
+ <Select
5299
+ aria-label="Select size sm"
5300
+ size="sm"
5301
+ className="w-[200px]"
5302
+ placeholder="Choose..."
5303
+ items={{ a: "Option A", b: "Option B" }}
5304
+ />
5305
+ </div>
5306
+ <div className="flex items-center gap-3">
5307
+ <span className="w-10 text-sm text-kumo-subtle">base</span>
5308
+ <Select
5309
+ aria-label="Select size base"
5310
+ size="base"
5311
+ className="w-[200px]"
5312
+ placeholder="Choose..."
5313
+ items={{ a: "Option A", b: "Option B" }}
5314
+ />
5315
+ </div>
5316
+ <div className="flex items-center gap-3">
5317
+ <span className="w-10 text-sm text-kumo-subtle">lg</span>
5318
+ <Select
5319
+ aria-label="Select size lg"
5320
+ size="lg"
5321
+ className="w-[200px]"
5322
+ placeholder="Choose..."
5323
+ items={{ a: "Option A", b: "Option B" }}
5324
+ />
5325
+ </div>
5326
+ </div>
5327
+ ```
5328
+
4273
5329
  ```tsx
4274
5330
  <Select
4275
5331
  label="Issue Type"
@@ -4432,13 +5488,12 @@ Separator sub-component
4432
5488
  <Select
4433
5489
  label="Author"
4434
5490
  description="Select the primary author for this document"
5491
+ placeholder="Select an author"
4435
5492
  className="w-[200px]"
4436
5493
  onValueChange={(v) => setValue(v as (typeof authors)[0] | null)}
4437
5494
  value={value}
4438
5495
  isItemEqualToValue={(item, value) => item?.id === value?.id}
4439
- renderValue={(author) => {
4440
- return author?.name ?? "Select an author";
4441
- }}
5496
+ renderValue={(author) => author.name}
4442
5497
  >
4443
5498
  {authors.map((author) => (
4444
5499
  <Select.Option key={author.id} value={author}>
@@ -4457,16 +5512,18 @@ Separator sub-component
4457
5512
  placeholder="Choose a region..."
4458
5513
  className="w-[250px]"
4459
5514
  value={value}
4460
- onValueChange={(v) => setValue(v as string | null)}
5515
+ onValueChange={(v) => setValue(v as Region | null)}
5516
+ isItemEqualToValue={(item, val) => item.value === val.value}
4461
5517
  >
4462
- <Select.Option value="us-east">US East</Select.Option>
4463
- <Select.Option value="us-west">US West</Select.Option>
4464
- <Select.Option value="eu-west" disabled>
4465
- EU West
4466
- </Select.Option>
4467
- <Select.Option value="ap-south" disabled>
4468
- AP South
4469
- </Select.Option>
5518
+ {regions.map((region) => (
5519
+ <Select.Option
5520
+ key={region.value}
5521
+ value={region}
5522
+ disabled={region.disabled}
5523
+ >
5524
+ {region.label}
5525
+ </Select.Option>
5526
+ ))}
4470
5527
  </Select>
4471
5528
  ```
4472
5529
 
@@ -4476,47 +5533,25 @@ Separator sub-component
4476
5533
  placeholder="Pick a food..."
4477
5534
  className="w-[220px]"
4478
5535
  value={value}
4479
- onValueChange={(v) => setValue(v as string | null)}
5536
+ onValueChange={(v) => setValue(v as Food | null)}
5537
+ isItemEqualToValue={(item, val) => item.value === val.value}
4480
5538
  >
4481
5539
  <Select.Group>
4482
5540
  <Select.GroupLabel>Fruits</Select.GroupLabel>
4483
- <Select.Option value="apple">Apple</Select.Option>
4484
- <Select.Option value="banana">Banana</Select.Option>
4485
- <Select.Option value="cherry">Cherry</Select.Option>
5541
+ {foods.fruits.map((food) => (
5542
+ <Select.Option key={food.value} value={food}>
5543
+ {food.label}
5544
+ </Select.Option>
5545
+ ))}
4486
5546
  </Select.Group>
4487
5547
  <Select.Separator />
4488
5548
  <Select.Group>
4489
5549
  <Select.GroupLabel>Vegetables</Select.GroupLabel>
4490
- <Select.Option value="carrot">Carrot</Select.Option>
4491
- <Select.Option value="broccoli">Broccoli</Select.Option>
4492
- <Select.Option value="spinach">Spinach</Select.Option>
4493
- </Select.Group>
4494
- </Select>
4495
- ```
4496
-
4497
- ```tsx
4498
- <Select
4499
- label="Server Region"
4500
- placeholder="Select a region..."
4501
- className="w-[260px]"
4502
- value={value}
4503
- onValueChange={(v) => setValue(v as string | null)}
4504
- >
4505
- <Select.Group>
4506
- <Select.GroupLabel>Available</Select.GroupLabel>
4507
- <Select.Option value="us-east-1">US East (N. Virginia)</Select.Option>
4508
- <Select.Option value="us-west-2">US West (Oregon)</Select.Option>
4509
- <Select.Option value="eu-west-1">EU West (Ireland)</Select.Option>
4510
- </Select.Group>
4511
- <Select.Separator />
4512
- <Select.Group>
4513
- <Select.GroupLabel>Unavailable</Select.GroupLabel>
4514
- <Select.Option value="ap-south-1" disabled>
4515
- AP South (Mumbai)
4516
- </Select.Option>
4517
- <Select.Option value="sa-east-1" disabled>
4518
- SA East (São Paulo)
4519
- </Select.Option>
5550
+ {foods.vegetables.map((food) => (
5551
+ <Select.Option key={food.value} value={food}>
5552
+ {food.label}
5553
+ </Select.Option>
5554
+ ))}
4520
5555
  </Select.Group>
4521
5556
  </Select>
4522
5557
  ```
@@ -4528,10 +5563,11 @@ Separator sub-component
4528
5563
  placeholder="Choose an option..."
4529
5564
  className="w-[220px]"
4530
5565
  value={value}
4531
- onValueChange={(v) => setValue(v as string | null)}
5566
+ onValueChange={(v) => setValue(v as LongListItem | null)}
5567
+ isItemEqualToValue={(item, val) => item.value === val.value}
4532
5568
  >
4533
5569
  {longListItems.map((item) => (
4534
- <Select.Option key={item.value} value={item.value}>
5570
+ <Select.Option key={item.value} value={item}>
4535
5571
  {item.label}
4536
5572
  </Select.Option>
4537
5573
  ))}
@@ -4592,7 +5628,7 @@ Password/secret input that masks its value by default and reveals on click. Incl
4592
5628
 
4593
5629
  **Colors (kumo tokens used):**
4594
5630
 
4595
- `bg-kumo-brand`, `bg-kumo-control`, `outline-kumo-hairline`, `ring-kumo-hairline`, `text-kumo-default`, `text-kumo-subtle`
5631
+ `bg-kumo-brand`, `bg-kumo-control`, `outline-kumo-focus`, `ring-kumo-brand`, `ring-kumo-focus`, `text-kumo-default`, `text-kumo-subtle`
4596
5632
 
4597
5633
  **Examples:**
4598
5634
 
@@ -4709,7 +5745,7 @@ Sidebar — responsive navigation panel with expand/collapse support. Compound
4709
5745
 
4710
5746
  **Colors (kumo tokens used):**
4711
5747
 
4712
- `bg-kumo-base`, `bg-kumo-brand`, `bg-kumo-line`, `bg-kumo-overlay`, `bg-kumo-recessed`, `bg-kumo-tint`, `border-kumo-line`, `ring-kumo-hairline`, `ring-kumo-line`, `text-kumo-default`, `text-kumo-strong`, `text-kumo-subtle`
5748
+ `bg-kumo-base`, `bg-kumo-brand`, `bg-kumo-hairline`, `bg-kumo-overlay`, `bg-kumo-recessed`, `bg-kumo-tint`, `border-kumo-hairline`, `ring-kumo-brand`, `ring-kumo-hairline`, `text-kumo-default`, `text-kumo-strong`, `text-kumo-subtle`
4713
5749
 
4714
5750
  **Styling:**
4715
5751
 
@@ -4739,66 +5775,129 @@ Props:
4739
5775
 
4740
5776
  Header sub-component
4741
5777
 
5778
+ Props:
5779
+ - `collapsible`: boolean
5780
+ - `defaultOpen`: boolean
5781
+ - `open`: boolean
5782
+
4742
5783
  #### Sidebar.Content
4743
5784
 
4744
5785
  Content sub-component
4745
5786
 
5787
+ Props:
5788
+ - `collapsible`: boolean
5789
+ - `defaultOpen`: boolean
5790
+ - `open`: boolean
5791
+
4746
5792
  #### Sidebar.Footer
4747
5793
 
4748
5794
  Footer sub-component
4749
5795
 
5796
+ Props:
5797
+ - `collapsible`: boolean
5798
+ - `defaultOpen`: boolean
5799
+ - `open`: boolean
5800
+
4750
5801
  #### Sidebar.Group
4751
5802
 
4752
5803
  Group sub-component
4753
5804
 
5805
+ Props:
5806
+ - `collapsible`: boolean
5807
+ - `defaultOpen`: boolean
5808
+ - `open`: boolean
5809
+
4754
5810
  #### Sidebar.GroupLabel
4755
5811
 
4756
5812
  GroupLabel sub-component
4757
5813
 
5814
+ Props:
5815
+ - `icon`: React.ComponentType<{ className?: string
5816
+
4758
5817
  #### Sidebar.GroupContent
4759
5818
 
4760
5819
  GroupContent sub-component
4761
5820
 
5821
+ Props:
5822
+ - `icon`: React.ComponentType<{ className?: string
5823
+
4762
5824
  #### Sidebar.Menu
4763
5825
 
4764
5826
  Menu sub-component
4765
5827
 
5828
+ Props:
5829
+ - `icon`: React.ComponentType<{ className?: string
5830
+
4766
5831
  #### Sidebar.MenuItem
4767
5832
 
4768
5833
  MenuItem sub-component
4769
5834
 
5835
+ Props:
5836
+ - `icon`: React.ComponentType<{ className?: string
5837
+
4770
5838
  #### Sidebar.MenuButton
4771
5839
 
4772
5840
  MenuButton sub-component
4773
5841
 
5842
+ Props:
5843
+ - `icon`: React.ComponentType<{ className?: string
5844
+
4774
5845
  #### Sidebar.MenuAction
4775
5846
 
4776
5847
  MenuAction sub-component
4777
5848
 
5849
+ Props:
5850
+ - `active`: boolean
5851
+ - `href`: string
5852
+
4778
5853
  #### Sidebar.MenuBadge
4779
5854
 
4780
5855
  MenuBadge sub-component
4781
5856
 
5857
+ Props:
5858
+ - `active`: boolean
5859
+ - `href`: string
5860
+
4782
5861
  #### Sidebar.MenuSub
4783
5862
 
4784
5863
  MenuSub sub-component
4785
5864
 
5865
+ Props:
5866
+ - `active`: boolean
5867
+ - `href`: string
5868
+
4786
5869
  #### Sidebar.MenuSubItem
4787
5870
 
4788
5871
  MenuSubItem sub-component
4789
5872
 
5873
+ Props:
5874
+ - `active`: boolean
5875
+ - `href`: string
5876
+
4790
5877
  #### Sidebar.MenuSubButton
4791
5878
 
4792
5879
  MenuSubButton sub-component
4793
5880
 
5881
+ Props:
5882
+ - `active`: boolean
5883
+ - `href`: string
5884
+
4794
5885
  #### Sidebar.Separator
4795
5886
 
4796
5887
  Separator sub-component
4797
5888
 
5889
+ Props:
5890
+ - `placeholder`: string
5891
+ - `shortcut`: string
5892
+
4798
5893
  #### Sidebar.Input
4799
5894
 
4800
5895
  Input sub-component
4801
5896
 
5897
+ Props:
5898
+ - `placeholder`: string
5899
+ - `shortcut`: string
5900
+
4802
5901
  #### Sidebar.Trigger
4803
5902
 
4804
5903
  Trigger sub-component
@@ -4815,6 +5914,9 @@ ResizeHandle sub-component
4815
5914
 
4816
5915
  MenuChevron sub-component
4817
5916
 
5917
+ Props:
5918
+ - `className`: string
5919
+
4818
5920
  #### Sidebar.Collapsible
4819
5921
 
4820
5922
  Collapsible sub-component
@@ -5144,7 +6246,7 @@ CollapsibleContent sub-component
5144
6246
 
5145
6247
  ### Surface
5146
6248
 
5147
- Polymorphic container with consistent background, shadow, and border styling. Use the `render` prop to change the underlying element: ```tsx <Surface render={<section />} className="rounded-lg p-4">Card content</Surface> ```
6249
+ Surface component
5148
6250
 
5149
6251
  **Type:** component
5150
6252
 
@@ -5156,7 +6258,7 @@ Polymorphic container with consistent background, shadow, and border styling. U
5156
6258
 
5157
6259
  - `as`: React.ElementType
5158
6260
  - `render`: ReactNode
5159
- Allows you to replace the components HTML element with a different tag, or compose it with another component.
6261
+ Allows you to replace the component's HTML element with a different tag, or compose it with another component.
5160
6262
 
5161
6263
  Accepts a `ReactElement` or a function that returns the element to render.
5162
6264
  - `children`: ReactNode
@@ -5165,49 +6267,6 @@ Accepts a `ReactElement` or a function that returns the element to render.
5165
6267
  - `lang`: string
5166
6268
  - `title`: string
5167
6269
 
5168
- **Colors (kumo tokens used):**
5169
-
5170
- `bg-kumo-base`, `ring-kumo-line`
5171
-
5172
- **Examples:**
5173
-
5174
- ```tsx
5175
- <Surface className="rounded-lg p-6">
5176
- <Text size="lg" bold>
5177
- Surface Component
5178
- </Text>
5179
- <div className="mt-2">
5180
- <Text variant="secondary">
5181
- A container with consistent elevation and border styling.
5182
- </Text>
5183
- </div>
5184
- </Surface>
5185
- ```
5186
-
5187
- ```tsx
5188
- <div className="flex flex-col gap-4">
5189
- <Surface render={<section />} className="rounded-lg p-4">
5190
- <Text bold>As section element</Text>
5191
- </Surface>
5192
- <Surface render={<article />} className="rounded-lg p-4">
5193
- <Text bold>As article element</Text>
5194
- </Surface>
5195
- <Surface render={<aside />} className="rounded-lg p-4">
5196
- <Text bold>As aside element</Text>
5197
- </Surface>
5198
- </div>
5199
- ```
5200
-
5201
- ```tsx
5202
- <Surface className="rounded-lg p-6">
5203
- <Text bold>Outer Surface</Text>
5204
- <Surface className="mt-4 rounded-md bg-kumo-elevated p-4">
5205
- <Text variant="secondary">Nested Surface</Text>
5206
- </Surface>
5207
- </Surface>
5208
- ```
5209
-
5210
-
5211
6270
  ---
5212
6271
 
5213
6272
  ### Switch
@@ -5252,7 +6311,7 @@ Switch component
5252
6311
 
5253
6312
  **Colors (kumo tokens used):**
5254
6313
 
5255
- `bg-kumo-base`, `border-kumo-line`, `ring-kumo-line`, `text-kumo-danger`, `text-kumo-default`, `text-kumo-subtle`
6314
+ `bg-kumo-base`, `ring-kumo-brand`, `ring-kumo-focus`, `ring-kumo-hairline`, `text-kumo-danger`, `text-kumo-default`, `text-kumo-subtle`
5256
6315
 
5257
6316
  **Sub-Components:**
5258
6317
 
@@ -5267,7 +6326,7 @@ Item sub-component
5267
6326
  Group sub-component
5268
6327
 
5269
6328
  Props:
5270
- - `legend`: string (required)
6329
+ - `legend`: string
5271
6330
  - `children`: ReactNode (required)
5272
6331
  - `error`: string
5273
6332
  - `description`: ReactNode
@@ -5275,6 +6334,14 @@ Props:
5275
6334
  - `controlFirst`: boolean
5276
6335
  - `className`: string
5277
6336
 
6337
+ #### Switch.Legend
6338
+
6339
+ Legend sub-component
6340
+
6341
+ Props:
6342
+ - `children`: ReactNode (required)
6343
+ - `className`: string
6344
+
5278
6345
 
5279
6346
  **Examples:**
5280
6347
 
@@ -5346,6 +6413,23 @@ Props:
5346
6413
  />
5347
6414
  ```
5348
6415
 
6416
+ ```tsx
6417
+ <Switch.Group legend="Notification settings">
6418
+ <Switch.Item label="Email notifications" />
6419
+ <Switch.Item label="SMS notifications" />
6420
+ <Switch.Item label="Push notifications" />
6421
+ </Switch.Group>
6422
+ ```
6423
+
6424
+ ```tsx
6425
+ <Switch.Group>
6426
+ <Switch.Legend className="sr-only">Notification settings</Switch.Legend>
6427
+ <Switch.Item label="Email notifications" />
6428
+ <Switch.Item label="SMS notifications" />
6429
+ <Switch.Item label="Push notifications" />
6430
+ </Switch.Group>
6431
+ ```
6432
+
5349
6433
  ```tsx
5350
6434
  <div className="flex flex-col gap-4">
5351
6435
  <Switch
@@ -5400,7 +6484,7 @@ Table — semantic HTML table with styled rows, cells, and selection support. C
5400
6484
 
5401
6485
  **Colors (kumo tokens used):**
5402
6486
 
5403
- `bg-kumo-base`, `bg-kumo-elevated`, `bg-kumo-hairline`, `bg-kumo-tint`, `border-kumo-fill`, `text-kumo-default`, `text-kumo-strong`
6487
+ `bg-kumo-base`, `bg-kumo-elevated`, `bg-kumo-hairline`, `bg-kumo-tint`, `border-kumo-fill`, `ring-kumo-brand`, `text-kumo-default`, `text-kumo-strong`
5404
6488
 
5405
6489
  **Sub-Components:**
5406
6490
 
@@ -5446,326 +6530,553 @@ ResizeHandle sub-component
5446
6530
  **Examples:**
5447
6531
 
5448
6532
  ```tsx
5449
- <LayerCard>
5450
- <LayerCard.Primary className="p-0">
5451
- <Table>
5452
- <Table.Header>
5453
- <Table.Row>
5454
- <Table.Head>Subject</Table.Head>
5455
- <Table.Head>From</Table.Head>
5456
- <Table.Head>Date</Table.Head>
6533
+ <LayerCard className="p-0">
6534
+ <Table>
6535
+ <Table.Header>
6536
+ <Table.Row>
6537
+ <Table.Head>Subject</Table.Head>
6538
+ <Table.Head>From</Table.Head>
6539
+ <Table.Head>Date</Table.Head>
6540
+ </Table.Row>
6541
+ </Table.Header>
6542
+ <Table.Body>
6543
+ {emailData.slice(0, 3).map((row) => (
6544
+ <Table.Row key={row.id}>
6545
+ <Table.Cell>{row.subject}</Table.Cell>
6546
+ <Table.Cell>{row.from}</Table.Cell>
6547
+ <Table.Cell>{row.date}</Table.Cell>
5457
6548
  </Table.Row>
5458
- </Table.Header>
5459
- <Table.Body>
5460
- {emailData.slice(0, 3).map((row) => (
5461
- <Table.Row key={row.id}>
5462
- <Table.Cell>{row.subject}</Table.Cell>
5463
- <Table.Cell>{row.from}</Table.Cell>
5464
- <Table.Cell>{row.date}</Table.Cell>
5465
- </Table.Row>
5466
- ))}
5467
- </Table.Body>
5468
- </Table>
5469
- </LayerCard.Primary>
6549
+ ))}
6550
+ </Table.Body>
6551
+ </Table>
5470
6552
  </LayerCard>
5471
6553
  ```
5472
6554
 
5473
6555
  ```tsx
5474
- <LayerCard>
5475
- <LayerCard.Primary className="p-0">
5476
- <Table>
5477
- <Table.Header>
5478
- <Table.Row>
5479
- <Table.CheckHead
5480
- checked={selectedIds.size === rows.length}
5481
- indeterminate={
5482
- selectedIds.size > 0 && selectedIds.size < rows.length
5483
- }
5484
- onValueChange={toggleAll}
5485
- aria-label="Select all rows"
6556
+ <LayerCard className="p-0">
6557
+ <Table>
6558
+ <Table.Header>
6559
+ <Table.Row>
6560
+ <Table.CheckHead
6561
+ checked={selectedIds.size === rows.length}
6562
+ indeterminate={
6563
+ selectedIds.size > 0 && selectedIds.size < rows.length
6564
+ }
6565
+ onCheckedChange={toggleAll}
6566
+ aria-label="Select all rows"
6567
+ />
6568
+ <Table.Head>Subject</Table.Head>
6569
+ <Table.Head>From</Table.Head>
6570
+ <Table.Head>Date</Table.Head>
6571
+ </Table.Row>
6572
+ </Table.Header>
6573
+ <Table.Body>
6574
+ {rows.map((row) => (
6575
+ <Table.Row key={row.id}>
6576
+ <Table.CheckCell
6577
+ checked={selectedIds.has(row.id)}
6578
+ onCheckedChange={() => toggleRow(row.id)}
6579
+ aria-label={`Select ${row.subject}`}
5486
6580
  />
5487
- <Table.Head>Subject</Table.Head>
5488
- <Table.Head>From</Table.Head>
5489
- <Table.Head>Date</Table.Head>
6581
+ <Table.Cell>{row.subject}</Table.Cell>
6582
+ <Table.Cell>{row.from}</Table.Cell>
6583
+ <Table.Cell>{row.date}</Table.Cell>
5490
6584
  </Table.Row>
5491
- </Table.Header>
5492
- <Table.Body>
5493
- {rows.map((row) => (
5494
- <Table.Row key={row.id}>
5495
- <Table.CheckCell
5496
- checked={selectedIds.has(row.id)}
5497
- onValueChange={() => toggleRow(row.id)}
5498
- aria-label={`Select ${row.subject}`}
5499
- />
5500
- <Table.Cell>{row.subject}</Table.Cell>
5501
- <Table.Cell>{row.from}</Table.Cell>
5502
- <Table.Cell>{row.date}</Table.Cell>
5503
- </Table.Row>
5504
- ))}
5505
- </Table.Body>
5506
- </Table>
5507
- </LayerCard.Primary>
6585
+ ))}
6586
+ </Table.Body>
6587
+ </Table>
5508
6588
  </LayerCard>
5509
6589
  ```
5510
6590
 
5511
6591
  ```tsx
5512
- <LayerCard>
5513
- <LayerCard.Primary className="p-0">
5514
- <Table>
5515
- <Table.Header variant="compact">
5516
- <Table.Row>
5517
- <Table.Head>Subject</Table.Head>
5518
- <Table.Head>From</Table.Head>
5519
- <Table.Head>Date</Table.Head>
6592
+ <LayerCard className="p-0">
6593
+ <Table>
6594
+ <Table.Header variant="compact">
6595
+ <Table.Row>
6596
+ <Table.Head>Subject</Table.Head>
6597
+ <Table.Head>From</Table.Head>
6598
+ <Table.Head>Date</Table.Head>
6599
+ </Table.Row>
6600
+ </Table.Header>
6601
+ <Table.Body>
6602
+ {emailData.slice(0, 3).map((row) => (
6603
+ <Table.Row key={row.id}>
6604
+ <Table.Cell>{row.subject}</Table.Cell>
6605
+ <Table.Cell>{row.from}</Table.Cell>
6606
+ <Table.Cell>{row.date}</Table.Cell>
5520
6607
  </Table.Row>
5521
- </Table.Header>
5522
- <Table.Body>
5523
- {emailData.slice(0, 3).map((row) => (
5524
- <Table.Row key={row.id}>
5525
- <Table.Cell>{row.subject}</Table.Cell>
5526
- <Table.Cell>{row.from}</Table.Cell>
5527
- <Table.Cell>{row.date}</Table.Cell>
5528
- </Table.Row>
5529
- ))}
5530
- </Table.Body>
5531
- </Table>
5532
- </LayerCard.Primary>
6608
+ ))}
6609
+ </Table.Body>
6610
+ </Table>
5533
6611
  </LayerCard>
5534
6612
  ```
5535
6613
 
5536
6614
  ```tsx
5537
- <LayerCard>
5538
- <LayerCard.Primary className="p-0">
5539
- <Table>
5540
- <Table.Header>
5541
- <Table.Row>
5542
- <Table.CheckHead
5543
- checked={selectedIds.size === rows.length}
5544
- indeterminate={
5545
- selectedIds.size > 0 && selectedIds.size < rows.length
5546
- }
5547
- onValueChange={toggleAll}
5548
- aria-label="Select all rows"
6615
+ <LayerCard className="p-0">
6616
+ <Table>
6617
+ <Table.Header>
6618
+ <Table.Row>
6619
+ <Table.CheckHead
6620
+ checked={selectedIds.size === rows.length}
6621
+ indeterminate={
6622
+ selectedIds.size > 0 && selectedIds.size < rows.length
6623
+ }
6624
+ onCheckedChange={toggleAll}
6625
+ aria-label="Select all rows"
6626
+ />
6627
+ <Table.Head>Subject</Table.Head>
6628
+ <Table.Head>From</Table.Head>
6629
+ <Table.Head>Date</Table.Head>
6630
+ </Table.Row>
6631
+ </Table.Header>
6632
+ <Table.Body>
6633
+ {rows.map((row) => (
6634
+ <Table.Row
6635
+ key={row.id}
6636
+ variant={selectedIds.has(row.id) ? "selected" : "default"}
6637
+ >
6638
+ <Table.CheckCell
6639
+ checked={selectedIds.has(row.id)}
6640
+ onCheckedChange={() => toggleRow(row.id)}
6641
+ aria-label={`Select ${row.subject}`}
5549
6642
  />
5550
- <Table.Head>Subject</Table.Head>
5551
- <Table.Head>From</Table.Head>
5552
- <Table.Head>Date</Table.Head>
6643
+ <Table.Cell>{row.subject}</Table.Cell>
6644
+ <Table.Cell>{row.from}</Table.Cell>
6645
+ <Table.Cell>{row.date}</Table.Cell>
5553
6646
  </Table.Row>
5554
- </Table.Header>
5555
- <Table.Body>
5556
- {rows.map((row) => (
5557
- <Table.Row
5558
- key={row.id}
5559
- variant={selectedIds.has(row.id) ? "selected" : "default"}
5560
- >
5561
- <Table.CheckCell
5562
- checked={selectedIds.has(row.id)}
5563
- onValueChange={() => toggleRow(row.id)}
5564
- aria-label={`Select ${row.subject}`}
5565
- />
5566
- <Table.Cell>{row.subject}</Table.Cell>
5567
- <Table.Cell>{row.from}</Table.Cell>
5568
- <Table.Cell>{row.date}</Table.Cell>
5569
- </Table.Row>
5570
- ))}
5571
- </Table.Body>
5572
- </Table>
5573
- </LayerCard.Primary>
6647
+ ))}
6648
+ </Table.Body>
6649
+ </Table>
5574
6650
  </LayerCard>
5575
6651
  ```
5576
6652
 
5577
6653
  ```tsx
5578
- <LayerCard>
5579
- <LayerCard.Primary className="p-0">
5580
- <Table layout="fixed">
5581
- <colgroup>
5582
- <col />
5583
- <col className="w-[150px]" />
5584
- <col className="w-[150px]" />
5585
- </colgroup>
5586
- <Table.Header>
5587
- <Table.Row>
5588
- <Table.Head>Subject</Table.Head>
5589
- <Table.Head>From</Table.Head>
5590
- <Table.Head>Date</Table.Head>
6654
+ <LayerCard className="p-0">
6655
+ <Table layout="fixed">
6656
+ <colgroup>
6657
+ <col />
6658
+ <col className="w-[150px]" />
6659
+ <col className="w-[150px]" />
6660
+ </colgroup>
6661
+ <Table.Header>
6662
+ <Table.Row>
6663
+ <Table.Head>Subject</Table.Head>
6664
+ <Table.Head>From</Table.Head>
6665
+ <Table.Head>Date</Table.Head>
6666
+ </Table.Row>
6667
+ </Table.Header>
6668
+ <Table.Body>
6669
+ {emailData.map((row) => (
6670
+ <Table.Row key={row.id}>
6671
+ <Table.Cell>{row.subject}</Table.Cell>
6672
+ <Table.Cell>{row.from}</Table.Cell>
6673
+ <Table.Cell>{row.date}</Table.Cell>
5591
6674
  </Table.Row>
5592
- </Table.Header>
5593
- <Table.Body>
5594
- {emailData.map((row) => (
5595
- <Table.Row key={row.id}>
5596
- <Table.Cell>{row.subject}</Table.Cell>
5597
- <Table.Cell>{row.from}</Table.Cell>
5598
- <Table.Cell>{row.date}</Table.Cell>
5599
- </Table.Row>
5600
- ))}
5601
- </Table.Body>
5602
- </Table>
5603
- </LayerCard.Primary>
6675
+ ))}
6676
+ </Table.Body>
6677
+ </Table>
5604
6678
  </LayerCard>
5605
6679
  ```
5606
6680
 
5607
6681
  ```tsx
5608
- <LayerCard>
5609
- <LayerCard.Primary className="w-full max-w-md overflow-x-auto p-0">
5610
- <Table>
5611
- <Table.Header>
5612
- <Table.Row>
5613
- <Table.Head>Subject</Table.Head>
5614
- <Table.Head>From</Table.Head>
5615
- <Table.Head>Date</Table.Head>
5616
- <Table.Head>Tags</Table.Head>
5617
- <Table.Head sticky="right">
5618
- <span className="sr-only">Actions</span>
5619
- </Table.Head>
6682
+ <LayerCard className="w-full max-w-md overflow-x-auto p-0">
6683
+ <Table>
6684
+ <Table.Header variant="compact">
6685
+ <Table.Row>
6686
+ <Table.Head>Subject</Table.Head>
6687
+ <Table.Head>From</Table.Head>
6688
+ <Table.Head>Date</Table.Head>
6689
+ <Table.Head>Tags</Table.Head>
6690
+ <Table.Head sticky="right">
6691
+ <span className="sr-only">Actions</span>
6692
+ </Table.Head>
6693
+ </Table.Row>
6694
+ </Table.Header>
6695
+ <Table.Body>
6696
+ {emailData.map((row) => (
6697
+ <Table.Row key={row.id}>
6698
+ <Table.Cell className="whitespace-nowrap">
6699
+ {row.subject}
6700
+ </Table.Cell>
6701
+ <Table.Cell className="whitespace-nowrap">
6702
+ {row.from}
6703
+ </Table.Cell>
6704
+ <Table.Cell className="whitespace-nowrap">
6705
+ {row.date}
6706
+ </Table.Cell>
6707
+ <Table.Cell className="whitespace-nowrap">
6708
+ {row.tags ? (
6709
+ <div className="inline-flex gap-1">
6710
+ {row.tags.map((tag) => (
6711
+ <Badge key={tag}>{tag}</Badge>
6712
+ ))}
6713
+ </div>
6714
+ ) : (
6715
+ "—"
6716
+ )}
6717
+ </Table.Cell>
6718
+ <Table.Cell sticky="right" className="text-right">
6719
+ <DropdownMenu>
6720
+ <DropdownMenu.Trigger
6721
+ render={
6722
+ <Button
6723
+ variant="ghost"
6724
+ size="sm"
6725
+ shape="square"
6726
+ aria-label="More options"
6727
+ >
6728
+ <DotsThree weight="bold" size={16} />
6729
+ </Button>
6730
+ }
6731
+ />
6732
+ <DropdownMenu.Content>
6733
+ <DropdownMenu.Item icon={Eye}>View</DropdownMenu.Item>
6734
+ <DropdownMenu.Item icon={PencilSimple}>
6735
+ Edit
6736
+ </DropdownMenu.Item>
6737
+ <DropdownMenu.Separator />
6738
+ <DropdownMenu.Item icon={Trash} variant="danger">
6739
+ Delete
6740
+ </DropdownMenu.Item>
6741
+ </DropdownMenu.Content>
6742
+ </DropdownMenu>
6743
+ </Table.Cell>
6744
+ </Table.Row>
6745
+ ))}
6746
+ </Table.Body>
6747
+ </Table>
6748
+ </LayerCard>
6749
+ ```
6750
+
6751
+ ```tsx
6752
+ <LayerCard className="w-full max-w-md overflow-x-auto p-0">
6753
+ <Table>
6754
+ <Table.Header>
6755
+ <Table.Row>
6756
+ <Table.Head>Subject</Table.Head>
6757
+ <Table.Head>From</Table.Head>
6758
+ <Table.Head>Date</Table.Head>
6759
+ <Table.Head>Tags</Table.Head>
6760
+ <Table.Head sticky="right">
6761
+ <span className="sr-only">Actions</span>
6762
+ </Table.Head>
6763
+ </Table.Row>
6764
+ </Table.Header>
6765
+ <Table.Body>
6766
+ {emailData.map((row) => (
6767
+ <Table.Row key={row.id}>
6768
+ <Table.Cell className="whitespace-nowrap">
6769
+ {row.subject}
6770
+ </Table.Cell>
6771
+ <Table.Cell className="whitespace-nowrap">
6772
+ {row.from}
6773
+ </Table.Cell>
6774
+ <Table.Cell className="whitespace-nowrap">
6775
+ {row.date}
6776
+ </Table.Cell>
6777
+ <Table.Cell className="whitespace-nowrap">
6778
+ {row.tags ? (
6779
+ <div className="inline-flex gap-1">
6780
+ {row.tags.map((tag) => (
6781
+ <Badge key={tag}>{tag}</Badge>
6782
+ ))}
6783
+ </div>
6784
+ ) : (
6785
+ "—"
6786
+ )}
6787
+ </Table.Cell>
6788
+ <Table.Cell sticky="right" className="text-right">
6789
+ <DropdownMenu>
6790
+ <DropdownMenu.Trigger
6791
+ render={
6792
+ <Button
6793
+ variant="ghost"
6794
+ size="sm"
6795
+ shape="square"
6796
+ aria-label="More options"
6797
+ >
6798
+ <DotsThree weight="bold" size={16} />
6799
+ </Button>
6800
+ }
6801
+ />
6802
+ <DropdownMenu.Content>
6803
+ <DropdownMenu.Item icon={Eye}>View</DropdownMenu.Item>
6804
+ <DropdownMenu.Item icon={PencilSimple}>
6805
+ Edit
6806
+ </DropdownMenu.Item>
6807
+ <DropdownMenu.Separator />
6808
+ <DropdownMenu.Item icon={Trash} variant="danger">
6809
+ Delete
6810
+ </DropdownMenu.Item>
6811
+ </DropdownMenu.Content>
6812
+ </DropdownMenu>
6813
+ </Table.Cell>
5620
6814
  </Table.Row>
5621
- </Table.Header>
5622
- <Table.Body>
5623
- {emailData.map((row) => (
5624
- <Table.Row key={row.id}>
5625
- <Table.Cell className="whitespace-nowrap">
5626
- {row.subject}
5627
- </Table.Cell>
5628
- <Table.Cell className="whitespace-nowrap">
5629
- {row.from}
5630
- </Table.Cell>
5631
- <Table.Cell className="whitespace-nowrap">
5632
- {row.date}
5633
- </Table.Cell>
5634
- <Table.Cell className="whitespace-nowrap">
5635
- {row.tags ? (
5636
- <div className="inline-flex gap-1">
6815
+ ))}
6816
+ </Table.Body>
6817
+ </Table>
6818
+ </LayerCard>
6819
+ ```
6820
+
6821
+ ```tsx
6822
+ <LayerCard className="w-full overflow-x-auto p-0">
6823
+ <Table layout="fixed">
6824
+ <colgroup>
6825
+ <col />{" "}
6826
+ {/* Checkbox column - width handled by Table.CheckHead/CheckCell */}
6827
+ <col />
6828
+ <col style={{ width: "150px" }} />
6829
+ <col style={{ width: "120px" }} />
6830
+ <col style={{ width: "50px" }} />
6831
+ </colgroup>
6832
+ <Table.Header>
6833
+ <Table.Row>
6834
+ <Table.CheckHead
6835
+ checked={selectedIds.size === emailData.length}
6836
+ indeterminate={
6837
+ selectedIds.size > 0 && selectedIds.size < emailData.length
6838
+ }
6839
+ onCheckedChange={toggleAll}
6840
+ aria-label="Select all rows"
6841
+ />
6842
+ <Table.Head>Subject</Table.Head>
6843
+ <Table.Head>From</Table.Head>
6844
+ <Table.Head>Date</Table.Head>
6845
+ <Table.Head></Table.Head>
6846
+ </Table.Row>
6847
+ </Table.Header>
6848
+ <Table.Body>
6849
+ {emailData.map((row) => (
6850
+ <Table.Row
6851
+ key={row.id}
6852
+ variant={selectedIds.has(row.id) ? "selected" : "default"}
6853
+ >
6854
+ <Table.CheckCell
6855
+ checked={selectedIds.has(row.id)}
6856
+ onCheckedChange={() => toggleRow(row.id)}
6857
+ aria-label={`Select ${row.subject}`}
6858
+ />
6859
+ <Table.Cell>
6860
+ <div className="flex items-center gap-2">
6861
+ <EnvelopeSimple size={16} />
6862
+ <span className="truncate">{row.subject}</span>
6863
+ {row.tags && (
6864
+ <div className="ml-2 inline-flex gap-1">
5637
6865
  {row.tags.map((tag) => (
5638
6866
  <Badge key={tag}>{tag}</Badge>
5639
6867
  ))}
5640
6868
  </div>
5641
- ) : (
5642
- "—"
5643
6869
  )}
5644
- </Table.Cell>
5645
- <Table.Cell sticky="right" className="text-right">
5646
- <DropdownMenu>
5647
- <DropdownMenu.Trigger
5648
- render={
5649
- <Button
5650
- variant="ghost"
5651
- size="sm"
5652
- shape="square"
5653
- aria-label="More options"
5654
- >
5655
- <DotsThree weight="bold" size={16} />
5656
- </Button>
5657
- }
5658
- />
5659
- <DropdownMenu.Content>
5660
- <DropdownMenu.Item icon={Eye}>View</DropdownMenu.Item>
5661
- <DropdownMenu.Item icon={PencilSimple}>
5662
- Edit
5663
- </DropdownMenu.Item>
5664
- <DropdownMenu.Separator />
5665
- <DropdownMenu.Item icon={Trash} variant="danger">
5666
- Delete
5667
- </DropdownMenu.Item>
5668
- </DropdownMenu.Content>
5669
- </DropdownMenu>
5670
- </Table.Cell>
5671
- </Table.Row>
5672
- ))}
5673
- </Table.Body>
5674
- </Table>
5675
- </LayerCard.Primary>
6870
+ </div>
6871
+ </Table.Cell>
6872
+ <Table.Cell>
6873
+ <span className="truncate">{row.from}</span>
6874
+ </Table.Cell>
6875
+ <Table.Cell>
6876
+ <span className="truncate">{row.date}</span>
6877
+ </Table.Cell>
6878
+ <Table.Cell className="text-right">
6879
+ <DropdownMenu>
6880
+ <DropdownMenu.Trigger
6881
+ render={
6882
+ <Button
6883
+ variant="ghost"
6884
+ size="sm"
6885
+ shape="square"
6886
+ aria-label="More options"
6887
+ >
6888
+ <DotsThree weight="bold" size={16} />
6889
+ </Button>
6890
+ }
6891
+ />
6892
+ <DropdownMenu.Content>
6893
+ <DropdownMenu.Item icon={Eye}>View</DropdownMenu.Item>
6894
+ <DropdownMenu.Item icon={PencilSimple}>
6895
+ Edit
6896
+ </DropdownMenu.Item>
6897
+ <DropdownMenu.Separator />
6898
+ <DropdownMenu.Item icon={Trash} variant="danger">
6899
+ Delete
6900
+ </DropdownMenu.Item>
6901
+ </DropdownMenu.Content>
6902
+ </DropdownMenu>
6903
+ </Table.Cell>
6904
+ </Table.Row>
6905
+ ))}
6906
+ </Table.Body>
6907
+ </Table>
5676
6908
  </LayerCard>
5677
6909
  ```
5678
6910
 
6911
+
6912
+ ---
6913
+
6914
+ ### TableOfContents
6915
+
6916
+ TableOfContents — presentational compound component for section navigation. Purely visual; all interaction logic (scroll tracking, active state management) is left to the consumer.
6917
+
6918
+ **Type:** component
6919
+
6920
+ **Import:** `import { TableOfContents } from "@cloudflare/kumo";`
6921
+
6922
+ **Category:** Other
6923
+
6924
+ **Props:**
6925
+
6926
+ - `children`: ReactNode
6927
+ - `className`: string
6928
+ - `id`: string
6929
+ - `lang`: string
6930
+ - `title`: string
6931
+
6932
+ **Colors (kumo tokens used):**
6933
+
6934
+ `border-kumo-brand`, `border-kumo-hairline`, `border-kumo-line`, `text-kumo-default`, `text-kumo-subtle`
6935
+
6936
+ **Sub-Components:**
6937
+
6938
+ This is a compound component. Use these sub-components:
6939
+
6940
+ #### TableOfContents.Title
6941
+
6942
+ Title sub-component
6943
+
6944
+ #### TableOfContents.List
6945
+
6946
+ List sub-component
6947
+
6948
+ #### TableOfContents.Item
6949
+
6950
+ Item sub-component
6951
+
6952
+ Props:
6953
+ - `active`: boolean
6954
+
6955
+ #### TableOfContents.Group
6956
+
6957
+ Group sub-component
6958
+
6959
+ Props:
6960
+ - `label`: string (required)
6961
+ - `href`: string
6962
+ - `active`: boolean
6963
+
6964
+
6965
+ **Examples:**
6966
+
5679
6967
  ```tsx
5680
- <LayerCard>
5681
- <LayerCard.Primary className="w-full overflow-x-auto p-0">
5682
- <Table layout="fixed">
5683
- <colgroup>
5684
- <col />{" "}
5685
- {/* Checkbox column - width handled by Table.CheckHead/CheckCell */}
5686
- <col />
5687
- <col style={{ width: "150px" }} />
5688
- <col style={{ width: "120px" }} />
5689
- <col style={{ width: "50px" }} />
5690
- </colgroup>
5691
- <Table.Header>
5692
- <Table.Row>
5693
- <Table.CheckHead
5694
- checked={selectedIds.size === emailData.length}
5695
- indeterminate={
5696
- selectedIds.size > 0 && selectedIds.size < emailData.length
5697
- }
5698
- onValueChange={toggleAll}
5699
- aria-label="Select all rows"
5700
- />
5701
- <Table.Head>Subject</Table.Head>
5702
- <Table.Head>From</Table.Head>
5703
- <Table.Head>Date</Table.Head>
5704
- <Table.Head></Table.Head>
5705
- </Table.Row>
5706
- </Table.Header>
5707
- <Table.Body>
5708
- {emailData.map((row) => (
5709
- <Table.Row
5710
- key={row.id}
5711
- variant={selectedIds.has(row.id) ? "selected" : "default"}
6968
+ <DemoWrapper>
6969
+ <TableOfContents>
6970
+ <TableOfContents.Title>On this page</TableOfContents.Title>
6971
+ <TableOfContents.List>
6972
+ {headings.map((heading) => (
6973
+ <TableOfContents.Item
6974
+ key={heading.text}
6975
+ active={heading.text === "Usage"}
6976
+ className="cursor-pointer"
6977
+ >
6978
+ {heading.text}
6979
+ </TableOfContents.Item>
6980
+ ))}
6981
+ </TableOfContents.List>
6982
+ </TableOfContents>
6983
+ </DemoWrapper>
6984
+ ```
6985
+
6986
+ ```tsx
6987
+ <DemoWrapper>
6988
+ <TableOfContents>
6989
+ <TableOfContents.Title>On this page</TableOfContents.Title>
6990
+ <TableOfContents.List>
6991
+ {headings.map((heading) => (
6992
+ <TableOfContents.Item
6993
+ key={heading.text}
6994
+ active={heading.text === active}
6995
+ onClick={() => setActive(heading.text)}
6996
+ className="cursor-pointer"
6997
+ >
6998
+ {heading.text}
6999
+ </TableOfContents.Item>
7000
+ ))}
7001
+ </TableOfContents.List>
7002
+ </TableOfContents>
7003
+ </DemoWrapper>
7004
+ ```
7005
+
7006
+ ```tsx
7007
+ <DemoWrapper>
7008
+ <TableOfContents>
7009
+ <TableOfContents.Title>On this page</TableOfContents.Title>
7010
+ <TableOfContents.List>
7011
+ {headings.map((heading) => (
7012
+ <TableOfContents.Item key={heading.text} className="cursor-pointer">
7013
+ {heading.text}
7014
+ </TableOfContents.Item>
7015
+ ))}
7016
+ </TableOfContents.List>
7017
+ </TableOfContents>
7018
+ </DemoWrapper>
7019
+ ```
7020
+
7021
+ ```tsx
7022
+ <DemoWrapper>
7023
+ <TableOfContents>
7024
+ <TableOfContents.Title>On this page</TableOfContents.Title>
7025
+ <TableOfContents.List>
7026
+ <TableOfContents.Item active className="cursor-pointer">
7027
+ Overview
7028
+ </TableOfContents.Item>
7029
+ <TableOfContents.Group label="Examples" href="#examples-demo">
7030
+ <TableOfContents.Item className="cursor-pointer">
7031
+ Basic example
7032
+ </TableOfContents.Item>
7033
+ <TableOfContents.Item className="cursor-pointer">
7034
+ Advanced example
7035
+ </TableOfContents.Item>
7036
+ </TableOfContents.Group>
7037
+ <TableOfContents.Group label="Getting Started">
7038
+ <TableOfContents.Item className="cursor-pointer">
7039
+ Installation
7040
+ </TableOfContents.Item>
7041
+ <TableOfContents.Item className="cursor-pointer">
7042
+ Configuration
7043
+ </TableOfContents.Item>
7044
+ </TableOfContents.Group>
7045
+ <TableOfContents.Group label="API" href="#api-demo">
7046
+ <TableOfContents.Item className="cursor-pointer">
7047
+ Props
7048
+ </TableOfContents.Item>
7049
+ <TableOfContents.Item className="cursor-pointer">
7050
+ Events
7051
+ </TableOfContents.Item>
7052
+ </TableOfContents.Group>
7053
+ </TableOfContents.List>
7054
+ </TableOfContents>
7055
+ </DemoWrapper>
7056
+ ```
7057
+
7058
+ ```tsx
7059
+ <DemoWrapper>
7060
+ <div className="space-y-3">
7061
+ <TableOfContents>
7062
+ <TableOfContents.List>
7063
+ {["Introduction", "Installation", "Usage"].map((text) => (
7064
+ <TableOfContents.Item
7065
+ key={text}
7066
+ render={<button type="button" />}
7067
+ onClick={() => setClicked(text)}
7068
+ active={text === "Introduction"}
5712
7069
  >
5713
- <Table.CheckCell
5714
- checked={selectedIds.has(row.id)}
5715
- onValueChange={() => toggleRow(row.id)}
5716
- aria-label={`Select ${row.subject}`}
5717
- />
5718
- <Table.Cell>
5719
- <div className="flex items-center gap-2">
5720
- <EnvelopeSimple size={16} />
5721
- <span className="truncate">{row.subject}</span>
5722
- {row.tags && (
5723
- <div className="ml-2 inline-flex gap-1">
5724
- {row.tags.map((tag) => (
5725
- <Badge key={tag}>{tag}</Badge>
5726
- ))}
5727
- </div>
5728
- )}
5729
- </div>
5730
- </Table.Cell>
5731
- <Table.Cell>
5732
- <span className="truncate">{row.from}</span>
5733
- </Table.Cell>
5734
- <Table.Cell>
5735
- <span className="truncate">{row.date}</span>
5736
- </Table.Cell>
5737
- <Table.Cell className="text-right">
5738
- <DropdownMenu>
5739
- <DropdownMenu.Trigger
5740
- render={
5741
- <Button
5742
- variant="ghost"
5743
- size="sm"
5744
- shape="square"
5745
- aria-label="More options"
5746
- >
5747
- <DotsThree weight="bold" size={16} />
5748
- </Button>
5749
- }
5750
- />
5751
- <DropdownMenu.Content>
5752
- <DropdownMenu.Item icon={Eye}>View</DropdownMenu.Item>
5753
- <DropdownMenu.Item icon={PencilSimple}>
5754
- Edit
5755
- </DropdownMenu.Item>
5756
- <DropdownMenu.Separator />
5757
- <DropdownMenu.Item icon={Trash} variant="danger">
5758
- Delete
5759
- </DropdownMenu.Item>
5760
- </DropdownMenu.Content>
5761
- </DropdownMenu>
5762
- </Table.Cell>
5763
- </Table.Row>
7070
+ {text}
7071
+ </TableOfContents.Item>
5764
7072
  ))}
5765
- </Table.Body>
5766
- </Table>
5767
- </LayerCard.Primary>
5768
- </LayerCard>
7073
+ </TableOfContents.List>
7074
+ </TableOfContents>
7075
+ {clicked && (
7076
+ <p className="text-xs text-kumo-subtle">Clicked: {clicked}</p>
7077
+ )}
7078
+ </div>
7079
+ </DemoWrapper>
5769
7080
  ```
5770
7081
 
5771
7082
 
@@ -5806,7 +7117,7 @@ Tab navigation component with segmented or underline style. Built on Base UI Tab
5806
7117
 
5807
7118
  **Colors (kumo tokens used):**
5808
7119
 
5809
- `bg-kumo-base`, `bg-kumo-brand`, `bg-kumo-recessed`, `bg-kumo-tint`, `border-kumo-hairline`, `ring-kumo-hairline`, `ring-kumo-line`, `text-kumo-default`, `text-kumo-strong`, `text-kumo-subtle`
7120
+ `bg-kumo-base`, `bg-kumo-brand`, `bg-kumo-recessed`, `bg-kumo-tint`, `border-kumo-hairline`, `ring-kumo-brand`, `ring-kumo-focus`, `ring-kumo-hairline`, `ring-kumo-line`, `text-kumo-default`, `text-kumo-strong`, `text-kumo-subtle`
5810
7121
 
5811
7122
  **Styling:**
5812
7123
 
@@ -5943,8 +7254,11 @@ Text component
5943
7254
  Whether to use bold font weight (only applies to body variants).
5944
7255
  - `truncate`: boolean
5945
7256
  Whether to truncate overflowing text with an ellipsis. Adds `truncate min-w-0` classes.
5946
- - `as`: React.ElementType
5947
- The HTML element type to render as (e.g. `"span"`, `"p"`, `"h1"`). Auto-selected based on variant if omitted.
7257
+ - `as`: enum
7258
+ 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"`.
7259
+
7260
+ - **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.
7261
+ - **Optional** for body variants (defaults to `"p"`) and monospace variants (defaults to `"span"`).
5948
7262
  - `children`: ReactNode
5949
7263
  Text content.
5950
7264
 
@@ -5959,69 +7273,75 @@ Text component
5959
7273
 
5960
7274
  ```tsx
5961
7275
  <div className="grid w-full grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3">
5962
- <div className="flex flex-col justify-end gap-1 rounded-lg border border-kumo-line bg-kumo-base p-4">
5963
- <Text variant="heading1">Heading 1</Text>
5964
- <p className="font-mono text-xs text-kumo-subtle">text-3xl (30px)</p>
7276
+ <div className="flex flex-col justify-end gap-1 rounded-lg border border-kumo-hairline bg-kumo-base p-4">
7277
+ <Text variant="heading1" as="h1">
7278
+ Heading 1
7279
+ </Text>
7280
+ <Text variant="mono-secondary">text-3xl (30px)</Text>
5965
7281
  </div>
5966
- <div className="flex flex-col justify-end gap-1 rounded-lg border border-kumo-line bg-kumo-base p-4">
5967
- <Text variant="heading2">Heading 2</Text>
5968
- <p className="font-mono text-xs text-kumo-subtle">text-2xl (24px)</p>
7282
+ <div className="flex flex-col justify-end gap-1 rounded-lg border border-kumo-hairline bg-kumo-base p-4">
7283
+ <Text variant="heading2" as="h2">
7284
+ Heading 2
7285
+ </Text>
7286
+ <Text variant="mono-secondary">text-2xl (24px)</Text>
5969
7287
  </div>
5970
- <div className="flex flex-col justify-end gap-1 rounded-lg border border-kumo-line bg-kumo-base p-4">
5971
- <Text variant="heading3">Heading 3</Text>
5972
- <p className="font-mono text-xs text-kumo-subtle">text-lg (16px)</p>
7288
+ <div className="flex flex-col justify-end gap-1 rounded-lg border border-kumo-hairline bg-kumo-base p-4">
7289
+ <Text variant="heading3" as="h3">
7290
+ Heading 3
7291
+ </Text>
7292
+ <Text variant="mono-secondary">text-lg (16px)</Text>
5973
7293
  </div>
5974
- <div className="flex flex-col justify-end gap-1 rounded-lg border border-kumo-line bg-kumo-base p-4">
7294
+ <div className="flex flex-col justify-end gap-1 rounded-lg border border-kumo-hairline bg-kumo-base p-4">
5975
7295
  <Text>Body</Text>
5976
- <p className="font-mono text-xs text-kumo-subtle">text-base (14px)</p>
7296
+ <Text variant="mono-secondary">text-base (14px)</Text>
5977
7297
  </div>
5978
- <div className="flex flex-col justify-end gap-1 rounded-lg border border-kumo-line bg-kumo-base p-4">
7298
+ <div className="flex flex-col justify-end gap-1 rounded-lg border border-kumo-hairline bg-kumo-base p-4">
5979
7299
  <Text bold>Body bold</Text>
5980
- <p className="font-mono text-xs text-kumo-subtle">text-base (14px)</p>
7300
+ <Text variant="mono-secondary">text-base (14px)</Text>
5981
7301
  </div>
5982
- <div className="flex flex-col justify-end gap-1 rounded-lg border border-kumo-line bg-kumo-base p-4">
7302
+ <div className="flex flex-col justify-end gap-1 rounded-lg border border-kumo-hairline bg-kumo-base p-4">
5983
7303
  <Text size="lg">Body lg</Text>
5984
- <p className="font-mono text-xs text-kumo-subtle">text-lg (16px)</p>
7304
+ <Text variant="mono-secondary">text-lg (16px)</Text>
5985
7305
  </div>
5986
- <div className="flex flex-col justify-end gap-1 rounded-lg border border-kumo-line bg-kumo-base p-4">
7306
+ <div className="flex flex-col justify-end gap-1 rounded-lg border border-kumo-hairline bg-kumo-base p-4">
5987
7307
  <Text size="sm">Body sm</Text>
5988
- <p className="font-mono text-xs text-kumo-subtle">text-sm (13px)</p>
7308
+ <Text variant="mono-secondary">text-sm (13px)</Text>
5989
7309
  </div>
5990
- <div className="flex flex-col justify-end gap-1 rounded-lg border border-kumo-line bg-kumo-base p-4">
7310
+ <div className="flex flex-col justify-end gap-1 rounded-lg border border-kumo-hairline bg-kumo-base p-4">
5991
7311
  <Text size="xs">Body xs</Text>
5992
- <p className="font-mono text-xs text-kumo-subtle">text-xs (12px)</p>
7312
+ <Text variant="mono-secondary">text-xs (12px)</Text>
5993
7313
  </div>
5994
- <div className="flex flex-col justify-end gap-1 rounded-lg border border-kumo-line bg-kumo-base p-4">
7314
+ <div className="flex flex-col justify-end gap-1 rounded-lg border border-kumo-hairline bg-kumo-base p-4">
5995
7315
  <Text variant="secondary">Body secondary</Text>
5996
- <p className="font-mono text-xs text-kumo-subtle">text-base (14px)</p>
7316
+ <Text variant="mono-secondary">text-base (14px)</Text>
5997
7317
  </div>
5998
- <div className="flex flex-col justify-end gap-1 rounded-lg border border-kumo-line bg-kumo-base p-4">
7318
+ <div className="flex flex-col justify-end gap-1 rounded-lg border border-kumo-hairline bg-kumo-base p-4">
5999
7319
  <Text variant="mono">Monospace</Text>
6000
- <p className="font-mono text-xs text-kumo-subtle">text-sm (13px)</p>
7320
+ <Text variant="mono-secondary">text-sm (13px)</Text>
6001
7321
  </div>
6002
- <div className="flex flex-col justify-end gap-1 rounded-lg border border-kumo-line bg-kumo-base p-4">
7322
+ <div className="flex flex-col justify-end gap-1 rounded-lg border border-kumo-hairline bg-kumo-base p-4">
6003
7323
  <Text variant="mono" size="lg">
6004
7324
  Monospace lg
6005
7325
  </Text>
6006
- <p className="font-mono text-xs text-kumo-subtle">text-base (14px)</p>
7326
+ <Text variant="mono-secondary">text-base (14px)</Text>
6007
7327
  </div>
6008
- <div className="flex flex-col justify-end gap-1 rounded-lg border border-kumo-line bg-kumo-base p-4">
7328
+ <div className="flex flex-col justify-end gap-1 rounded-lg border border-kumo-hairline bg-kumo-base p-4">
6009
7329
  <Text variant="mono-secondary">Monospace secondary</Text>
6010
- <p className="font-mono text-xs text-kumo-subtle">text-sm (13px)</p>
7330
+ <Text variant="mono-secondary">text-sm (13px)</Text>
6011
7331
  </div>
6012
- <div className="flex flex-col justify-end gap-1 rounded-lg border border-kumo-line bg-kumo-base p-4">
7332
+ <div className="flex flex-col justify-end gap-1 rounded-lg border border-kumo-hairline bg-kumo-base p-4">
6013
7333
  <Text variant="success">Success</Text>
6014
- <p className="font-mono text-xs text-kumo-subtle">text-base (14px)</p>
7334
+ <Text variant="mono-secondary">text-base (14px)</Text>
6015
7335
  </div>
6016
- <div className="flex flex-col justify-end gap-1 rounded-lg border border-kumo-line bg-kumo-base p-4">
7336
+ <div className="flex flex-col justify-end gap-1 rounded-lg border border-kumo-hairline bg-kumo-base p-4">
6017
7337
  <Text variant="error">Error</Text>
6018
- <p className="font-mono text-xs text-kumo-subtle">text-base (14px)</p>
7338
+ <Text variant="mono-secondary">text-base (14px)</Text>
6019
7339
  </div>
6020
7340
  </div>
6021
7341
  ```
6022
7342
 
6023
7343
  ```tsx
6024
- <div className="w-64 rounded-lg border border-kumo-line bg-kumo-base p-4">
7344
+ <div className="w-64 rounded-lg border border-kumo-hairline bg-kumo-base p-4">
6025
7345
  <Text truncate>
6026
7346
  This is a long piece of text that will be truncated with an ellipsis
6027
7347
  when it overflows its container.
@@ -6057,7 +7377,7 @@ Toasty — toast notification provider and viewport. Renders a `Toast.Provider`
6057
7377
 
6058
7378
  **Colors (kumo tokens used):**
6059
7379
 
6060
- `bg-kumo-base`, `bg-kumo-contrast`, `bg-kumo-control`, `bg-kumo-danger`, `bg-kumo-fill-hover`, `bg-kumo-info`, `bg-kumo-success`, `bg-kumo-warning`, `border-kumo-fill`, `ring-kumo-danger`, `ring-kumo-hairline`, `ring-kumo-info`, `ring-kumo-success`, `ring-kumo-warning`, `text-kumo-danger`, `text-kumo-default`, `text-kumo-info`, `text-kumo-strong`, `text-kumo-subtle`, `text-kumo-success`, `text-kumo-warning`
7380
+ `bg-kumo-base`, `bg-kumo-contrast`, `bg-kumo-control`, `bg-kumo-danger`, `bg-kumo-fill-hover`, `bg-kumo-info`, `bg-kumo-success`, `bg-kumo-warning`, `border-kumo-fill`, `ring-kumo-danger`, `ring-kumo-hairline`, `ring-kumo-info`, `ring-kumo-line`, `ring-kumo-success`, `ring-kumo-warning`, `text-kumo-danger`, `text-kumo-default`, `text-kumo-info`, `text-kumo-strong`, `text-kumo-subtle`, `text-kumo-success`, `text-kumo-warning`
6061
7381
 
6062
7382
  **Styling:**
6063
7383
 
@@ -6096,25 +7416,32 @@ Accessible popup that shows additional information on hover/focus. Wrap your app
6096
7416
 
6097
7417
  ```tsx
6098
7418
  <TooltipProvider>
6099
- <Tooltip content="Add new item" asChild>
6100
- <Button shape="square" icon={PlusIcon} aria-label="Add new item" />
6101
- </Tooltip>
7419
+ <Tooltip
7420
+ content="Add new item"
7421
+ render={
7422
+ <Button shape="square" icon={PlusIcon} aria-label="Add new item" />
7423
+ }
7424
+ />
6102
7425
  </TooltipProvider>
6103
7426
  ```
6104
7427
 
6105
7428
  ```tsx
6106
7429
  <TooltipProvider>
6107
7430
  <div className="flex gap-2">
6108
- <Tooltip content="Add" asChild>
6109
- <Button shape="square" icon={PlusIcon} aria-label="Add" />
6110
- </Tooltip>
6111
- <Tooltip content="Change language" asChild>
6112
- <Button
6113
- shape="square"
6114
- icon={TranslateIcon}
6115
- aria-label="Change language"
6116
- />
6117
- </Tooltip>
7431
+ <Tooltip
7432
+ content="Add"
7433
+ render={<Button shape="square" icon={PlusIcon} aria-label="Add" />}
7434
+ />
7435
+ <Tooltip
7436
+ content="Change language"
7437
+ render={
7438
+ <Button
7439
+ shape="square"
7440
+ icon={TranslateIcon}
7441
+ aria-label="Change language"
7442
+ />
7443
+ }
7444
+ />
6118
7445
  </div>
6119
7446
  </TooltipProvider>
6120
7447
  ```
@@ -6134,23 +7461,27 @@ Accessible popup that shows additional information on hover/focus. Wrap your app
6134
7461
  ```tsx
6135
7462
  <TooltipProvider>
6136
7463
  <div className="flex gap-4">
6137
- <Tooltip content="Opens after 1 second" delay={1000} asChild>
6138
- <Button variant="secondary">1s open delay</Button>
7464
+ <Tooltip
7465
+ content="Opens after 1 second"
7466
+ delay={1000}
7467
+ render={<Button variant="secondary" />}
7468
+ >
7469
+ 1s open delay
6139
7470
  </Tooltip>
6140
7471
  <Tooltip
6141
7472
  content="Stays open 500ms after leaving"
6142
7473
  closeDelay={500}
6143
- asChild
7474
+ render={<Button variant="secondary" />}
6144
7475
  >
6145
- <Button variant="secondary">500ms close delay</Button>
7476
+ 500ms close delay
6146
7477
  </Tooltip>
6147
7478
  <Tooltip
6148
7479
  content="Instant open, stays 1s"
6149
7480
  delay={0}
6150
7481
  closeDelay={1000}
6151
- asChild
7482
+ render={<Button variant="secondary" />}
6152
7483
  >
6153
- <Button variant="secondary">Instant + 1s close</Button>
7484
+ Instant + 1s close
6154
7485
  </Tooltip>
6155
7486
  </div>
6156
7487
  </TooltipProvider>
@@ -6183,11 +7514,11 @@ Multi-line textarea input with Input variants and InputArea-specific dimensions
6183
7514
  ## Quick Reference
6184
7515
 
6185
7516
  **Components by Category:**
7517
+ - **Other:** Autocomplete, CloudflareLogo, DatePicker, Label, Link, SensitiveInput, Sidebar, Table, TableOfContents, DeleteResource
6186
7518
  - **Display:** Badge, Breadcrumbs, Code, Collapsible, Empty, LayerCard, Meter, Text
6187
7519
  - **Feedback:** Banner, Loader, Toasty
6188
7520
  - **Action:** Button, ClipboardText
6189
- - **Input:** Checkbox, Combobox, DateRangePicker, Field, Input, Radio, Select, Switch
6190
- - **Other:** CloudflareLogo, DatePicker, Label, Link, SensitiveInput, Sidebar, Table, DeleteResource
7521
+ - **Input:** Checkbox, Combobox, DateRangePicker, Field, Input, InputGroup, Radio, Select, Switch
6191
7522
  - **Navigation:** CommandPalette, MenuBar, Pagination, Tabs
6192
7523
  - **Overlay:** Dialog, DropdownMenu, Popover, Tooltip
6193
7524
  - **Layout:** Grid, Surface, PageHeader, ResourceListPage