@ui-sdk/web 0.0.0-stage → 0.1.0-beta.1

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 (467) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +10 -2
  3. package/browser/web/accordion.js +1 -0
  4. package/browser/web/alert-dialog.js +1 -0
  5. package/browser/web/autocomplete.js +1 -0
  6. package/browser/web/avatar.js +1 -0
  7. package/browser/web/button.js +1 -0
  8. package/browser/web/calendar.js +1 -0
  9. package/browser/web/carousel.js +1 -0
  10. package/browser/web/checkbox.js +1 -0
  11. package/browser/web/chunks/0eRGibL6.js +1 -0
  12. package/browser/web/chunks/2bIEUO6_.js +1 -0
  13. package/browser/web/chunks/5A9w2ULz.js +1 -0
  14. package/browser/web/chunks/5RSyydjV.js +1 -0
  15. package/browser/web/chunks/9pWTy2wl.js +1 -0
  16. package/browser/web/chunks/B0f2j6zz.js +1 -0
  17. package/browser/web/chunks/B1rux6br.js +1 -0
  18. package/browser/web/chunks/B3-APaNf.js +1 -0
  19. package/browser/web/chunks/B7EgSgjQ.js +1 -0
  20. package/browser/web/chunks/B8QcOzJU.js +1 -0
  21. package/browser/web/chunks/BFueEkwm.js +3 -0
  22. package/browser/web/chunks/BJj3oS29.js +1 -0
  23. package/browser/web/chunks/BNSvTCpr.js +1 -0
  24. package/browser/web/chunks/BPD0kAZB.js +1 -0
  25. package/browser/web/chunks/BQeduZqT.js +1 -0
  26. package/browser/web/chunks/B_CVFyiz.js +1 -0
  27. package/browser/web/chunks/B_ns1YHO.js +1 -0
  28. package/browser/web/chunks/BcwkVTsR.js +1 -0
  29. package/browser/web/chunks/BeaQ6TYM.js +1 -0
  30. package/browser/web/chunks/BgBB013u.js +1 -0
  31. package/browser/web/chunks/BgsKhHDm.js +1 -0
  32. package/browser/web/chunks/BjMcbuhi.js +9 -0
  33. package/browser/web/chunks/Bjiy_F2N.js +1 -0
  34. package/browser/web/chunks/BqScCLwv.js +1 -0
  35. package/browser/web/chunks/BqX3Utqx.js +1 -0
  36. package/browser/web/chunks/BtVkQf3z.js +1 -0
  37. package/browser/web/chunks/By30h-7B.js +1 -0
  38. package/browser/web/chunks/C1zqYpy2.js +1 -0
  39. package/browser/web/chunks/C436juFf.js +1 -0
  40. package/browser/web/chunks/C4_bULs1.js +1 -0
  41. package/browser/web/chunks/C4omqJEz.js +1 -0
  42. package/browser/web/chunks/C7tt0T3n.js +1 -0
  43. package/browser/web/chunks/C8w7s5dg.js +1 -0
  44. package/browser/web/chunks/CElY4erO.js +1 -0
  45. package/browser/web/chunks/CFODo-m2.js +1 -0
  46. package/browser/web/chunks/CL4wjam9.js +1 -0
  47. package/browser/web/chunks/CMg-8UVf.js +1 -0
  48. package/browser/web/chunks/COWKfakj.js +1 -0
  49. package/browser/web/chunks/CQBU0qZ4.js +1 -0
  50. package/browser/web/chunks/CV6uABgc.js +1 -0
  51. package/browser/web/chunks/C_SWFpWQ.js +1 -0
  52. package/browser/web/chunks/C_Uanbrl.js +1 -0
  53. package/browser/web/chunks/Ce_CSanC.js +1 -0
  54. package/browser/web/chunks/Cg-ZmRhS.js +1 -0
  55. package/browser/web/chunks/Cgf2wPI_.js +1 -0
  56. package/browser/web/chunks/Cuep_3Vf.js +1 -0
  57. package/browser/web/chunks/D02PaHn6.js +1 -0
  58. package/browser/web/chunks/D5LiaI5R.js +1 -0
  59. package/browser/web/chunks/D9UgVYvF.js +1 -0
  60. package/browser/web/chunks/DC08tnkE.js +2 -0
  61. package/browser/web/chunks/DG8YGSvu.js +1 -0
  62. package/browser/web/chunks/DIQd0FYD.js +1 -0
  63. package/browser/web/chunks/DMLqacE8.js +1 -0
  64. package/browser/web/chunks/DSUI3yI-.js +1 -0
  65. package/browser/web/chunks/DT3Hb76X.js +1 -0
  66. package/browser/web/chunks/DY75g3-W.js +1 -0
  67. package/browser/web/chunks/DZpNQKZ9.js +1 -0
  68. package/browser/web/chunks/Db-W1wrC.js +1 -0
  69. package/browser/web/chunks/Dc1xK3Ii.js +1 -0
  70. package/browser/web/chunks/DdF6awFs.js +1 -0
  71. package/browser/web/chunks/DdaCLml8.js +1 -0
  72. package/browser/web/chunks/Dh8MLjQO.js +1 -0
  73. package/browser/web/chunks/DiuslJRy.js +1 -0
  74. package/browser/web/chunks/DjRcw3Y0.js +1 -0
  75. package/browser/web/chunks/Djdv-16J.js +1 -0
  76. package/browser/web/chunks/DnFXe_lF.js +1 -0
  77. package/browser/web/chunks/DneGv1oC.js +1 -0
  78. package/browser/web/chunks/DsVxP-p-.js +1 -0
  79. package/browser/web/chunks/DwDilCo2.js +1 -0
  80. package/browser/web/chunks/DwV48AXv.js +1 -0
  81. package/browser/web/chunks/F37aF4-L.js +1 -0
  82. package/browser/web/chunks/LyB6XIbN.js +1 -0
  83. package/browser/web/chunks/NKnbYGjC.js +1 -0
  84. package/browser/web/chunks/Vk-rVi16.js +1 -0
  85. package/browser/web/chunks/XsM0J1Ex.js +1 -0
  86. package/browser/web/chunks/asSN9iEp.js +1 -0
  87. package/browser/web/chunks/c-AjHfdF.js +1 -0
  88. package/browser/web/chunks/dR-12TPY.js +1 -0
  89. package/browser/web/chunks/hR4xM0EC.js +1 -0
  90. package/browser/web/chunks/hqOaBxAg.js +1 -0
  91. package/browser/web/chunks/kMKqqeG4.js +1 -0
  92. package/browser/web/chunks/kXboBcfi.js +1 -0
  93. package/browser/web/chunks/l4aQIg22.js +1 -0
  94. package/browser/web/chunks/tJC0JSU4.js +1 -0
  95. package/browser/web/chunks/wHdS_QYM.js +1 -0
  96. package/browser/web/chunks/yv8dTvNI.js +1 -0
  97. package/browser/web/chunks/yw9M3nfi.js +1 -0
  98. package/browser/web/collapsible.js +1 -0
  99. package/browser/web/color-picker.js +1 -0
  100. package/browser/web/combobox.js +2 -0
  101. package/browser/web/command.js +1 -0
  102. package/browser/web/core.js +5 -0
  103. package/browser/web/date-input.js +1 -0
  104. package/browser/web/date-picker.js +1 -0
  105. package/browser/web/dialog.js +1 -0
  106. package/browser/web/drawer.js +1 -0
  107. package/browser/web/field.js +1 -0
  108. package/browser/web/file-input.js +1 -0
  109. package/browser/web/hover-card.js +1 -0
  110. package/browser/web/image-cropper.js +1 -0
  111. package/browser/web/input.js +1 -0
  112. package/browser/web/label.js +1 -0
  113. package/browser/web/listbox.js +1 -0
  114. package/browser/web/menu.js +1 -0
  115. package/browser/web/menubar.js +1 -0
  116. package/browser/web/meter.js +1 -0
  117. package/browser/web/navigation-menu.js +1 -0
  118. package/browser/web/number-input.js +1 -0
  119. package/browser/web/otp-input.js +2 -0
  120. package/browser/web/overlays.js +1 -0
  121. package/browser/web/pagination.js +1 -0
  122. package/browser/web/password-input.js +1 -0
  123. package/browser/web/popover.js +1 -0
  124. package/browser/web/preferences.js +1 -0
  125. package/browser/web/progress.js +1 -0
  126. package/browser/web/radio.js +1 -0
  127. package/browser/web/rating.js +1 -0
  128. package/browser/web/resizable.js +1 -0
  129. package/browser/web/scroll-area.js +1 -0
  130. package/browser/web/segmented-control.js +1 -0
  131. package/browser/web/select.js +1 -0
  132. package/browser/web/separator.js +1 -0
  133. package/browser/web/slider.js +1 -0
  134. package/browser/web/switch.js +1 -0
  135. package/browser/web/tabs.js +1 -0
  136. package/browser/web/textarea.js +1 -0
  137. package/browser/web/time-input.js +1 -0
  138. package/browser/web/timeline.js +1 -0
  139. package/browser/web/toast.js +1 -0
  140. package/browser/web/toggle.js +1 -0
  141. package/browser/web/token-input.js +8 -0
  142. package/browser/web/toolbar.js +1 -0
  143. package/browser/web/tooltip.js +1 -0
  144. package/browser/web/tree.js +1 -0
  145. package/browser/web/trigger-menu.js +4 -0
  146. package/browser/web/waterfall.js +1 -0
  147. package/browser/web.css +3378 -0
  148. package/browser/web.js +3 -0
  149. package/custom-elements.json +32315 -0
  150. package/dist/accordion.d.ts +2 -0
  151. package/dist/accordion.js +57 -0
  152. package/dist/action.d.ts +16 -0
  153. package/dist/action.js +39 -0
  154. package/dist/agent.d.ts +2 -0
  155. package/dist/agent.js +7 -0
  156. package/dist/autocomplete.d.ts +2 -0
  157. package/dist/autocomplete.js +120 -0
  158. package/dist/autoload.d.ts +18 -0
  159. package/dist/autoload.js +63 -0
  160. package/dist/avatar.d.ts +2 -0
  161. package/dist/avatar.js +27 -0
  162. package/dist/browser-core.d.ts +2 -0
  163. package/dist/browser-core.js +8 -0
  164. package/dist/button.d.ts +2 -0
  165. package/dist/button.js +35 -0
  166. package/dist/calendar.d.ts +23 -0
  167. package/dist/calendar.js +429 -0
  168. package/dist/carousel.d.ts +2 -0
  169. package/dist/carousel.js +54 -0
  170. package/dist/checkbox.d.ts +4 -0
  171. package/dist/checkbox.js +75 -0
  172. package/dist/collapsible.d.ts +2 -0
  173. package/dist/collapsible.js +28 -0
  174. package/dist/color-picker.d.ts +2 -0
  175. package/dist/color-picker.js +64 -0
  176. package/dist/combobox.d.ts +2 -0
  177. package/dist/combobox.js +334 -0
  178. package/dist/command.d.ts +2 -0
  179. package/dist/command.js +122 -0
  180. package/dist/date-input.d.ts +3 -0
  181. package/dist/date-input.js +87 -0
  182. package/dist/date-picker.d.ts +2 -0
  183. package/dist/date-picker.js +174 -0
  184. package/dist/default-text.d.ts +3 -0
  185. package/dist/default-text.js +24 -0
  186. package/dist/define-element.d.ts +404 -0
  187. package/dist/define-element.js +1489 -0
  188. package/dist/dialog.d.ts +3 -0
  189. package/dist/dialog.js +94 -0
  190. package/dist/drawer.d.ts +2 -0
  191. package/dist/drawer.js +96 -0
  192. package/dist/entries/accordion.d.ts +3 -0
  193. package/dist/entries/accordion.js +7 -0
  194. package/dist/entries/alert-dialog.d.ts +3 -0
  195. package/dist/entries/alert-dialog.js +13 -0
  196. package/dist/entries/autocomplete.d.ts +3 -0
  197. package/dist/entries/autocomplete.js +7 -0
  198. package/dist/entries/avatar.d.ts +2 -0
  199. package/dist/entries/avatar.js +3 -0
  200. package/dist/entries/button.d.ts +2 -0
  201. package/dist/entries/button.js +3 -0
  202. package/dist/entries/calendar.d.ts +3 -0
  203. package/dist/entries/calendar.js +7 -0
  204. package/dist/entries/carousel.d.ts +3 -0
  205. package/dist/entries/carousel.js +7 -0
  206. package/dist/entries/checkbox.d.ts +3 -0
  207. package/dist/entries/checkbox.js +15 -0
  208. package/dist/entries/collapsible.d.ts +3 -0
  209. package/dist/entries/collapsible.js +7 -0
  210. package/dist/entries/color-picker.d.ts +3 -0
  211. package/dist/entries/color-picker.js +7 -0
  212. package/dist/entries/combobox.d.ts +3 -0
  213. package/dist/entries/combobox.js +7 -0
  214. package/dist/entries/command.d.ts +3 -0
  215. package/dist/entries/command.js +7 -0
  216. package/dist/entries/date-input.d.ts +3 -0
  217. package/dist/entries/date-input.js +7 -0
  218. package/dist/entries/date-picker.d.ts +3 -0
  219. package/dist/entries/date-picker.js +7 -0
  220. package/dist/entries/dialog.d.ts +3 -0
  221. package/dist/entries/dialog.js +7 -0
  222. package/dist/entries/drawer.d.ts +3 -0
  223. package/dist/entries/drawer.js +8 -0
  224. package/dist/entries/field.d.ts +2 -0
  225. package/dist/entries/field.js +3 -0
  226. package/dist/entries/file-input.d.ts +3 -0
  227. package/dist/entries/file-input.js +13 -0
  228. package/dist/entries/hover-card.d.ts +3 -0
  229. package/dist/entries/hover-card.js +7 -0
  230. package/dist/entries/image-cropper.d.ts +3 -0
  231. package/dist/entries/image-cropper.js +7 -0
  232. package/dist/entries/input.d.ts +3 -0
  233. package/dist/entries/input.js +8 -0
  234. package/dist/entries/label.d.ts +2 -0
  235. package/dist/entries/label.js +3 -0
  236. package/dist/entries/listbox.d.ts +3 -0
  237. package/dist/entries/listbox.js +7 -0
  238. package/dist/entries/menu.d.ts +3 -0
  239. package/dist/entries/menu.js +7 -0
  240. package/dist/entries/menubar.d.ts +3 -0
  241. package/dist/entries/menubar.js +7 -0
  242. package/dist/entries/meter.d.ts +2 -0
  243. package/dist/entries/meter.js +3 -0
  244. package/dist/entries/navigation-menu.d.ts +3 -0
  245. package/dist/entries/navigation-menu.js +7 -0
  246. package/dist/entries/number-input.d.ts +3 -0
  247. package/dist/entries/number-input.js +7 -0
  248. package/dist/entries/otp-input.d.ts +3 -0
  249. package/dist/entries/otp-input.js +7 -0
  250. package/dist/entries/overlays.d.ts +2 -0
  251. package/dist/entries/overlays.js +3 -0
  252. package/dist/entries/pagination.d.ts +3 -0
  253. package/dist/entries/pagination.js +11 -0
  254. package/dist/entries/password-input.d.ts +3 -0
  255. package/dist/entries/password-input.js +7 -0
  256. package/dist/entries/popover.d.ts +3 -0
  257. package/dist/entries/popover.js +7 -0
  258. package/dist/entries/preferences.d.ts +3 -0
  259. package/dist/entries/preferences.js +13 -0
  260. package/dist/entries/progress.d.ts +2 -0
  261. package/dist/entries/progress.js +3 -0
  262. package/dist/entries/radio.d.ts +3 -0
  263. package/dist/entries/radio.js +7 -0
  264. package/dist/entries/rating.d.ts +3 -0
  265. package/dist/entries/rating.js +8 -0
  266. package/dist/entries/resizable.d.ts +3 -0
  267. package/dist/entries/resizable.js +11 -0
  268. package/dist/entries/scroll-area.d.ts +3 -0
  269. package/dist/entries/scroll-area.js +7 -0
  270. package/dist/entries/segmented-control.d.ts +3 -0
  271. package/dist/entries/segmented-control.js +7 -0
  272. package/dist/entries/select.d.ts +3 -0
  273. package/dist/entries/select.js +7 -0
  274. package/dist/entries/separator.d.ts +2 -0
  275. package/dist/entries/separator.js +3 -0
  276. package/dist/entries/slider.d.ts +3 -0
  277. package/dist/entries/slider.js +7 -0
  278. package/dist/entries/switch.d.ts +3 -0
  279. package/dist/entries/switch.js +7 -0
  280. package/dist/entries/tabs.d.ts +3 -0
  281. package/dist/entries/tabs.js +7 -0
  282. package/dist/entries/textarea.d.ts +3 -0
  283. package/dist/entries/textarea.js +7 -0
  284. package/dist/entries/time-input.d.ts +3 -0
  285. package/dist/entries/time-input.js +7 -0
  286. package/dist/entries/timeline.d.ts +3 -0
  287. package/dist/entries/timeline.js +7 -0
  288. package/dist/entries/toast.d.ts +2 -0
  289. package/dist/entries/toast.js +3 -0
  290. package/dist/entries/toggle.d.ts +3 -0
  291. package/dist/entries/toggle.js +12 -0
  292. package/dist/entries/token-input.d.ts +3 -0
  293. package/dist/entries/token-input.js +17 -0
  294. package/dist/entries/toolbar.d.ts +3 -0
  295. package/dist/entries/toolbar.js +7 -0
  296. package/dist/entries/tooltip.d.ts +3 -0
  297. package/dist/entries/tooltip.js +7 -0
  298. package/dist/entries/tree.d.ts +3 -0
  299. package/dist/entries/tree.js +17 -0
  300. package/dist/entries/trigger-menu.d.ts +3 -0
  301. package/dist/entries/trigger-menu.js +11 -0
  302. package/dist/entries/waterfall.d.ts +3 -0
  303. package/dist/entries/waterfall.js +11 -0
  304. package/dist/events.d.ts +1658 -0
  305. package/dist/events.js +0 -0
  306. package/dist/field.d.ts +2 -0
  307. package/dist/field.js +101 -0
  308. package/dist/file-input.d.ts +2 -0
  309. package/dist/file-input.js +140 -0
  310. package/dist/forward-attributes.d.ts +2 -0
  311. package/dist/forward-attributes.js +22 -0
  312. package/dist/history.d.ts +2 -0
  313. package/dist/history.js +11 -0
  314. package/dist/hover-card.d.ts +2 -0
  315. package/dist/hover-card.js +31 -0
  316. package/dist/image-cropper.d.ts +2 -0
  317. package/dist/image-cropper.js +66 -0
  318. package/dist/index.d.ts +66 -0
  319. package/dist/index.js +269 -0
  320. package/dist/input.d.ts +3 -0
  321. package/dist/input.js +69 -0
  322. package/dist/label.d.ts +2 -0
  323. package/dist/label.js +11 -0
  324. package/dist/list.d.ts +40 -0
  325. package/dist/list.js +192 -0
  326. package/dist/listbox.d.ts +2 -0
  327. package/dist/listbox.js +84 -0
  328. package/dist/menu.d.ts +4 -0
  329. package/dist/menu.js +295 -0
  330. package/dist/menubar.d.ts +4 -0
  331. package/dist/menubar.js +30 -0
  332. package/dist/meter.d.ts +2 -0
  333. package/dist/meter.js +22 -0
  334. package/dist/navigation-menu.d.ts +2 -0
  335. package/dist/navigation-menu.js +114 -0
  336. package/dist/number-input.d.ts +2 -0
  337. package/dist/number-input.js +73 -0
  338. package/dist/observe.d.ts +2 -0
  339. package/dist/observe.js +7 -0
  340. package/dist/otp-input.d.ts +2 -0
  341. package/dist/otp-input.js +72 -0
  342. package/dist/overlays.d.ts +13 -0
  343. package/dist/overlays.js +156 -0
  344. package/dist/pagination.d.ts +2 -0
  345. package/dist/pagination.js +127 -0
  346. package/dist/password-input.d.ts +2 -0
  347. package/dist/password-input.js +57 -0
  348. package/dist/popover.d.ts +2 -0
  349. package/dist/popover.js +64 -0
  350. package/dist/popup.d.ts +40 -0
  351. package/dist/popup.js +112 -0
  352. package/dist/preferences.d.ts +2 -0
  353. package/dist/preferences.js +56 -0
  354. package/dist/progress.d.ts +2 -0
  355. package/dist/progress.js +22 -0
  356. package/dist/radio.d.ts +2 -0
  357. package/dist/radio.js +33 -0
  358. package/dist/rating.d.ts +2 -0
  359. package/dist/rating.js +64 -0
  360. package/dist/resizable.d.ts +2 -0
  361. package/dist/resizable.js +42 -0
  362. package/dist/scroll-area.d.ts +2 -0
  363. package/dist/scroll-area.js +45 -0
  364. package/dist/segmented-control.d.ts +2 -0
  365. package/dist/segmented-control.js +28 -0
  366. package/dist/select.d.ts +2 -0
  367. package/dist/select.js +239 -0
  368. package/dist/separator.d.ts +2 -0
  369. package/dist/separator.js +11 -0
  370. package/dist/slider.d.ts +2 -0
  371. package/dist/slider.js +77 -0
  372. package/dist/tabs.d.ts +2 -0
  373. package/dist/tabs.js +37 -0
  374. package/dist/timeline.d.ts +2 -0
  375. package/dist/timeline.js +27 -0
  376. package/dist/toast.d.ts +20 -0
  377. package/dist/toast.js +177 -0
  378. package/dist/toggle.d.ts +3 -0
  379. package/dist/toggle.js +64 -0
  380. package/dist/token-input.d.ts +2 -0
  381. package/dist/token-input.js +103 -0
  382. package/dist/toolbar.d.ts +2 -0
  383. package/dist/toolbar.js +36 -0
  384. package/dist/tooltip.d.ts +2 -0
  385. package/dist/tooltip.js +35 -0
  386. package/dist/tree.d.ts +2 -0
  387. package/dist/tree.js +147 -0
  388. package/dist/trigger-menu.d.ts +2 -0
  389. package/dist/trigger-menu.js +133 -0
  390. package/dist/waterfall.d.ts +2 -0
  391. package/dist/waterfall.js +140 -0
  392. package/docs/README.md +89 -0
  393. package/docs/agents.md +1523 -0
  394. package/docs/components/accordion.md +1401 -0
  395. package/docs/components/alert-dialog.md +788 -0
  396. package/docs/components/autocomplete.md +1692 -0
  397. package/docs/components/avatar.md +261 -0
  398. package/docs/components/button.md +441 -0
  399. package/docs/components/calendar.md +1536 -0
  400. package/docs/components/carousel.md +1055 -0
  401. package/docs/components/checkbox.md +1045 -0
  402. package/docs/components/collapsible.md +535 -0
  403. package/docs/components/color-picker.md +651 -0
  404. package/docs/components/combobox.md +3274 -0
  405. package/docs/components/command.md +1431 -0
  406. package/docs/components/date-input.md +563 -0
  407. package/docs/components/date-picker.md +1136 -0
  408. package/docs/components/dialog.md +1360 -0
  409. package/docs/components/drawer.md +1201 -0
  410. package/docs/components/field.md +519 -0
  411. package/docs/components/file-input.md +617 -0
  412. package/docs/components/hover-card.md +486 -0
  413. package/docs/components/image-cropper.md +489 -0
  414. package/docs/components/input.md +327 -0
  415. package/docs/components/label.md +208 -0
  416. package/docs/components/listbox.md +1015 -0
  417. package/docs/components/menu.md +1212 -0
  418. package/docs/components/menubar.md +460 -0
  419. package/docs/components/meter.md +298 -0
  420. package/docs/components/navigation-menu.md +1573 -0
  421. package/docs/components/number-input.md +1087 -0
  422. package/docs/components/otp-input.md +558 -0
  423. package/docs/components/pagination.md +639 -0
  424. package/docs/components/password-input.md +649 -0
  425. package/docs/components/popover.md +1433 -0
  426. package/docs/components/preferences.md +243 -0
  427. package/docs/components/progress.md +406 -0
  428. package/docs/components/radio.md +855 -0
  429. package/docs/components/rating.md +431 -0
  430. package/docs/components/resizable.md +866 -0
  431. package/docs/components/scroll-area.md +898 -0
  432. package/docs/components/segmented-control.md +421 -0
  433. package/docs/components/select.md +1957 -0
  434. package/docs/components/separator.md +238 -0
  435. package/docs/components/slider.md +1018 -0
  436. package/docs/components/switch.md +583 -0
  437. package/docs/components/tabs.md +948 -0
  438. package/docs/components/textarea.md +331 -0
  439. package/docs/components/time-input.md +235 -0
  440. package/docs/components/timeline.md +622 -0
  441. package/docs/components/toast.md +1223 -0
  442. package/docs/components/toggle.md +522 -0
  443. package/docs/components/token-input.md +854 -0
  444. package/docs/components/toolbar.md +815 -0
  445. package/docs/components/tooltip.md +860 -0
  446. package/docs/components/tree.md +1243 -0
  447. package/docs/components/trigger-menu.md +1110 -0
  448. package/docs/components/waterfall.md +709 -0
  449. package/docs/controllers.md +66 -0
  450. package/docs/core.md +8027 -0
  451. package/docs/custom-parts.md +91 -0
  452. package/docs/first-component.md +88 -0
  453. package/docs/forms.md +125 -0
  454. package/docs/installation.md +141 -0
  455. package/docs/introduction.md +32 -0
  456. package/docs/lists-and-menus.md +166 -0
  457. package/docs/llms.txt +1566 -0
  458. package/docs/parts-and-composition.md +57 -0
  459. package/docs/popups.md +92 -0
  460. package/docs/rendering.md +71 -0
  461. package/docs/server-rendering.md +118 -0
  462. package/docs/state-and-events.md +134 -0
  463. package/docs/styling-and-animation.md +104 -0
  464. package/docs/utilities/async-options.md +332 -0
  465. package/docs/utilities/shortcuts.md +184 -0
  466. package/html-custom-data.json +14792 -0
  467. package/package.json +302 -3
@@ -0,0 +1,815 @@
1
+ # Toolbar
2
+
3
+ Give buttons, toggles, menus and fields one tab stop with arrow-key navigation.
4
+
5
+ Use a Toolbar to group the controls of an editor, a canvas or a table. Tab enters it once, and the arrow keys move between its buttons, toggles, menus and fields.
6
+
7
+ ```ts title="demo.ts"
8
+ import "@ui-sdk/web/toolbar"
9
+ import "@ui-sdk/web/toggle"
10
+ import { Bold, createElement, Italic, Link, Underline } from "lucide"
11
+ import { log } from "./log"
12
+
13
+ const styles = [
14
+ { label: "Bold", icon: Bold },
15
+ { label: "Italic", icon: Italic },
16
+ { label: "Underline", icon: Underline },
17
+ ]
18
+
19
+ function mount(root: HTMLElement) {
20
+ root.innerHTML = `
21
+ <ui-toolbar aria-label="Formatting">
22
+ ${styles
23
+ .map(
24
+ (style) => `
25
+ <ui-toggle>
26
+ <button aria-label="${style.label}">
27
+ <ui-toggle-icon>${createElement(style.icon, { "aria-hidden": "true" }).outerHTML}</ui-toggle-icon>
28
+ </button>
29
+ </ui-toggle>
30
+ `
31
+ )
32
+ .join("")}
33
+ <ui-toolbar-separator></ui-toolbar-separator>
34
+ <ui-toolbar-button>
35
+ <button aria-label="Insert link">
36
+ ${createElement(Link, { "aria-hidden": "true" }).outerHTML}
37
+ </button>
38
+ </ui-toolbar-button>
39
+ </ui-toolbar>
40
+ `
41
+ root.querySelectorAll("ui-toggle").forEach((toggle, index) => {
42
+ const { label } = styles[index]
43
+ toggle.addEventListener("pressedchange", (event) =>
44
+ log(root, `${label} ${event.detail.value ? "on" : "off"}`)
45
+ )
46
+ })
47
+ root
48
+ .querySelector('[aria-label="Insert link"]')!
49
+ .addEventListener("click", () => log(root, "Insert link"))
50
+ }
51
+
52
+ export { mount }
53
+ ```
54
+
55
+ Tab into the toolbar, then use Left and Right to move between Bold, Italic, Underline and Insert link. Press Space to toggle the focused style. The console logs each change.
56
+
57
+ ## Installation
58
+
59
+ ```bash
60
+ npm install @ui-sdk/web @ui-sdk/core
61
+ ```
62
+
63
+ Importing the component defines its elements. Import the toggle, menu, select or number input too if you put one inside. On the server the import does nothing.
64
+
65
+ ```ts
66
+ import "@ui-sdk/web/toolbar"
67
+ ```
68
+
69
+ ## Composition
70
+
71
+ Use the following composition to build a `ui-toolbar`:
72
+
73
+ ```text
74
+ ui-toolbar
75
+ ├── ui-toolbar-button
76
+ │ └── button
77
+ ├── ui-toolbar-separator
78
+ ├── ui-toolbar-group
79
+ │ ├── ui-toolbar-button
80
+ │ │ └── button
81
+ │ └── ui-toolbar-button
82
+ │ └── button
83
+ ├── ui-toolbar-link
84
+ │ └── a
85
+ └── ui-toolbar-input
86
+ └── input
87
+ ```
88
+
89
+ Put buttons, links and fields straight inside the toolbar, each in its part: a native `button` in `ui-toolbar-button`, a link in `ui-toolbar-link` and an `input` in `ui-toolbar-input`. `ui-toolbar-group` names a set of related items, and `ui-toolbar-separator` draws a line between sets. Toggles and toggle groups join the toolbar on their own, and menu and select triggers join through `ui-toolbar-button`.
90
+
91
+ ## Usage
92
+
93
+ Import the parts and put them together:
94
+
95
+ ```html
96
+ <script type="module">
97
+ import "@ui-sdk/web/toolbar"
98
+ </script>
99
+
100
+ <ui-toolbar aria-label="Formatting">
101
+ <ui-toolbar-button><button>Undo</button></ui-toolbar-button>
102
+ <ui-toolbar-button><button>Redo</button></ui-toolbar-button>
103
+ <ui-toolbar-separator></ui-toolbar-separator>
104
+ <ui-toolbar-button><button>Insert Link</button></ui-toolbar-button>
105
+ </ui-toolbar>
106
+ ```
107
+
108
+ Name the toolbar with `aria-label`, and give every icon-only control its own.
109
+
110
+ ## Toggle Groups
111
+
112
+ A [Toggle](./toggle.md) group inside a toolbar joins its navigation instead of adding another tab stop. Arrow keys move focus without pressing anything; Enter or Space presses the focused toggle.
113
+
114
+ ```ts title="toggle-group.ts"
115
+ import "@ui-sdk/web/toolbar"
116
+ import "@ui-sdk/web/toggle"
117
+ import {
118
+ AlignCenter,
119
+ AlignLeft,
120
+ AlignRight,
121
+ createElement,
122
+ List,
123
+ ListOrdered,
124
+ } from "lucide"
125
+ import { log } from "./log"
126
+
127
+ const alignments = [
128
+ { value: "left", label: "Align left", icon: AlignLeft },
129
+ { value: "center", label: "Align center", icon: AlignCenter },
130
+ { value: "right", label: "Align right", icon: AlignRight },
131
+ ]
132
+
133
+ const lists = [
134
+ { value: "bulleted", label: "Bulleted list", icon: List },
135
+ { value: "numbered", label: "Numbered list", icon: ListOrdered },
136
+ ]
137
+
138
+ const toggles = (items: typeof alignments) =>
139
+ items
140
+ .map(
141
+ (item) => `
142
+ <ui-toggle value="${item.value}">
143
+ <button aria-label="${item.label}">
144
+ <ui-toggle-icon>${createElement(item.icon, { "aria-hidden": "true" }).outerHTML}</ui-toggle-icon>
145
+ </button>
146
+ </ui-toggle>
147
+ `
148
+ )
149
+ .join("")
150
+
151
+ function mount(root: HTMLElement) {
152
+ root.innerHTML = `
153
+ <ui-toolbar aria-label="Paragraph">
154
+ <ui-toggle-group default-value="left" deselectable="false" aria-label="Alignment">
155
+ ${toggles(alignments)}
156
+ </ui-toggle-group>
157
+ <ui-toolbar-separator></ui-toolbar-separator>
158
+ <ui-toggle-group aria-label="List">
159
+ ${toggles(lists)}
160
+ </ui-toggle-group>
161
+ </ui-toolbar>
162
+ `
163
+ const [alignment, list] = root.querySelectorAll("ui-toggle-group")
164
+ alignment.addEventListener("valuechange", (event) =>
165
+ log(root, `Align ${event.detail.value[0]}`)
166
+ )
167
+ list.addEventListener("valuechange", (event) => {
168
+ const [value] = event.detail.value
169
+ log(root, lists.find((list) => list.value === value)?.label ?? "No list")
170
+ })
171
+ }
172
+
173
+ export { mount }
174
+ ```
175
+
176
+ Arrow from the alignment group to the list group, then press Space on Align center or Numbered list. The console logs each choice.
177
+
178
+ ## Groups
179
+
180
+ Use `ui-toolbar-group` to name related controls. Set `disabled` on the group to disable them together; they stay focusable with `aria-disabled`.
181
+
182
+ ```ts title="group.ts"
183
+ import "@ui-sdk/web/toolbar"
184
+ import { Clipboard, Copy, createElement, Redo, Scissors, Undo } from "lucide"
185
+ import { log } from "./log"
186
+
187
+ const clipboard = [
188
+ { label: "Cut", icon: Scissors },
189
+ { label: "Copy", icon: Copy },
190
+ { label: "Paste", icon: Clipboard },
191
+ ]
192
+
193
+ function mount(root: HTMLElement) {
194
+ root.innerHTML = `
195
+ <ui-toolbar aria-label="Edit">
196
+ <ui-toolbar-group aria-label="Clipboard">
197
+ ${clipboard
198
+ .map(
199
+ (action) => `
200
+ <ui-toolbar-button>
201
+ <button aria-label="${action.label}">
202
+ ${createElement(action.icon, { "aria-hidden": "true" }).outerHTML}
203
+ </button>
204
+ </ui-toolbar-button>
205
+ `
206
+ )
207
+ .join("")}
208
+ </ui-toolbar-group>
209
+ <ui-toolbar-separator></ui-toolbar-separator>
210
+ <ui-toolbar-group disabled aria-label="History">
211
+ <ui-toolbar-button>
212
+ <button aria-label="Undo">
213
+ ${createElement(Undo, { "aria-hidden": "true" }).outerHTML}
214
+ </button>
215
+ </ui-toolbar-button>
216
+ <ui-toolbar-button>
217
+ <button aria-label="Redo">
218
+ ${createElement(Redo, { "aria-hidden": "true" }).outerHTML}
219
+ </button>
220
+ </ui-toolbar-button>
221
+ </ui-toolbar-group>
222
+ </ui-toolbar>
223
+ `
224
+ root
225
+ .querySelectorAll('[aria-label="Clipboard"] button')
226
+ .forEach((button, index) => {
227
+ button.addEventListener("click", () => log(root, clipboard[index].label))
228
+ })
229
+ }
230
+
231
+ export { mount }
232
+ ```
233
+
234
+ Move through Cut, Copy and Paste into History with the arrow keys. Undo and Redo stay focusable but do nothing.
235
+
236
+ ## Menus
237
+
238
+ Wrap a [Menu](./menu.md) trigger in `ui-toolbar-button`. In a horizontal toolbar, Down opens the menu while Left and Right keep moving between toolbar items.
239
+
240
+ ```html
241
+ <ui-menu>
242
+ <ui-toolbar-button>
243
+ <ui-menu-trigger><button>Share</button></ui-menu-trigger>
244
+ </ui-toolbar-button>
245
+ <ui-menu-content>…</ui-menu-content>
246
+ </ui-menu>
247
+ ```
248
+
249
+ ```ts title="menu.ts"
250
+ import "@ui-sdk/web/toolbar"
251
+ import "@ui-sdk/web/menu"
252
+ import { ChevronDown, createElement } from "lucide"
253
+ import { log } from "./log"
254
+
255
+ function mount(root: HTMLElement) {
256
+ root.innerHTML = `
257
+ <ui-toolbar aria-label="Document">
258
+ <ui-toolbar-button>
259
+ <button data-action="save">Save</button>
260
+ </ui-toolbar-button>
261
+ <ui-menu>
262
+ <ui-toolbar-button>
263
+ <ui-menu-trigger>
264
+ <button>
265
+ Share
266
+ ${createElement(ChevronDown, { "aria-hidden": "true" }).outerHTML}
267
+ </button>
268
+ </ui-menu-trigger>
269
+ </ui-toolbar-button>
270
+ <ui-menu-content>
271
+ <ui-menu-item value="email">Email</ui-menu-item>
272
+ <ui-menu-item value="link">Copy Link</ui-menu-item>
273
+ </ui-menu-content>
274
+ </ui-menu>
275
+ <ui-toolbar-button>
276
+ <button data-action="print">Print</button>
277
+ </ui-toolbar-button>
278
+ </ui-toolbar>
279
+ `
280
+ root
281
+ .querySelector("[data-action=save]")!
282
+ .addEventListener("click", () => log(root, "Saved"))
283
+ root
284
+ .querySelector("ui-menu")!
285
+ .addEventListener("action", (event) =>
286
+ log(root, `Shared by ${event.detail.value}`)
287
+ )
288
+ root
289
+ .querySelector("[data-action=print]")!
290
+ .addEventListener("click", () => log(root, "Printed"))
291
+ }
292
+
293
+ export { mount }
294
+ ```
295
+
296
+ Focus Share and press Down, then choose Email or Copy Link. Escape closes the menu and returns focus to Share.
297
+
298
+ ## Selects
299
+
300
+ A [Select](./select.md) trigger joins the same way. It keeps its select behavior while it takes part in the toolbar's focus order.
301
+
302
+ ```ts title="select.ts"
303
+ import "@ui-sdk/web/toolbar"
304
+ import "@ui-sdk/web/select"
305
+ import { Check, ChevronsUpDown, createElement, ZoomIn, ZoomOut } from "lucide"
306
+ import { log } from "./log"
307
+
308
+ const zooms = ["50%", "75%", "100%", "150%", "200%"]
309
+
310
+ function mount(root: HTMLElement) {
311
+ root.innerHTML = `
312
+ <ui-toolbar aria-label="View">
313
+ <ui-toolbar-button data-action="zoom-out">
314
+ <button aria-label="Zoom out">
315
+ ${createElement(ZoomOut, { "aria-hidden": "true" }).outerHTML}
316
+ </button>
317
+ </ui-toolbar-button>
318
+ <ui-select default-value="100%">
319
+ <ui-toolbar-button>
320
+ <ui-select-trigger>
321
+ <button aria-label="Zoom">
322
+ <ui-select-value></ui-select-value>
323
+ ${createElement(ChevronsUpDown, { "aria-hidden": "true" }).outerHTML}
324
+ </button>
325
+ </ui-select-trigger>
326
+ </ui-toolbar-button>
327
+ <ui-select-content>
328
+ ${zooms
329
+ .map(
330
+ (zoom) => `
331
+ <ui-select-item value="${zoom}">
332
+ ${zoom}
333
+ <ui-select-item-indicator>${createElement(Check, { "aria-hidden": "true" }).outerHTML}</ui-select-item-indicator>
334
+ </ui-select-item>
335
+ `
336
+ )
337
+ .join("")}
338
+ </ui-select-content>
339
+ </ui-select>
340
+ <ui-toolbar-button data-action="zoom-in">
341
+ <button aria-label="Zoom in">
342
+ ${createElement(ZoomIn, { "aria-hidden": "true" }).outerHTML}
343
+ </button>
344
+ </ui-toolbar-button>
345
+ </ui-toolbar>
346
+ `
347
+ const select = root.querySelector("ui-select")!
348
+ const zoomOut = root.querySelector("[data-action=zoom-out]")!
349
+ const zoomIn = root.querySelector("[data-action=zoom-in]")!
350
+ const change = (value: string) => {
351
+ const index = zooms.indexOf(value)
352
+ zoomOut.toggleAttribute("disabled", index === 0)
353
+ zoomIn.toggleAttribute("disabled", index === zooms.length - 1)
354
+ log(root, `Zoom ${value}`)
355
+ }
356
+ const step = (by: number) => {
357
+ const value = zooms[zooms.indexOf(select.value as string) + by]
358
+ select.value = value
359
+ change(value)
360
+ }
361
+ zoomOut.addEventListener("click", () => step(-1))
362
+ zoomIn.addEventListener("click", () => step(1))
363
+ select.addEventListener("valuechange", (event) => {
364
+ const value = event.detail.value as string | null
365
+ if (value) {
366
+ change(value)
367
+ }
368
+ })
369
+ }
370
+
371
+ export { mount }
372
+ ```
373
+
374
+ Open Zoom and choose a value, or step it with Zoom out and Zoom in. Each button turns off at the end of the range.
375
+
376
+ ## Fields
377
+
378
+ Wrap a text field in `ui-toolbar-input`, or another field's control, like a [Number Input](./number-input.md) control. A field keeps Home, End and the arrow keys while they move its caret. At the matching end, with no text selected, an arrow moves to the next item.
379
+
380
+ Entering a field with an arrow puts its caret at the far end in that direction: press the same arrow again to leave, or the other arrow to edit. A number input keeps Up and Down for stepping its value.
381
+
382
+ ```ts title="input.ts"
383
+ import "@ui-sdk/web/toolbar"
384
+ import "@ui-sdk/web/number-input"
385
+ import { createElement, Minus, Plus } from "lucide"
386
+
387
+ function mount(root: HTMLElement) {
388
+ root.innerHTML = `
389
+ <ui-toolbar aria-label="Text">
390
+ <ui-number-input default-value="14" min="8" max="72">
391
+ <ui-number-input-group>
392
+ <ui-number-input-decrement>
393
+ <button aria-label="Decrease font size">
394
+ ${createElement(Minus, { "aria-hidden": "true" }).outerHTML}
395
+ </button>
396
+ </ui-number-input-decrement>
397
+ <ui-toolbar-input>
398
+ <ui-number-input-control>
399
+ <input aria-label="Font size" />
400
+ </ui-number-input-control>
401
+ </ui-toolbar-input>
402
+ <ui-number-input-increment>
403
+ <button aria-label="Increase font size">
404
+ ${createElement(Plus, { "aria-hidden": "true" }).outerHTML}
405
+ </button>
406
+ </ui-number-input-increment>
407
+ </ui-number-input-group>
408
+ </ui-number-input>
409
+ <ui-toolbar-separator></ui-toolbar-separator>
410
+ <ui-toolbar-input>
411
+ <input aria-label="Find" placeholder="Find…" />
412
+ </ui-toolbar-input>
413
+ </ui-toolbar>
414
+ `
415
+ }
416
+
417
+ export { mount }
418
+ ```
419
+
420
+ Move into Font size and press Up or Down to change it. In Find, type a word, then move the caret to an edge before that arrow leaves the field.
421
+
422
+ ## Links
423
+
424
+ `ui-toolbar-link` joins the same focus order and keeps its link behavior. The demo handles a plain click itself and leaves modified clicks, like opening in a new tab, to the browser.
425
+
426
+ ```ts title="link.ts"
427
+ import "@ui-sdk/web/toolbar"
428
+ import { Check, createElement, MessageSquare } from "lucide"
429
+ import { log } from "./log"
430
+
431
+ function mount(root: HTMLElement) {
432
+ root.innerHTML = `
433
+ <ui-toolbar aria-label="Pull request">
434
+ <ui-toolbar-button>
435
+ <button aria-label="Approve">
436
+ ${createElement(Check, { "aria-hidden": "true" }).outerHTML}
437
+ </button>
438
+ </ui-toolbar-button>
439
+ <ui-toolbar-button>
440
+ <button aria-label="Comment">
441
+ ${createElement(MessageSquare, { "aria-hidden": "true" }).outerHTML}
442
+ </button>
443
+ </ui-toolbar-button>
444
+ <ui-toolbar-separator></ui-toolbar-separator>
445
+ <ui-toolbar-link>
446
+ <a href="#files">Files Changed</a>
447
+ </ui-toolbar-link>
448
+ <ui-toolbar-link>
449
+ <a href="#checks">Checks</a>
450
+ </ui-toolbar-link>
451
+ </ui-toolbar>
452
+ `
453
+ root
454
+ .querySelector('[aria-label="Approve"]')!
455
+ .addEventListener("click", () => log(root, "Approved"))
456
+ root
457
+ .querySelector('[aria-label="Comment"]')!
458
+ .addEventListener("click", () => log(root, "Comment"))
459
+ for (const link of root.querySelectorAll("a")) {
460
+ link.addEventListener("click", (event) => {
461
+ if (
462
+ event.button !== 0 ||
463
+ event.metaKey ||
464
+ event.ctrlKey ||
465
+ event.shiftKey ||
466
+ event.altKey
467
+ ) {
468
+ return
469
+ }
470
+ event.preventDefault()
471
+ log(root, `Opened ${link.textContent}`)
472
+ })
473
+ }
474
+ }
475
+
476
+ export { mount }
477
+ ```
478
+
479
+ Arrow to Files Changed and press Enter. The console logs the page it opened.
480
+
481
+ ## Vertical
482
+
483
+ Set `orientation="vertical"` to move with Up and Down, like a canvas tool palette. Separators turn to run across the toolbar.
484
+
485
+ ```ts title="vertical.ts"
486
+ import "@ui-sdk/web/toolbar"
487
+ import "@ui-sdk/web/toggle"
488
+ import {
489
+ createElement,
490
+ MousePointer2,
491
+ Pencil,
492
+ Square,
493
+ Trash2,
494
+ Type,
495
+ } from "lucide"
496
+ import { log } from "./log"
497
+
498
+ const tools = [
499
+ { value: "select", label: "Select", icon: MousePointer2 },
500
+ { value: "draw", label: "Draw", icon: Pencil },
501
+ { value: "shape", label: "Shape", icon: Square },
502
+ { value: "text", label: "Text", icon: Type },
503
+ ]
504
+
505
+ function mount(root: HTMLElement) {
506
+ root.innerHTML = `
507
+ <ui-toolbar orientation="vertical" aria-label="Canvas">
508
+ <ui-toggle-group default-value="select" deselectable="false" orientation="vertical" aria-label="Tool">
509
+ ${tools
510
+ .map(
511
+ (tool) => `
512
+ <ui-toggle value="${tool.value}">
513
+ <button aria-label="${tool.label}">
514
+ <ui-toggle-icon>${createElement(tool.icon, { "aria-hidden": "true" }).outerHTML}</ui-toggle-icon>
515
+ </button>
516
+ </ui-toggle>
517
+ `
518
+ )
519
+ .join("")}
520
+ </ui-toggle-group>
521
+ <ui-toolbar-separator></ui-toolbar-separator>
522
+ <ui-toolbar-button>
523
+ <button aria-label="Delete">
524
+ ${createElement(Trash2, { "aria-hidden": "true" }).outerHTML}
525
+ </button>
526
+ </ui-toolbar-button>
527
+ </ui-toolbar>
528
+ `
529
+ root
530
+ .querySelector("ui-toggle-group")!
531
+ .addEventListener("valuechange", (event) => {
532
+ const [value] = event.detail.value
533
+ log(root, `${tools.find((tool) => tool.value === value)?.label} tool`)
534
+ })
535
+ root
536
+ .querySelector('[aria-label="Delete"]')!
537
+ .addEventListener("click", () => log(root, "Deleted selection"))
538
+ }
539
+
540
+ export { mount }
541
+ ```
542
+
543
+ Use Up and Down to move between the tools and Delete. Space picks the focused tool.
544
+
545
+ ## Disabled
546
+
547
+ A disabled item stays reachable with `aria-disabled`, so people can find it, but it ignores presses, including keys meant for a component wrapped in it. Set `focusable-when-disabled="false"` to skip it instead.
548
+
549
+ ```ts title="disabled.ts"
550
+ import "@ui-sdk/web/toolbar"
551
+ import { log } from "./log"
552
+
553
+ function mount(root: HTMLElement) {
554
+ root.innerHTML = `
555
+ <ui-toolbar aria-label="Message">
556
+ <ui-toolbar-button>
557
+ <button>Reply</button>
558
+ </ui-toolbar-button>
559
+ <ui-toolbar-button disabled>
560
+ <button>Archive</button>
561
+ </ui-toolbar-button>
562
+ <ui-toolbar-button disabled focusable-when-disabled="false">
563
+ <button>Delete</button>
564
+ </ui-toolbar-button>
565
+ </ui-toolbar>
566
+ `
567
+ for (const button of root.querySelectorAll("button")) {
568
+ button.addEventListener("click", () => log(root, button.textContent!))
569
+ }
570
+ }
571
+
572
+ export { mount }
573
+ ```
574
+
575
+ Arrow from Reply to Archive, which is disabled but focusable. Delete is skipped. Only Reply logs a press.
576
+
577
+ Set `disabled` on the toolbar to disable every item. The toolbar keeps its tab stop, and its fields can't be edited.
578
+
579
+ ```html
580
+ <ui-toolbar disabled aria-label="Formatting">
581
+ <ui-toolbar-button><button>Bold</button></ui-toolbar-button>
582
+ <ui-toolbar-input><input aria-label="Find" /></ui-toolbar-input>
583
+ </ui-toolbar>
584
+ ```
585
+
586
+ ## Loop
587
+
588
+ Arrow keys wrap from the last item to the first by default. Set `loop="false"` to stop at the ends.
589
+
590
+ ```ts title="loop.ts"
591
+ import "@ui-sdk/web/toolbar"
592
+ import { log } from "./log"
593
+
594
+ function mount(root: HTMLElement) {
595
+ root.innerHTML = `
596
+ <ui-toolbar loop="false" aria-label="Pages">
597
+ ${["First", "Previous", "Next", "Last"]
598
+ .map(
599
+ (label) => `
600
+ <ui-toolbar-button>
601
+ <button>${label}</button>
602
+ </ui-toolbar-button>
603
+ `
604
+ )
605
+ .join("")}
606
+ </ui-toolbar>
607
+ `
608
+ for (const button of root.querySelectorAll("button")) {
609
+ button.addEventListener("click", () =>
610
+ log(root, `${button.textContent} page`)
611
+ )
612
+ }
613
+ }
614
+
615
+ export { mount }
616
+ ```
617
+
618
+ Focus Last and press Right. Focus stays there; Home still moves to First.
619
+
620
+ ## Controller
621
+
622
+ The toolbar element's `api` property is its controller. Its `focus()` moves focus to the item focused last, like the Alt+F10 shortcut editors give their toolbars.
623
+
624
+ ```ts title="controller.ts"
625
+ import "@ui-sdk/web/toolbar"
626
+ import { registerShortcut } from "@ui-sdk/web"
627
+ import { Bold, createElement, Italic, Link } from "lucide"
628
+ import { log } from "./log"
629
+
630
+ const actions = [
631
+ { label: "Bold", icon: Bold },
632
+ { label: "Italic", icon: Italic },
633
+ { label: "Insert link", icon: Link },
634
+ ]
635
+
636
+ function mount(root: HTMLElement) {
637
+ root.innerHTML = `
638
+ <div data-slot="stack">
639
+ <div data-slot="controls">
640
+ <button type="button">Focus Toolbar</button>
641
+ </div>
642
+ <ui-toolbar aria-label="Notes formatting">
643
+ ${actions
644
+ .map(
645
+ (action) => `
646
+ <ui-toolbar-button>
647
+ <button aria-label="${action.label}">
648
+ ${createElement(action.icon, { "aria-hidden": "true" }).outerHTML}
649
+ </button>
650
+ </ui-toolbar-button>
651
+ `
652
+ )
653
+ .join("")}
654
+ </ui-toolbar>
655
+ <textarea aria-label="Notes" placeholder="Type, then press Alt+F10"></textarea>
656
+ </div>
657
+ `
658
+ const toolbar = root.querySelector("ui-toolbar")!
659
+ root
660
+ .querySelector('[data-slot="controls"] button')!
661
+ .addEventListener("click", () => toolbar.api.focus())
662
+ toolbar.querySelectorAll("button").forEach((button, index) => {
663
+ button.addEventListener("click", () => log(root, actions[index].label))
664
+ })
665
+ return registerShortcut("alt+f10", () => toolbar.api.focus(), {
666
+ allowInInput: true,
667
+ })
668
+ }
669
+
670
+ export { mount }
671
+ ```
672
+
673
+ Type in Notes, then press Alt+F10 or choose Focus Toolbar. Press a toolbar button and the console logs it.
674
+
675
+ ## Custom Rendering
676
+
677
+ Wrap a component's trigger or control in `ui-toolbar-button` or `ui-toolbar-input` to combine their behavior, as the menu, select and number input examples do. The toolbar part finds the native button or field inside and adds its behavior to that same element. [Parts and Composition](../parts-and-composition.md) explains the rendering contract.
678
+
679
+ ## Styling
680
+
681
+ Use `data-orientation` on the root for a row or a column, and on a separator for the way its line runs, across the toolbar. Use `data-disabled` to style unavailable items and groups. Toggles inside keep their own `data-pressed`.
682
+
683
+ Each part has a `data-slot`, such as `toolbar-button`, and its state attributes are listed under [Data Attributes](#data-attributes). An item's attributes land on its button, link or field.
684
+
685
+ ## Data Attributes
686
+
687
+ ### `<ui-toolbar>`
688
+ `[data-slot="toolbar"]`
689
+
690
+ - `data-orientation` (`horizontal`, `vertical`): The toolbar's orientation. On a separator, which way the line runs: across the toolbar.
691
+ - `data-disabled`: Present when disabled, by the item itself, its group or the toolbar.
692
+
693
+ ### `<ui-toolbar-button>`
694
+ `[data-slot="toolbar-button"]`
695
+
696
+ - `data-disabled`: Present when disabled, by the item itself, its group or the toolbar.
697
+ - `data-orientation` (`horizontal`, `vertical`): The toolbar's orientation. On a separator, which way the line runs: across the toolbar.
698
+
699
+ ### `<ui-toolbar-link>`
700
+ `[data-slot="toolbar-link"]`
701
+
702
+ - `data-disabled`: Present when disabled, by the item itself, its group or the toolbar.
703
+ - `data-orientation` (`horizontal`, `vertical`): The toolbar's orientation. On a separator, which way the line runs: across the toolbar.
704
+
705
+ ### `<ui-toolbar-input>`
706
+ `[data-slot="toolbar-input"]`
707
+
708
+ - `data-disabled`: Present when disabled, by the item itself, its group or the toolbar.
709
+ - `data-orientation` (`horizontal`, `vertical`): The toolbar's orientation. On a separator, which way the line runs: across the toolbar.
710
+
711
+ ### `<ui-toolbar-group>`
712
+ `[data-slot="toolbar-group"]`
713
+
714
+ - `data-disabled`: Present when disabled, by the item itself, its group or the toolbar.
715
+ - `data-orientation` (`horizontal`, `vertical`): The toolbar's orientation. On a separator, which way the line runs: across the toolbar.
716
+
717
+ ### `<ui-toolbar-separator>`
718
+ `[data-slot="toolbar-separator"]`
719
+
720
+ - `data-orientation` (`horizontal`, `vertical`): The toolbar's orientation. On a separator, which way the line runs: across the toolbar.
721
+
722
+ ## API Reference
723
+
724
+ Props are attributes in kebab case, like `focusable-when-disabled`: `"false"` is false, as in `loop="false"`.
725
+
726
+ ### Toolbar
727
+
728
+ - `orientation?` (`ToolbarOrientation`): Which arrow keys move between items: left and right, or up and down.
729
+ - `loop?` (`boolean`): Whether arrow keys wrap from the last item to the first.
730
+ - `disabled?` (`boolean`): Stops every item from being used. Items stay focusable with `aria-disabled`, so the toolbar keeps its tab stop and stays discoverable.
731
+ - `controller?` (`{ focus: () => void; }`): Focuses the toolbar from anywhere. Create one with `createToolbarController()`.
732
+ - `debug?` (`boolean`): Logs every state change with its reason to the console, in development builds.
733
+
734
+ ### ToolbarButton
735
+
736
+ - `disabled?` (`boolean`): Stops the item from being used. It stays focusable with `aria-disabled`, so arrow keys still reach it and a tooltip can say why.
737
+ - `focusableWhenDisabled?` (`boolean`): Whether a disabled item stays reachable with arrow keys. Turn it off to skip it, natively disabled.
738
+
739
+ ### ToolbarInput
740
+
741
+ - `disabled?` (`boolean`): Stops the item from being used. It stays focusable with `aria-disabled`, so arrow keys still reach it and a tooltip can say why.
742
+ - `focusableWhenDisabled?` (`boolean`): Whether a disabled item stays reachable with arrow keys. Turn it off to skip it, natively disabled.
743
+
744
+ ### ToolbarGroup
745
+
746
+ - `disabled?` (`boolean`): Disables every item in the group. They stay focusable with `aria-disabled`.
747
+
748
+ `ui-toolbar-link` and `ui-toolbar-separator` take no props of their own.
749
+
750
+ ### State
751
+
752
+ The same state shows as data attributes on the button inside `ui-toolbar-button`:
753
+
754
+ - `disabled` (`boolean`): Whether the item is disabled, by itself, its group or the toolbar.
755
+ - `orientation` (`ToolbarOrientation`): The toolbar's `orientation` option: `"vertical"`, or `"horizontal"` for anything else.
756
+
757
+ ### Controller
758
+
759
+ The element's `api` property has the same methods.
760
+
761
+ - `focus()` (`() => void`): Moves focus to the item that holds the toolbar's tab stop: the one focused last, or the first.
762
+
763
+ ## Accessibility
764
+
765
+ The toolbar follows the [WAI-ARIA toolbar pattern](https://www.w3.org/WAI/ARIA/apg/patterns/toolbar/). The root has the `toolbar` role and `aria-orientation`, and separators have the `separator` role.
766
+
767
+ ### Keyboard
768
+
769
+ The toolbar has one tab stop, a roving focus. Tab enters on the first enabled item, then returns to the item focused last. The next Tab leaves the toolbar.
770
+
771
+ | Key | Action |
772
+ | -------------------------- | ----------------------------------------------- |
773
+ | `ArrowRight` / `ArrowLeft` | Move focus in a horizontal toolbar |
774
+ | `ArrowDown` / `ArrowUp` | Move focus in a vertical toolbar |
775
+ | `Home` / `End` | Focus the first or last item, except in a field |
776
+ | `Enter` / `Space` | Activate a button or toggle, or open its popup |
777
+
778
+ Controls keep the keys they use: Down opens a menu, and Up and Down step a number input. Moving focus never presses a toggle. In right-to-left text, Left and Right swap.
779
+
780
+ ### Tested Behavior
781
+
782
+ Every line below is an automated test.
783
+
784
+ - The toolbar is named and has a horizontal orientation.
785
+ - Tab lands on the first item, and Tab again leaves the toolbar.
786
+ - Shift+Tab from after the toolbar lands on its tab stop.
787
+ - ArrowRight moves through every item, into toggle groups and out of fields.
788
+ - ArrowRight on the last item wraps to the first, and ArrowLeft back.
789
+ - Arrow keys never press a toggle, and Space and Enter do.
790
+ - Tab comes back to the item focused last.
791
+ - A toggle group in the toolbar is no tab stop of its own.
792
+ - A disabled button stays reachable, says it's disabled and does nothing.
793
+ - A button runs its action when pressed.
794
+ - A menu trigger rendered through a button opens with ArrowDown, and arrows still move past it.
795
+ - Choosing from a menu in the toolbar returns focus to its trigger.
796
+ - A text field keeps Home and End for its caret.
797
+ - Up and Down step a number field in the toolbar.
798
+ - Separators run across the toolbar.
799
+ - A group of buttons is named.
800
+ - A link in the toolbar follows its href with Enter.
801
+ - With loop off, arrows stop at the ends.
802
+ - A disabled toolbar keeps one tab stop, and every item says it's disabled.
803
+
804
+ **Vertical**
805
+
806
+ - ArrowDown and ArrowUp move between items, and Left and Right don't.
807
+ - Separators run across a vertical toolbar.
808
+
809
+ **Disabled groups**
810
+
811
+ - Toggles and toggle groups in a disabled group are disabled.
812
+ - A link in a disabled group is disabled, and follows its href once enabled.
813
+ - Enabling a group enables the toggles and buttons in it.
814
+
815
+ Runs in React, Vue and web components.