bitboss-ui 3.0.0-beta.63 → 3.0.0-beta.64

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 (377) hide show
  1. package/README.md +25 -20
  2. package/bin/bitboss-ui.mjs +73 -7
  3. package/dist/ai/BbAlert.md +10 -1
  4. package/dist/ai/BbBadge.md +35 -3
  5. package/dist/ai/BbBadgeButton.md +4 -2
  6. package/dist/ai/BbBaseButton.md +9 -3
  7. package/dist/ai/BbBreadcrumbs.md +2 -2
  8. package/dist/ai/BbButton.md +113 -8
  9. package/dist/ai/BbCheckbox.md +1 -1
  10. package/dist/ai/BbCheckboxGroup.md +94 -6
  11. package/dist/ai/BbColorInput.md +4 -1
  12. package/dist/ai/BbColorPalette.md +2 -1
  13. package/dist/ai/BbConfirm.md +7 -3
  14. package/dist/ai/BbDatePicker.md +2 -1
  15. package/dist/ai/BbDatePickerInput.md +4 -1
  16. package/dist/ai/BbDialog.md +12 -11
  17. package/dist/ai/BbDropdown.md +189 -38
  18. package/dist/ai/BbDropdownButton.md +27 -7
  19. package/dist/ai/BbForm.md +55 -22
  20. package/dist/ai/BbHost.md +2 -2
  21. package/dist/ai/BbHoverCard.md +7 -3
  22. package/dist/ai/BbIcon.md +12 -6
  23. package/dist/ai/BbIndicator.md +11 -1
  24. package/dist/ai/BbNumberInput.md +4 -1
  25. package/dist/ai/BbOffCanvas.md +37 -3
  26. package/dist/ai/BbPopover.md +2 -1
  27. package/dist/ai/BbRadio.md +1 -1
  28. package/dist/ai/BbRadioGroup.md +102 -10
  29. package/dist/ai/BbSelect.md +52 -17
  30. package/dist/ai/BbSelectPopover.md +93 -26
  31. package/dist/ai/BbSwitch.md +1 -1
  32. package/dist/ai/BbSwitchGroup.md +30 -3
  33. package/dist/ai/BbTable.md +17 -10
  34. package/dist/ai/BbTabs.md +8 -3
  35. package/dist/ai/BbTabsList.md +4 -1
  36. package/dist/ai/BbTag.md +5 -2
  37. package/dist/ai/BbTextInput.md +4 -1
  38. package/dist/ai/BbTextarea.md +4 -1
  39. package/dist/ai/BbTimePicker.md +2 -1
  40. package/dist/ai/BbTimePickerInput.md +4 -1
  41. package/dist/ai/BbToast.md +9 -3
  42. package/dist/ai/BbTooltip.md +71 -9
  43. package/dist/ai/ChipsBox.md +1 -1
  44. package/dist/ai/CommonField.md +1 -1
  45. package/dist/ai/OptionsContainer.md +42 -0
  46. package/dist/ai/changelog.json +416 -6
  47. package/dist/ai/components.json +50 -48
  48. package/dist/ai/composables/useConfirm.md +39 -1
  49. package/dist/ai/design-tokens.json +6 -6
  50. package/dist/ai/guides/agent-contract.md +2 -2
  51. package/dist/ai/guides/ai-router.md +24 -23
  52. package/dist/ai/guides/app-layout.md +5 -0
  53. package/dist/ai/guides/component-picker.md +9 -2
  54. package/dist/ai/guides/design-language.md +24 -24
  55. package/dist/ai/guides/design-tokens.md +15 -8
  56. package/dist/ai/guides/icons-policy.md +9 -2
  57. package/dist/ai/guides/inertia-helpers.md +79 -49
  58. package/dist/ai/guides/installation-and-plugin-setup.md +12 -2
  59. package/dist/ai/guides/migration/adoption-checklist.md +235 -0
  60. package/dist/ai/guides/migration/components/bb-checkbox-group.md +16 -15
  61. package/dist/ai/guides/migration/components/bb-dialog.md +9 -9
  62. package/dist/ai/guides/migration/components/bb-dropdown.md +7 -2
  63. package/dist/ai/guides/migration/components/bb-popover.md +4 -2
  64. package/dist/ai/guides/migration/components/bb-select.md +19 -0
  65. package/dist/ai/guides/migration/components/bb-table.md +1 -0
  66. package/dist/ai/guides/migration/components/bb-toast.md +4 -0
  67. package/dist/ai/guides/migration/components/bb-tooltip.md +15 -12
  68. package/dist/ai/guides/migration/components/use-confirm.md +25 -2
  69. package/dist/ai/guides/migration/v2-to-v3.md +163 -9
  70. package/dist/ai/guides/migration/v3-beta-css-classes.md +7 -3
  71. package/dist/ai/guides/options-items-playbook.md +2 -1
  72. package/dist/ai/guides/passthrough.md +147 -85
  73. package/dist/ai/guides/preset-components.md +140 -15
  74. package/dist/ai/helpers/definePreset.json +7 -0
  75. package/dist/ai/helpers/definePreset.ts +123 -11
  76. package/dist/ai/helpers/inertia/manifest.json +15 -9
  77. package/dist/ai/helpers/inertia/useConfirmOnRouteLeave.ts +4 -4
  78. package/dist/ai/helpers/inertia/usePaginatedResponseContext.ts +39 -24
  79. package/dist/ai/helpers/inertia/useRouteQuery.ts +10 -4
  80. package/dist/ai/index.md +1 -0
  81. package/dist/ai/manifest/common.json +0 -1
  82. package/dist/ai/manifest/components/BbAlert.json +7 -2
  83. package/dist/ai/manifest/components/BbBadge.json +13 -4
  84. package/dist/ai/manifest/components/BbBadge.tree.json +2 -0
  85. package/dist/ai/manifest/components/BbBadgeButton.json +4 -2
  86. package/dist/ai/manifest/components/BbBaseButton.json +4 -2
  87. package/dist/ai/manifest/components/BbBreadcrumbs.tree.json +1 -1
  88. package/dist/ai/manifest/components/BbButton.json +14 -3
  89. package/dist/ai/manifest/components/BbButton.tree.json +5 -1
  90. package/dist/ai/manifest/components/BbCheckboxGroup.json +13 -8
  91. package/dist/ai/manifest/components/BbCheckboxGroup.tree.json +11 -1
  92. package/dist/ai/manifest/components/BbColorInput.json +18 -15
  93. package/dist/ai/manifest/components/BbColorPalette.json +1 -1
  94. package/dist/ai/manifest/components/BbConfirm.json +4 -2
  95. package/dist/ai/manifest/components/BbConfirm.tree.json +1 -1
  96. package/dist/ai/manifest/components/BbDatePicker.json +1 -1
  97. package/dist/ai/manifest/components/BbDatePickerInput.json +17 -14
  98. package/dist/ai/manifest/components/BbDialog.tree.json +2 -1
  99. package/dist/ai/manifest/components/BbDropdown.json +24 -19
  100. package/dist/ai/manifest/components/BbDropdown.tree.json +9 -2
  101. package/dist/ai/manifest/components/BbDropdownButton.json +33 -20
  102. package/dist/ai/manifest/components/BbDropdownButton.tree.json +2 -2
  103. package/dist/ai/manifest/components/BbForm.json +2 -2
  104. package/dist/ai/manifest/components/BbHost.tree.json +1 -1
  105. package/dist/ai/manifest/components/BbHoverCard.json +1 -1
  106. package/dist/ai/manifest/components/BbIndicator.json +8 -2
  107. package/dist/ai/manifest/components/BbNumberInput.json +5 -2
  108. package/dist/ai/manifest/components/BbOffCanvas.json +2 -2
  109. package/dist/ai/manifest/components/BbOffCanvas.tree.json +1 -1
  110. package/dist/ai/manifest/components/BbPopover.json +1 -1
  111. package/dist/ai/manifest/components/BbRadioGroup.json +17 -12
  112. package/dist/ai/manifest/components/BbRadioGroup.tree.json +8 -1
  113. package/dist/ai/manifest/components/BbSelect.json +21 -18
  114. package/dist/ai/manifest/components/BbSelect.tree.json +2 -2
  115. package/dist/ai/manifest/components/BbSelectPopover.json +10 -10
  116. package/dist/ai/manifest/components/BbSelectPopover.tree.json +3 -2
  117. package/dist/ai/manifest/components/BbSwitchGroup.json +1 -1
  118. package/dist/ai/manifest/components/BbSwitchGroup.tree.json +3 -1
  119. package/dist/ai/manifest/components/BbTable.tree.json +14 -1
  120. package/dist/ai/manifest/components/BbTabs.json +9 -6
  121. package/dist/ai/manifest/components/BbTabs.tree.json +1 -1
  122. package/dist/ai/manifest/components/BbTabsList.json +6 -3
  123. package/dist/ai/manifest/components/BbTag.json +19 -16
  124. package/dist/ai/manifest/components/BbTag.tree.json +1 -1
  125. package/dist/ai/manifest/components/BbTextInput.json +6 -3
  126. package/dist/ai/manifest/components/BbTextarea.json +6 -3
  127. package/dist/ai/manifest/components/BbTimePicker.json +1 -1
  128. package/dist/ai/manifest/components/BbTimePickerInput.json +10 -7
  129. package/dist/ai/manifest/components/BbToast.json +7 -2
  130. package/dist/ai/manifest/components/BbToast.tree.json +4 -2
  131. package/dist/ai/manifest/components/BbTooltip.json +6 -5
  132. package/dist/ai/manifest/components/ChipsBox.tree.json +1 -1
  133. package/dist/ai/manifest/components/CommonField.json +1 -1
  134. package/dist/ai/manifest/components/OptionsContainer.json +3 -1
  135. package/dist/ai/manifest/components/OptionsContainer.tree.json +38 -0
  136. package/dist/ai/manifest/index.json +3 -3
  137. package/dist/ai/manifest/meta.json +5 -3
  138. package/dist/ai/manifest/types.advanced.json +5 -2
  139. package/dist/ai/manifest/types.api.json +9 -7
  140. package/dist/ai/recipes/inertia/layout-scaffold.md +19 -6
  141. package/dist/ai/recipes/inertia/records-workspace.md +49 -13
  142. package/dist/ai/recipes/nuxt/layout-scaffold.md +19 -6
  143. package/dist/ai/recipes/nuxt/records-workspace.md +42 -12
  144. package/dist/ai/recipes/vue/layout-scaffold.md +19 -6
  145. package/dist/ai/recipes/vue/records-workspace.md +42 -12
  146. package/dist/ai/source/BbAlert.md +94 -76
  147. package/dist/ai/source/BbBadge.md +174 -72
  148. package/dist/ai/source/BbBadgeButton.md +130 -65
  149. package/dist/ai/source/BbBaseButton.md +46 -124
  150. package/dist/ai/source/BbBaseCheckboxIcon.md +38 -0
  151. package/dist/ai/source/BbBaseRadioIcon.md +18 -0
  152. package/dist/ai/source/BbBaseSwitchIcon.md +51 -0
  153. package/dist/ai/source/BbButton.md +153 -36
  154. package/dist/ai/source/BbCheckboxGroup.md +142 -18
  155. package/dist/ai/source/BbColorInput.md +240 -204
  156. package/dist/ai/source/BbColorPalette.md +7 -4
  157. package/dist/ai/source/BbConfirm.md +34 -11
  158. package/dist/ai/source/BbConfirmPortal.md +24 -9
  159. package/dist/ai/source/BbDatePicker.md +11 -7
  160. package/dist/ai/source/BbDatePickerInput.md +306 -269
  161. package/dist/ai/source/BbDialog.md +49 -14
  162. package/dist/ai/source/BbDropdown.md +314 -197
  163. package/dist/ai/source/BbDropdownButton.md +197 -31
  164. package/dist/ai/source/BbDropdownGroup.md +274 -176
  165. package/dist/ai/source/BbForm.md +50 -6
  166. package/dist/ai/source/BbHoverCard.md +12 -5
  167. package/dist/ai/source/BbIcon.md +4 -3
  168. package/dist/ai/source/BbIndicator.md +73 -52
  169. package/dist/ai/source/BbNumberInput.md +293 -257
  170. package/dist/ai/source/BbOffCanvas.md +55 -29
  171. package/dist/ai/source/BbPopover.md +14 -10
  172. package/dist/ai/source/BbRadioGroup.md +413 -297
  173. package/dist/ai/source/BbSelect.md +549 -435
  174. package/dist/ai/source/BbSelectPopover.md +128 -33
  175. package/dist/ai/source/BbSwitchGroup.md +70 -10
  176. package/dist/ai/source/BbTable.md +369 -37
  177. package/dist/ai/source/BbTabs.md +115 -39
  178. package/dist/ai/source/BbTabsList.md +106 -38
  179. package/dist/ai/source/BbTabsPanels.md +96 -36
  180. package/dist/ai/source/BbTabsRoot.md +96 -36
  181. package/dist/ai/source/BbTag.md +267 -233
  182. package/dist/ai/source/BbTextInput.md +261 -225
  183. package/dist/ai/source/BbTextarea.md +251 -215
  184. package/dist/ai/source/BbTimePicker.md +11 -7
  185. package/dist/ai/source/BbTimePickerInput.md +257 -220
  186. package/dist/ai/source/BbToast.md +73 -32
  187. package/dist/ai/source/BbToastPortal.md +65 -30
  188. package/dist/ai/source/BbTooltip.md +148 -113
  189. package/dist/ai/source/CommonPopover.md +6 -1
  190. package/dist/ai/source/FlatListBox.md +19 -9
  191. package/dist/ai/source/GroupedListBox.md +19 -9
  192. package/dist/ai/source/OptionsContainer.md +25 -9
  193. package/dist/components/BbAlert/BbAlert.vue_vue_type_script_setup_true_lang.js +61 -36
  194. package/dist/components/BbAlert/types.d.ts +9 -5
  195. package/dist/components/BbAlert/types.js +8 -3
  196. package/dist/components/BbBadge/BadgeBodyContent.vue.d.ts +3 -3
  197. package/dist/components/BbBadge/BadgeBodyContent.vue_vue_type_script_setup_true_lang.js +26 -17
  198. package/dist/components/BbBadge/BbBadge.vue_vue_type_script_setup_true_lang.js +103 -50
  199. package/dist/components/BbBadge/BbBadgeButton.vue_vue_type_script_setup_true_lang.js +20 -15
  200. package/dist/components/BbBadge/badgeButtonContext.d.ts +12 -1
  201. package/dist/components/BbBadge/types.d.ts +45 -15
  202. package/dist/components/BbBadge/types.js +12 -3
  203. package/dist/components/BbBaseButton/BbBaseButton.vue_vue_type_script_setup_true_lang.js +89 -126
  204. package/dist/components/BbBaseButton/types.d.ts +23 -4
  205. package/dist/components/BbBaseButton/types.js +7 -1
  206. package/dist/components/BbBaseButton/useLinkState.d.ts +41 -0
  207. package/dist/components/BbBaseButton/useLinkState.js +70 -0
  208. package/dist/components/BbButton/BbButton.vue_vue_type_script_setup_true_lang.js +130 -74
  209. package/dist/components/BbButton/types.d.ts +50 -13
  210. package/dist/components/BbButton/types.js +10 -3
  211. package/dist/components/BbCheckboxGroup/BbCheckboxGroup.vue_vue_type_script_setup_true_lang.js +148 -95
  212. package/dist/components/BbCheckboxGroup/types.d.ts +34 -11
  213. package/dist/components/BbCheckboxGroup/types.js +9 -4
  214. package/dist/components/BbCollapsible/BbCollapsible.vue.d.ts +1 -1
  215. package/dist/components/BbColorInput/BbColorInput.vue_vue_type_script_setup_true_lang.js +134 -93
  216. package/dist/components/BbColorInput/types.d.ts +11 -4
  217. package/dist/components/BbColorInput/types.js +9 -3
  218. package/dist/components/BbConfirm/BbConfirm.vue_vue_type_script_setup_true_lang.js +82 -59
  219. package/dist/components/BbConfirm/types.d.ts +9 -4
  220. package/dist/components/BbConfirm/types.js +8 -3
  221. package/dist/components/BbDatePicker/BbDatePicker.vue.d.ts +1 -1
  222. package/dist/components/BbDatePicker/BbDatePicker.vue_vue_type_script_setup_true_lang.js +68 -67
  223. package/dist/components/BbDatePickerInput/BbDatePickerInput.vue.d.ts +1 -1
  224. package/dist/components/BbDatePickerInput/BbDatePickerInput.vue_vue_type_script_setup_true_lang.js +259 -215
  225. package/dist/components/BbDatePickerInput/types.d.ts +12 -5
  226. package/dist/components/BbDatePickerInput/types.js +9 -3
  227. package/dist/components/BbDialog/BbDialog.vue_vue_type_script_setup_true_lang.js +223 -219
  228. package/dist/components/BbDialog/useDialogStack.d.ts +1 -1
  229. package/dist/components/BbDropdown/AdaptiveDropdown.vue_vue_type_script_setup_true_lang.js +104 -89
  230. package/dist/components/BbDropdown/BbDropdown.vue.d.ts +1 -0
  231. package/dist/components/BbDropdown/BbDropdown.vue_vue_type_script_setup_true_lang.js +323 -285
  232. package/dist/components/BbDropdown/BbDropdownList.vue.d.ts +1 -0
  233. package/dist/components/BbDropdown/BbDropdownList.vue_vue_type_script_setup_true_lang.js +411 -319
  234. package/dist/components/BbDropdown/DropdownPipelineResolver.vue_vue_type_script_setup_true_lang.js +100 -98
  235. package/dist/components/BbDropdown/DropdownRow.vue.d.ts +4 -3
  236. package/dist/components/BbDropdown/DropdownRow.vue_vue_type_script_setup_true_lang.js +49 -28
  237. package/dist/components/BbDropdown/normalizeGroups.d.ts +6 -0
  238. package/dist/components/BbDropdown/normalizeGroups.js +21 -15
  239. package/dist/components/BbDropdown/types.d.ts +59 -12
  240. package/dist/components/BbDropdown/types.js +16 -3
  241. package/dist/components/BbDropdown/useDropdownContext.d.ts +6 -0
  242. package/dist/components/BbDropdownButton/BbDropdownButton.vue.d.ts +2 -1
  243. package/dist/components/BbDropdownButton/BbDropdownButton.vue_vue_type_script_setup_true_lang.js +179 -68
  244. package/dist/components/BbDropdownButton/types.d.ts +44 -16
  245. package/dist/components/BbDropdownButton/types.js +28 -3
  246. package/dist/components/BbForm/BbForm.vue_vue_type_script_setup_true_lang.js +111 -89
  247. package/dist/components/BbForm/formSchema.d.ts +13 -0
  248. package/dist/components/BbHoverCard/BbHoverCard.vue_vue_type_script_setup_true_lang.js +100 -100
  249. package/dist/components/BbIndicator/BbIndicator.vue_vue_type_script_setup_true_lang.js +40 -25
  250. package/dist/components/BbIndicator/types.d.ts +9 -5
  251. package/dist/components/BbIndicator/types.js +8 -3
  252. package/dist/components/BbNumberInput/BbNumberInput.vue_vue_type_script_setup_true_lang.js +243 -202
  253. package/dist/components/BbNumberInput/types.d.ts +12 -5
  254. package/dist/components/BbNumberInput/types.js +9 -3
  255. package/dist/components/BbOffCanvas/BbOffCanvas.vue.d.ts +1 -1
  256. package/dist/components/BbOffCanvas/BbOffCanvas.vue_vue_type_script_setup_true_lang.js +401 -399
  257. package/dist/components/BbOffCanvas/types.d.ts +6 -2
  258. package/dist/components/BbPopover/BbPopover.vue_vue_type_script_setup_true_lang.js +81 -80
  259. package/dist/components/BbRadioGroup/BbRadioGroup.vue_vue_type_script_setup_true_lang.js +158 -105
  260. package/dist/components/BbRadioGroup/types.d.ts +21 -7
  261. package/dist/components/BbRadioGroup/types.js +9 -4
  262. package/dist/components/BbSelect/BbSelect.vue.d.ts +4 -3
  263. package/dist/components/BbSelect/BbSelect.vue_vue_type_script_setup_true_lang.js +181 -137
  264. package/dist/components/BbSelect/types.d.ts +36 -22
  265. package/dist/components/BbSelect/types.js +22 -3
  266. package/dist/components/BbSelectPopover/BbSelectPopover.vue.d.ts +4 -4
  267. package/dist/components/BbSelectPopover/BbSelectPopover.vue_vue_type_script_setup_true_lang.js +543 -532
  268. package/dist/components/BbSelectPopover/knownItems.d.ts +5 -0
  269. package/dist/components/BbSelectPopover/types.d.ts +46 -12
  270. package/dist/components/BbSmoothHeight/BbSmoothHeight.vue.d.ts +1 -1
  271. package/dist/components/BbSwitchGroup/BbSwitchGroup.vue_vue_type_script_setup_true_lang.js +2 -2
  272. package/dist/components/BbSwitchGroup/types.d.ts +14 -4
  273. package/dist/components/BbSwitchGroup/types.js +8 -3
  274. package/dist/components/BbTable/BbTable.vue_vue_type_script_setup_true_lang.js +1102 -995
  275. package/dist/components/BbTable/estimatedFloors.golden.d.ts +25 -0
  276. package/dist/components/BbTable/measuredFloors.d.ts +46 -0
  277. package/dist/components/BbTable/measuredFloors.js +322 -0
  278. package/dist/components/BbTable/measuredFloorsTestKit.d.ts +27 -0
  279. package/dist/components/BbTable/textRuler.d.ts +71 -0
  280. package/dist/components/BbTable/textRuler.js +121 -0
  281. package/dist/components/BbTable/utils.d.ts +113 -6
  282. package/dist/components/BbTable/utils.js +118 -65
  283. package/dist/components/BbTabs/BbTabs.vue_vue_type_script_setup_true_lang.js +53 -35
  284. package/dist/components/BbTabs/BbTabsList.vue_vue_type_script_setup_true_lang.js +62 -45
  285. package/dist/components/BbTabs/types.d.ts +26 -11
  286. package/dist/components/BbTabs/types.js +23 -8
  287. package/dist/components/BbTag/BbTag.vue_vue_type_script_setup_true_lang.js +205 -164
  288. package/dist/components/BbTag/types.d.ts +11 -4
  289. package/dist/components/BbTag/types.js +9 -3
  290. package/dist/components/BbTextInput/BbTextInput.vue_vue_type_script_setup_true_lang.js +98 -57
  291. package/dist/components/BbTextInput/types.d.ts +12 -5
  292. package/dist/components/BbTextInput/types.js +9 -3
  293. package/dist/components/BbTextarea/BbTextarea.vue_vue_type_script_setup_true_lang.js +137 -96
  294. package/dist/components/BbTextarea/types.d.ts +12 -5
  295. package/dist/components/BbTextarea/types.js +9 -3
  296. package/dist/components/BbTimePicker/BbTimePicker.vue_vue_type_script_setup_true_lang.js +105 -104
  297. package/dist/components/BbTimePickerInput/BbTimePickerInput.vue_vue_type_script_setup_true_lang.js +241 -197
  298. package/dist/components/BbTimePickerInput/types.d.ts +12 -5
  299. package/dist/components/BbTimePickerInput/types.js +9 -3
  300. package/dist/components/BbToast/BbToast.vue_vue_type_script_setup_true_lang.js +74 -32
  301. package/dist/components/BbToast/BbToastMessage.vue_vue_type_script_setup_true_lang.js +47 -47
  302. package/dist/components/BbToast/types.d.ts +10 -5
  303. package/dist/components/BbToast/types.js +18 -3
  304. package/dist/components/BbTooltip/BbTooltip.vue_vue_type_script_setup_true_lang.js +85 -71
  305. package/dist/components/BbTooltip/types.d.ts +13 -8
  306. package/dist/components/BbTooltip/types.js +8 -3
  307. package/dist/components/CommonField/CommonField.vue.d.ts +1 -1
  308. package/dist/components/CommonPopover/CommonPopover.vue.d.ts +1 -1
  309. package/dist/components/CommonPopover/CommonPopover.vue_vue_type_script_setup_true_lang.js +69 -69
  310. package/dist/components/FlatListBox/FlatListBox.vue_vue_type_script_setup_true_lang.js +53 -50
  311. package/dist/components/GroupedListBox/GroupedListBox.vue_vue_type_script_setup_true_lang.js +146 -143
  312. package/dist/components/OptionsContainer/OptionsContainer.vue_vue_type_script_setup_true_lang.js +7 -2
  313. package/dist/components/OptionsContainer/types.d.ts +14 -3
  314. package/dist/composables/useBbFormContext.d.ts +4 -3
  315. package/dist/composables/useBbTabsContext.js +99 -85
  316. package/dist/composables/useChoiceIndicator.d.ts +58 -0
  317. package/dist/composables/useChoiceIndicator.js +197 -0
  318. package/dist/composables/useConfirm.d.ts +4 -4
  319. package/dist/composables/usePassthrough.d.ts +54 -1
  320. package/dist/composables/usePassthrough.js +100 -71
  321. package/dist/directives/bbTooltip.d.ts +12 -6
  322. package/dist/directives/createPopoverDirective.js +1 -1
  323. package/dist/index.d.ts +3 -1
  324. package/dist/llms-full.txt +2300 -543
  325. package/dist/llms-medium.txt +71 -53
  326. package/dist/llms.txt +2 -1
  327. package/dist/passthrough-deduper.js +6 -3
  328. package/dist/project-dts.d.ts +24 -0
  329. package/dist/project-dts.js +43 -17
  330. package/dist/styles.css +2 -2
  331. package/dist/types/AlertVariant.d.ts +14 -0
  332. package/dist/types/AlertVariant.js +9 -0
  333. package/dist/types/BadgeVariant.d.ts +14 -0
  334. package/dist/types/BadgeVariant.js +9 -0
  335. package/dist/types/ButtonVariant.d.ts +16 -0
  336. package/dist/types/ButtonVariant.js +11 -0
  337. package/dist/types/CheckboxVariant.d.ts +38 -0
  338. package/dist/types/CheckboxVariant.js +4 -0
  339. package/dist/types/CommonProps.d.ts +4 -3
  340. package/dist/types/Config.d.ts +7 -0
  341. package/dist/types/ConfirmVariant.d.ts +12 -0
  342. package/dist/types/ConfirmVariant.js +4 -0
  343. package/dist/types/DropdownItemVariant.d.ts +12 -0
  344. package/dist/types/DropdownItemVariant.js +4 -0
  345. package/dist/types/IndicatorVariant.d.ts +15 -0
  346. package/dist/types/IndicatorVariant.js +10 -0
  347. package/dist/types/InputVariant.d.ts +13 -0
  348. package/dist/types/InputVariant.js +8 -0
  349. package/dist/types/RadioVariant.d.ts +38 -0
  350. package/dist/types/RadioVariant.js +4 -0
  351. package/dist/types/TabsVariant.d.ts +13 -0
  352. package/dist/types/TabsVariant.js +8 -0
  353. package/dist/types/ToastVariant.d.ts +15 -0
  354. package/dist/types/ToastVariant.js +10 -0
  355. package/dist/types/TooltipVariant.d.ts +12 -0
  356. package/dist/types/TooltipVariant.js +4 -0
  357. package/dist/types/passthrough.d.ts +83 -15
  358. package/dist/types/passthrough.js +2 -2
  359. package/dist/types/ptComponentMap.d.ts +35 -23
  360. package/dist/utilities/functions/extractDomContainer.d.ts +20 -1
  361. package/dist/utilities/functions/extractDomContainer.js +8 -3
  362. package/dist/utils/focusVisibility.d.ts +6 -0
  363. package/dist/utils/focusVisibility.js +4 -1
  364. package/dist/utils/passthroughDeduper.d.ts +14 -0
  365. package/dist/utils/versionCheck.js +1 -1
  366. package/dist/vite-plugin.d.ts +64 -7
  367. package/dist/vite.js +385 -259
  368. package/llms.txt +2 -1
  369. package/package.json +3 -3
  370. package/scripts/lib/adoption-checklist.json +312 -0
  371. package/scripts/lib/eslint-plugin.d.ts +13 -0
  372. package/scripts/lib/eslint-plugin.mjs +75 -11
  373. package/scripts/lib/idiom-scan.mjs +65 -0
  374. package/scripts/lib/mcp-config.mjs +203 -9
  375. package/scripts/lib/migrate-fix.mjs +42 -1
  376. package/scripts/lib/project-variant-dts.mjs +18 -0
  377. package/scripts/lib/validate-bb-markup.mjs +99 -2
@@ -69,7 +69,8 @@ declare function close(): void;
69
69
  Hides the newest open dialog opened through the same `useConfirm()` (never
70
70
  another component's) without resolving anything. Its purpose is multi-step
71
71
  flows: with `autoClose: false` the dialog stays open after the promise resolves,
72
- and you call `close()` when your flow is done. Don't use it as a substitute for
72
+ and you call `close()` when your flow is done. Server work is not such a flow:
73
+ it goes in `yes.onClick` (see **Async work before the dialog closes**). Don't use it as a substitute for
73
74
  the buttons — a `confirm()` closed this way before any button ran leaves its
74
75
  promise pending.
75
76
 
@@ -166,6 +167,43 @@ const post = await confirm({
166
167
  // post is the api result, or false when the user declined
167
168
  ```
168
169
 
170
+ An Inertia visit goes in `onClick` too. It returns no promise, so wrap it (the
171
+ same wrapper as BbDialog's `save()`): Yes spins for the whole visit, and the
172
+ dialog closes when it settles. A failed visit rejects `confirm()` and still
173
+ closes the dialog.
174
+
175
+ ```ts
176
+ import { router } from '@inertiajs/vue3';
177
+ import { useConfirm } from 'bitboss-ui';
178
+
179
+ const { confirm } = useConfirm();
180
+
181
+ const destroy = (url: string) =>
182
+ new Promise<void>((resolve, reject) => {
183
+ router.delete(url, {
184
+ onSuccess: () => resolve(),
185
+ onError: (errors) => reject({ errors }),
186
+ // Cut short by another visit: resolve. Ended unsettled (a 500, a
187
+ // network error): reject. Both are no-ops after onSuccess / onError.
188
+ onFinish: (visit) =>
189
+ visit.cancelled || visit.interrupted
190
+ ? resolve()
191
+ : reject(new Error('The delete failed')),
192
+ });
193
+ });
194
+
195
+ const remove = (id: number) =>
196
+ confirm({
197
+ title: 'Delete invoice?',
198
+ variant: 'destructive',
199
+ yes: { text: 'Delete', onClick: () => destroy(`/invoices/${id}`) },
200
+ });
201
+ ```
202
+
203
+ Not `autoClose: false` with `close()` called from the visit callbacks: Yes
204
+ never shows busy, and a missed callback leaves the dialog up or closes it
205
+ mid-visit.
206
+
169
207
  ### Custom footer actions — more than yes/no
170
208
 
171
209
  Pass an `actions` array to replace the Yes/No footer with your own buttons.
@@ -456,18 +456,18 @@
456
456
  "dark": "#00000080"
457
457
  }
458
458
  },
459
- "--bb-overlay-blur": {
460
- "css": "--bb-overlay-blur",
461
- "light": "2px"
462
- },
463
- "--bb-overlay-stacked": {
464
- "css": "--bb-overlay-stacked",
459
+ "--bb-overlay-above": {
460
+ "css": "--bb-overlay-above",
465
461
  "derived": "var(--bb-overlay)",
466
462
  "resolved": {
467
463
  "light": "#0000001a",
468
464
  "dark": "#00000080"
469
465
  }
470
466
  },
467
+ "--bb-overlay-blur": {
468
+ "css": "--bb-overlay-blur",
469
+ "light": "2px"
470
+ },
471
471
  "--bb-panel": {
472
472
  "css": "--bb-panel",
473
473
  "light": "rgb(255 255 255)",
@@ -240,8 +240,8 @@ semantic status badges, a brand button tone — **add it, in both halves**:
240
240
 
241
241
  1. **Register the name** in the build plugin: `badgeVariants`, `buttonVariants`,
242
242
  `alertVariants`, `confirmVariants`, `dropdownItemVariants`, `tooltipVariants`,
243
- `toastVariants`, `indicatorVariants`, `inputVariants`, `tabsVariants`
244
- (`bitboss-ui/vite` or `bitboss-ui/nuxt`).
243
+ `toastVariants`, `indicatorVariants`, `inputVariants`, `tabsVariants`,
244
+ `radioVariants`, `checkboxVariants` (`bitboss-ui/vite` or `bitboss-ui/nuxt`).
245
245
  The plugin regenerates the typed registry, so the name type-checks.
246
246
  2. **Style the class** — `.bb-badge--<name>`, `.bb-button--<name>`, … —
247
247
  in a project stylesheet loaded **after** `bitboss-ui/styles.css`. The library
@@ -98,29 +98,30 @@ inline-edit playbook) instead of inventing a new shape.
98
98
 
99
99
  ## Playbooks (only when the pattern applies)
100
100
 
101
- | Need | Guide |
102
- | -------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
103
- | ⌘K / Ctrl+K global command palette | [BbSelectPopover](../BbSelectPopover.md#a-k-command-palette) § A ⌘K command palette |
104
- | Tied selects / stale model cleanup | [coherence-playbook](./coherence-playbook.md) |
105
- | Async `items` providers / prefill | [fetch-items-playbook](./fetch-items-playbook.md) |
106
- | `item-text` / `item-value` / the default `label` / `value` keys / disabled | [options-items-playbook](./options-items-playbook.md) |
107
- | Table cell edit ownership | [inline-edit-playbook](./inline-edit-playbook.md) |
108
- | Table row → detail (identity cells) | [agent-contract](./agent-contract.md) § Inline Links |
109
- | Peek that drills into related records | [agent-contract](./agent-contract.md) § Consult-Stack |
110
- | Icons (`lucide:*`, never invent names) | [icons-policy](./icons-policy.md) |
111
- | Tokens / styling around components | [design-language](./design-language.md) |
112
- | Inertia app-side helpers (`useProp`, `useQuery`, `useQueryObject`, `useTableContext`, …) the Inertia recipes import | [inertia-helpers](./inertia-helpers.md) |
113
- | Theming a whole app / retuning a component | [design-tokens](./design-tokens.md) — the two tiers, and why most restyling is a component token, not a `--bb-*` one |
114
- | Paint as data (DESIGN.md, impeccable, design-taste) | [design-tokens.json](../design-tokens.json) and [design-tokens.manifest.yaml](../design-tokens.manifest.yaml), generated from `variables.css`. Grep `--bb-*`, not `--color-*` or `--radius-*`. Root `DESIGN.md` is the Inertia fixture, not this library. |
115
- | A Tailwind utility on a `Bb*` component does nothing, or half-applies | [installation](./installation-and-plugin-setup.md) § Cascade layers — v4 is layered, we are not by default. It is per PROPERTY: a utility loses only where we declare the same one, and a shorthand like `p-4` can half-apply. `cssLayers: TAILWIND_V4_LAYERS` in the build plugin |
116
- | Restyling ONE part of a component (its icon, its spinner, its field box) — or a `:deep()` you are about to write | [passthrough](./passthrough.md) — the first choice: `pt:<part>` / `pt:<part>:<state>`, typed and linted; classes append, attributes win, listeners concatenate. A look many places need is a **variant**, not `pt`. No part for it? A CSS override on the internal class is allowed but can break in any release (a part's class is stable within 3.x) — [design-language](./design-language.md) § Hard Rules |
117
- | Styling the SELECTED option, the HIGHLIGHTED row, the CURRENT tab — a state a modifier class used to carry | [passthrough](./passthrough.md) § Parts that resolve per node — `pt:option:selected`, `pt:row:highlighted`, `pt:item:active`; every component's parts and states are in its table |
118
- | Typing a `pt` value in `<script>` (a const, a preset, a wrapper's `pt` prop, a global map split across files) | [passthrough](./passthrough.md) § Typing `pt` in `<script>` — `<Component>Props<Row>['pt']` with `satisfies`, `definePt` for map fragments. `PtValue` / `PtMap` are not exported |
119
- | `InstanceType<typeof BbSelect>` fails, a Storybook `Meta` or `findComponent` won't type, a `ref('')` on a text field | [typescript-generic-components](./typescript-generic-components.md) — the generic components and their four script-side differences |
120
- | Wrapping a `Bb*` component in your own (`MemberSelect`, `PriceListSelect`) | A preset (fixed items, label, option row): [preset-components](./preset-components.md), one `definePreset` call. With its own logic: [options-items-playbook](./options-items-playbook.md) § Wrapping BbSelect in your own component |
121
- | Forms with validation (`BbForm`) | [validated-forms](./validated-forms.md); the schema library (Zod, Valibot, ArkType, Yup, Joi, Effect, string rules) and switching between them: [validation-libraries](./validation-libraries.md); server errors from Inertia, a Laravel 422, Precognition, vee-validate or Nuxt UI into `setErrors`: [validation-providers](./validation-providers.md); porting an Element Plus / Naive UI / Ant Design Vue form (`rules` objects, async-validator): [from-async-validator](./migration/from-async-validator.md) |
122
- | Upgrading from bitboss-ui 2.x | [migration/v2-to-v3](./migration/v2-to-v3.md) |
123
- | Bumping between two v3 prereleases | `npx bitboss-ui changelog --since <your version>` (MCP `list_changes`) — what BREAKS in the bump, and in which release each break first shipped (`firstReleasedIn`); then `check --manifest` for the files it breaks |
101
+ | Need | Guide |
102
+ | ----------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
103
+ | ⌘K / Ctrl+K global command palette | [BbSelectPopover](../BbSelectPopover.md#a-k-command-palette) § A ⌘K command palette |
104
+ | Tied selects / stale model cleanup | [coherence-playbook](./coherence-playbook.md) |
105
+ | Async `items` providers / prefill | [fetch-items-playbook](./fetch-items-playbook.md) |
106
+ | `item-text` / `item-value` / the default `label` / `value` keys / disabled | [options-items-playbook](./options-items-playbook.md) |
107
+ | Table cell edit ownership | [inline-edit-playbook](./inline-edit-playbook.md) |
108
+ | Table row → detail (identity cells) | [agent-contract](./agent-contract.md) § Inline Links |
109
+ | Peek that drills into related records | [agent-contract](./agent-contract.md) § Consult-Stack |
110
+ | Icons (`lucide:*`, never invent names) | [icons-policy](./icons-policy.md) |
111
+ | Tokens / styling around components | [design-language](./design-language.md) |
112
+ | Inertia app-side helpers (`useProp`, `useQuery`, `useQueryObject`, `useTableContext`, …) the Inertia recipes import | [inertia-helpers](./inertia-helpers.md) |
113
+ | Theming a whole app / retuning a component | [design-tokens](./design-tokens.md) — the two tiers, and why most restyling is a component token, not a `--bb-*` one |
114
+ | Paint as data (DESIGN.md, impeccable, design-taste) | [design-tokens.json](../design-tokens.json) and [design-tokens.manifest.yaml](../design-tokens.manifest.yaml), generated from `variables.css`. Grep `--bb-*`, not `--color-*` or `--radius-*`. Root `DESIGN.md` is the Inertia fixture, not this library. |
115
+ | A Tailwind utility on a `Bb*` component does nothing, or half-applies | [installation](./installation-and-plugin-setup.md) § Cascade layers — v4 is layered, we are not by default. It is per PROPERTY: a utility loses only where we declare the same one, and a shorthand like `p-4` can half-apply. `cssLayers: TAILWIND_V4_LAYERS` in the build plugin |
116
+ | Restyling ONE part of a component (its icon, its spinner, its field box) — or a `:deep()` you are about to write | [passthrough](./passthrough.md) — the first choice: `pt:<part>` / `pt:<part>:<state>`, typed and linted; classes append, attributes win, listeners concatenate. A look many places need is a **variant**, not `pt`. No part for it? A CSS override on the internal class is allowed but can break in any release (a part's class is stable within 3.x) — [design-language](./design-language.md) § Hard Rules |
117
+ | Styling the SELECTED option, the HIGHLIGHTED row, the CURRENT tab — a state a modifier class used to carry | [passthrough](./passthrough.md) § Parts that resolve per node — `pt:option:selected`, `pt:row:highlighted`, `pt:item:active`; every component's parts and states are in its table |
118
+ | Typing a `pt` value in `<script>` (a const, a preset, a wrapper's `pt` prop, a global map split across files) | [passthrough](./passthrough.md) § Typing `pt` in `<script>` — `<Component>Props<Row>['pt']` with `satisfies`, `definePt` for map fragments. `PtValue` / `PtMap` are not exported |
119
+ | `InstanceType<typeof BbSelect>` fails, a Storybook `Meta` or `findComponent` won't type, a `ref('')` on a text field | [typescript-generic-components](./typescript-generic-components.md) — the generic components and their four script-side differences |
120
+ | Wrapping a `Bb*` component in your own (`MemberSelect`, `PriceListSelect`) | A preset (fixed items, label, option row): [preset-components](./preset-components.md), one `definePreset` call. With its own logic: [options-items-playbook](./options-items-playbook.md) § Wrapping BbSelect in your own component |
121
+ | Forms with validation (`BbForm`) | [validated-forms](./validated-forms.md); the schema library (Zod, Valibot, ArkType, Yup, Joi, Effect, string rules) and switching between them: [validation-libraries](./validation-libraries.md); server errors from Inertia, a Laravel 422, Precognition, vee-validate or Nuxt UI into `setErrors`: [validation-providers](./validation-providers.md); porting an Element Plus / Naive UI / Ant Design Vue form (`rules` objects, async-validator): [from-async-validator](./migration/from-async-validator.md) |
122
+ | Finishing a migration (from v2 or another library): the hand-rolled controls to move onto the library, `check --idioms` | [migration/adoption-checklist](./migration/adoption-checklist.md) |
123
+ | Upgrading from bitboss-ui 2.x | [migration/v2-to-v3](./migration/v2-to-v3.md) |
124
+ | Bumping between two v3 prereleases | `npx bitboss-ui changelog --since <your version>` (MCP `list_changes`) — what BREAKS in the bump, and in which release each break first shipped (`firstReleasedIn`); then `check --manifest` for the files it breaks |
124
125
 
125
126
  ---
126
127
 
@@ -242,6 +242,11 @@ const footer = [
242
242
  background: color-mix(in oklab, var(--bb-text) 6%, transparent);
243
243
  }
244
244
 
245
+ /* BbBaseButton drops the native ring: the keyboard focus is drawn here. */
246
+ .layout__nav-item:focus-visible {
247
+ box-shadow: 0 0 0 var(--bb-ring-size) var(--bb-ring);
248
+ }
249
+
245
250
  .layout__nav-item--active {
246
251
  background: color-mix(in oklab, var(--bb-text) 9%, transparent);
247
252
  font-weight: 500;
@@ -40,6 +40,12 @@ logo — on every `.vue` file it scans. That is the backstop: it fires without
40
40
  anyone thinking to ask. The badge case is not decidable from markup (a tinted
41
41
  pill is as often decoration as status), so it has no hint and stays your job.
42
42
 
43
+ Migrating an app that already built these? The
44
+ [adoption checklist](./migration/adoption-checklist.md) is the same question
45
+ asked of existing code: every hand-rolled pattern the library ships, how to
46
+ find it, and the replacement. `npx bitboss-ui check --idioms` runs its patterns
47
+ over the app (report-only).
48
+
43
49
  ---
44
50
 
45
51
  ## Text Input
@@ -81,6 +87,7 @@ pill is as often decoration as status), so it has no hint and stays your job.
81
87
  - Small static multi-choice submitted with a form → `BbCheckboxGroup`.
82
88
  - Each option is a live setting that applies the moment it flips → `BbSwitchGroup`.
83
89
  - The trigger is a status pill, avatar stack, or table-cell chip rather than a form field → `BbSelectPopover` (same search/options engine as `BbSelect`, you own the trigger).
90
+ - A segmented control: **switch views → `BbTabs`** (default `pill`), **pick a value → `BbRadioGroup` `variant="pill"`** (or `"line"`; several values → `BbCheckboxGroup` `variant="pill"`): BbTabs' look on a radiogroup ([§ Segmented control](../BbRadioGroup.md#segmented-control)). Decide by the job, not the look: a value a form or a filter submits is a radio group; what the page shows is a tab.
84
91
 
85
92
  Never hand-assemble a row of `BbCheckbox`/`BbRadio` — the groups give you fieldset semantics, item mapping, and validation for free.
86
93
 
@@ -192,7 +199,7 @@ There are also **`v-bb-color`**, **`v-bb-date`**, and **`v-bb-time`** directives
192
199
 
193
200
  **Offload navigation to the component.** `BbButton`, dropdown items, and breadcrumb items accept `href` (anchor, or Inertia visit with `method`/`data`/`preserveScroll`/…) and `to` (vue-router); tabs items accept `href`; `BbPagination` with `navigation` builds per-page links itself. Never wire `@click="router.push(...)"` for a plain destination.
194
201
 
195
- **Picking the pattern:** `BbTabs` switches peer sections of _one_ subject (Overview / Activity / Settings) — not steps in a flow, not hierarchy. A look the shipped variants don't have (a side nav, a filter row) starts from `variant="none"` plus the strip's tokens in `pt.wrapper.style` (inline, so no stylesheet and no scoped-style trap); the library does not add a variant per need. `BbBreadcrumbs` answers "where am I and how do I get back up". `BbPagination` steps through a paged result set — prefer it over infinite scroll when users need to find their place again.
202
+ **Picking the pattern:** `BbTabs` switches peer sections of _one_ subject (Overview / Activity / Settings) — not steps in a flow, not hierarchy, and not a value: a segmented strip that picks a value a form or a filter submits is a `BbRadioGroup` `variant="pill"` / `"line"`, the same look ([§ Segmented control](../BbRadioGroup.md#segmented-control)). A look the shipped variants don't have (a side nav, a filter row) starts from `variant="none"` plus the strip's tokens in `pt.wrapper.style` (inline, so no stylesheet and no scoped-style trap); the library does not add a variant per need. `BbBreadcrumbs` answers "where am I and how do I get back up". `BbPagination` steps through a paged result set — prefer it over infinite scroll when users need to find their place again.
196
203
 
197
204
  **Disclosure ladder (BbAccordion vs BbCollapsible vs BbSmoothHeight):**
198
205
 
@@ -247,7 +254,7 @@ compose it or write it yourself.
247
254
  | `BbModal` | It is [BbDialog](../BbDialog.md). |
248
255
  | `BbDrawer` / `BbSheet` | It is [BbOffCanvas](../BbOffCanvas.md). |
249
256
  | `BbCombobox` / `BbAutocomplete` | It is [BbSelect](../BbSelect.md) / [BbSelectPopover](../BbSelectPopover.md) — search is built in, see `disable-writing`. |
250
- | `BbToggle` / `BbToggleGroup` | It is [BbButton](../BbButton.md) with `v-model` (+ `true-value` / `false-value`), which owns `aria-pressed` and the active class. A group is several buttons: a boolean per button for independent toggles, one shared `v-model` with `:false-value="null"` for an optional choice, `group` to fuse them ([BbButton § Toggle buttons](../BbButton.md#toggle-buttons)); exactly one always active is a `BbRadioGroup` segmented control or `BbTabs`. |
257
+ | `BbToggle` / `BbToggleGroup` | It is [BbButton](../BbButton.md) with `v-model` (+ `true-value` / `false-value`), which owns `aria-pressed` and the active class. A group is several buttons: a boolean per button for independent toggles, one shared `v-model` with `:false-value="null"` for an optional choice, `group` to fuse them ([BbButton § Toggle buttons](../BbButton.md#toggle-buttons)); exactly one always active is a `BbRadioGroup` `variant="pill"` or `BbTabs`. |
251
258
  | `TagChip` / colored, read-only tag chip | It is [BbBadge](../BbBadge.md) — [BbTag](../BbTag.md) is a tags-_input_ only, not a display component. Use `BbBadge` with a registered `soft-*` variant for a fixed palette, or a one-off `--bg`/`--fg` override per row for arbitrary/data-driven colors (BbBadge.md § One-off colors) — not a registered variant per distinct color. |
252
259
  | `BbTab` (singular) | The consumer API is [BbTabs](../BbTabs.md) / `BbTabsRoot`. `BbTab` appears only as the **v2 "before" side** of the migration diffs. |
253
260
  | `BbCard` | Does not exist — a card is a `<div>` with tokens. See [design-language](./design-language.md). |
@@ -132,28 +132,28 @@ one renders with no value at all rather than erroring.
132
132
 
133
133
  ### Surfaces & structure
134
134
 
135
- | Token | Meaning |
136
- | ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
137
- | `--bb-panel` | Surface/background color of panels, popovers, dialogs |
138
- | `--bb-muted` | Subtle/disabled surface (derived, neutral) |
139
- | `--bb-hover` | Hover fill for **affordances** (buttons, links, controls) |
140
- | `--bb-surface-hover` | Hover fill for **passive surfaces** (rows, cells, days) — fainter |
141
- | `--bb-pressed` | Neutral pressed/active fill |
142
- | `--bb-border` | Border color; pair with `--bb-border-w` (1px) |
143
- | `--bb-field-border` | Resting border of every form field (the default input box and the group / rating / slider shells); follows `--bb-border` until set |
144
- | `--bb-border-w` | Hairline thickness — plates **and** internal dividers (dialog/off-canvas footers, menu rules, popover headers) |
145
- | `--bb-border-w-sm` | Nested / small hairline (xs/sm buttons, badges, glyphs) — half of `--bb-border-w`, floored at 1px and capped by it |
146
- | `--bb-radius` | Corner radius of controls (8px) |
147
- | `--bb-radius-surface` | Corner radius of large surfaces (derived, ×1.8) |
148
- | `--bb-radius-sm` | Corner radius of small nested elements (derived) |
149
- | `--bb-shadow` | Overlay elevation (dialogs, popovers, menus, toasts) |
150
- | `--bb-elev` | Resting lift on controls — a full `box-shadow`, default a transparent layer. Covers a soft lift and a hard offset alike |
151
- | `--bb-elev-sm` | The same lift on small chrome (badges, glyphs, xs/sm buttons); inherits `--bb-elev` unless a hard-offset theme splits it |
152
- | `--bb-panel-p` | Content padding of large surfaces (dialog, off-canvas); axis split via the locals `--px`/`--py` on `.bb-dialog` / `.bb-offcanvas` |
153
- | `--bb-overlay-blur` | Backdrop dim blur (2px) — on the bottom-most open panel's backdrop only |
154
- | `--bb-overlay-stacked` | Dim painted by a panel stacked over another open one (derived, equal to `--bb-overlay`; `transparent` = one dim under the pile) |
155
- | `--bb-surface-filter` | Frost on raised plates — dialog, off-canvas, popover bubble, toast, input shell, alert, table. A full `backdrop-filter` value, default `none` |
156
- | `--bb-z-overlay` | Z-index for overlays (10) |
135
+ | Token | Meaning |
136
+ | --------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
137
+ | `--bb-panel` | Surface/background color of panels, popovers, dialogs |
138
+ | `--bb-muted` | Subtle/disabled surface (derived, neutral) |
139
+ | `--bb-hover` | Hover fill for **affordances** (buttons, links, controls) |
140
+ | `--bb-surface-hover` | Hover fill for **passive surfaces** (rows, cells, days) — fainter |
141
+ | `--bb-pressed` | Neutral pressed/active fill |
142
+ | `--bb-border` | Border color; pair with `--bb-border-w` (1px) |
143
+ | `--bb-field-border` | Resting border of every form field (the default input box and the group / rating / slider shells); follows `--bb-border` until set |
144
+ | `--bb-border-w` | Hairline thickness — plates **and** internal dividers (dialog/off-canvas footers, menu rules, popover headers) |
145
+ | `--bb-border-w-sm` | Nested / small hairline (xs/sm buttons, badges, glyphs) — half of `--bb-border-w`, floored at 1px and capped by it |
146
+ | `--bb-radius` | Corner radius of controls (8px) |
147
+ | `--bb-radius-surface` | Corner radius of large surfaces (derived, ×1.8) |
148
+ | `--bb-radius-sm` | Corner radius of small nested elements (derived) |
149
+ | `--bb-shadow` | Overlay elevation (dialogs, popovers, menus, toasts) |
150
+ | `--bb-elev` | Resting lift on controls — a full `box-shadow`, default a transparent layer. Covers a soft lift and a hard offset alike |
151
+ | `--bb-elev-sm` | The same lift on small chrome (badges, glyphs, xs/sm buttons); inherits `--bb-elev` unless a hard-offset theme splits it |
152
+ | `--bb-panel-p` | Content padding of large surfaces (dialog, off-canvas); axis split via the locals `--px`/`--py` on `.bb-dialog` / `.bb-offcanvas` |
153
+ | `--bb-overlay-blur` | Backdrop dim blur (2px) — on the bottom-most open panel's backdrop only |
154
+ | `--bb-overlay-above` | Dim painted by a panel stacked over another open one (derived, equal to `--bb-overlay`; `transparent` = one dim under the pile); none on a dialog replacing a member of its own `stack` |
155
+ | `--bb-surface-filter` | Frost on raised plates — dialog, off-canvas, popover bubble, toast, input shell, alert, table. A full `backdrop-filter` value, default `none` |
156
+ | `--bb-z-overlay` | Z-index for overlays (10) |
157
157
 
158
158
  ### Color semantics
159
159
 
@@ -240,8 +240,8 @@ What the shared names mean (shadcn-style vocabulary):
240
240
 
241
241
  Projects can register extra variants through the Vite/Nuxt plugin
242
242
  (`buttonVariants`, `badgeVariants`, `alertVariants`, `confirmVariants`,
243
- `dropdownItemVariants`, `tooltipVariants`, `toastVariants`, `inputVariants`
244
- options).
243
+ `dropdownItemVariants`, `tooltipVariants`, `toastVariants`, `inputVariants`,
244
+ `tabsVariants`, `radioVariants`, `checkboxVariants` options).
245
245
  Registered names become typed values, but the library ships no CSS for them —
246
246
  the project styles `.bb-button--<name>` (etc.) itself, following the state
247
247
  recipe in [design-tokens.md](./design-tokens.md).
@@ -373,6 +373,13 @@ ladder formulas instead of these tokens, so a state name never lies.
373
373
  | `--bb-elev` | `0 0 0 0 transparent` | Resting lift on **controls** (buttons, inputs, badges, alerts, checkbox, slider thumb, tab pill). A full `box-shadow`, composed under the focus ring, so one knob covers a soft lift (`0 1px 2px rgb(0 0 0 / 0.05)`) and a hard offset (`4px 4px 0 0 #111`) alike. The default is a transparent layer, not `none`, so the shadow list keeps a constant length and stays interpolable. `--bb-shadow` is the overlay lift; this is the resting one. Ghost / link / none buttons stay flat whatever the theme sets. Avatar and the Indicator bubble carry it via `--bb-elev-sm`; BbDropzone (no plate of its own — the surface is your content) and BbProgress (a recessed track, not a raised plate) deliberately do not. |
374
374
  | `--bb-elev-sm` | `var(--bb-elev)` | The same lift on **small chrome** — badges, checkbox and radio glyphs, the slider thumb, the colour swatch, xs/sm buttons, the active pagination chip. It inherits `--bb-elev`, so a soft shadow needs one knob; only a hard offset needs the second value, because a hard offset has no falloff and its weight is purely relative to the box (a 4px offset is 11% of an xl button and 25% of a 16px glyph). It cannot be derived — CSS cannot halve the offsets inside a shadow string. |
375
375
 
376
+ **Turn a shadow knob off with `0 0 0 0 transparent`, not `none`.** `--bb-elev`,
377
+ `--bb-elev-sm` and `--bb-shadow-sm` are composed into `box-shadow` lists (the
378
+ tab indicator stacks `--bb-elev` and `--bb-shadow-sm`), and `none` inside a list
379
+ invalidates the whole declaration, taking the other layers with it. The
380
+ transparent layer draws nothing and keeps the list valid. `--bb-shadow` stands
381
+ alone wherever it is used, so `none` works there too.
382
+
376
383
  A four-knob chrome shift is `border-w` + `elev` + `shadow` + `radius`, and
377
384
  both nested tiers follow from the first and last, so there is no second pin
378
385
  to remember. Loud fills also pin `--bb-primary-border` and `--bb-link-fg`
@@ -476,14 +483,14 @@ to hardcode past it.
476
483
 
477
484
  ### Overlays
478
485
 
479
- | Token | Default | Notes |
480
- | ---------------------- | ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
481
- | `--bb-overlay` | `rgb(0 0 0 / 0.1)` | Backdrop dim color+opacity in one — the bottom-most open panel's backdrop |
482
- | `--bb-overlay-stacked` | derived: `--bb-overlay` | Dim painted by a dialog or off-canvas stacked over another open one, on top of everything beneath it (the parent included). Derived, so a theme that only sets `--bb-overlay` gets a matching value; `transparent` gives a single dim under the whole pile |
483
- | `--bb-overlay-blur` | `2px` | Backdrop blur — only the bottom-most open panel's backdrop carries it, whatever the depth |
484
- | `--bb-surface-filter` | `none` | Frost on raised plates (dialog, sheet, bubble, toast, alert, table, input shell). A full `backdrop-filter` value — `blur(22px) saturate(1.8)` — not a length. Glass themes set it and give `--bb-panel` an alpha. |
485
- | `--bb-z-overlay` | `10` | Overlay z-index |
486
- | `--bb-arrow` | `1` | Popover arrows on (`1`) / off (`0`) |
486
+ | Token | Default | Notes |
487
+ | --------------------- | ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
488
+ | `--bb-overlay` | `rgb(0 0 0 / 0.1)` | Backdrop dim color+opacity in one — the bottom-most open panel's backdrop |
489
+ | `--bb-overlay-above` | derived: `--bb-overlay` | Dim painted by a dialog or off-canvas stacked over another open one, on top of everything beneath it (the parent included). A dialog that replaces a member of its own `stack` paints none: the covered member's backdrop stays the only one. Derived, so a theme that only sets `--bb-overlay` gets a matching value; `transparent` gives a single dim under the whole pile |
490
+ | `--bb-overlay-blur` | `2px` | Backdrop blur — only the bottom-most open panel's backdrop carries it, whatever the depth |
491
+ | `--bb-surface-filter` | `none` | Frost on raised plates (dialog, sheet, bubble, toast, alert, table, input shell). A full `backdrop-filter` value — `blur(22px) saturate(1.8)` — not a length. Glass themes set it and give `--bb-panel` an alpha. |
492
+ | `--bb-z-overlay` | `10` | Overlay z-index |
493
+ | `--bb-arrow` | `1` | Popover arrows on (`1`) / off (`0`) |
487
494
 
488
495
  ### Input family
489
496
 
@@ -262,8 +262,15 @@ markup) yourself:
262
262
  duplicate.
263
263
  - Meaningful standalone icon: give `BbIcon` a `label` — it adds `role="img"`
264
264
  and `aria-label`. Deliberately **no `title`**: that renders a native browser
265
- tooltip, which double-tooltips any icon also carrying `v-bb-tooltip` (owner
266
- ruling 2026-07-30, `BbIcon.vue:200`). For a visible tip, add `v-bb-tooltip`.
265
+ tooltip (owner ruling 2026-07-30). `BbIcon` is never focusable.
266
+ - An info icon with a tip: make it an icon-only ghost `BbButton`, so keyboard
267
+ focus reaches it and opens the tip; the slot text is its name, the tip its
268
+ description:
269
+ `<BbButton variant="ghost" icon="lucide:info" v-bb-tooltip="'Prices include VAT'">About prices</BbButton>`.
270
+ When the text must be readable on touch, make it a `BbPopover` toggletip
271
+ (the same button as its activator; see the BbPopover guide, "Inline field
272
+ help"). `v-bb-tooltip` on a bare `BbIcon` or `<span>` is a pointer-only
273
+ hint: keyboard and touch never open it.
267
274
  - Icon-only `BbButton` (the `icon` prop): supply the accessible name through the
268
275
  label (default slot, or `text`) — it renders `sr-only` but is still announced.
269
276
  `aria-label` is only an override; the one hard rule is that the button must
@@ -544,7 +544,12 @@ safe to sync from server responses without visit loops.
544
544
  // requires: npm i query-string
545
545
  import { router, usePage } from '@inertiajs/vue3';
546
546
  import qs from 'query-string';
547
- import { computed, type WritableComputedRef } from 'vue';
547
+ import {
548
+ computed,
549
+ toValue,
550
+ type MaybeRefOrGetter,
551
+ type WritableComputedRef,
552
+ } from 'vue';
548
553
 
549
554
  type Options<T> = {
550
555
  /** Parse the raw string (e.g. `Number`). Defaults to identity. */
@@ -555,7 +560,8 @@ type Options<T> = {
555
560
 
556
561
  export function useRouteQuery<T = string>(
557
562
  key: string,
558
- defaultValue: string,
563
+ /** The value while the key is absent; a ref or getter is read each time. */
564
+ defaultValue: MaybeRefOrGetter<string>,
559
565
  options: Options<T> = {}
560
566
  ): WritableComputedRef<T> {
561
567
  const {
@@ -569,7 +575,7 @@ export function useRouteQuery<T = string>(
569
575
  const [, queryString = ''] = page.url.split('?');
570
576
  const raw = qs.parse(queryString)[key];
571
577
  const single = Array.isArray(raw) ? raw[0] : raw;
572
- return single != null ? String(single) : defaultValue;
578
+ return single != null ? String(single) : toValue(defaultValue);
573
579
  };
574
580
 
575
581
  return computed<T>({
@@ -580,7 +586,7 @@ export function useRouteQuery<T = string>(
580
586
 
581
587
  const [path = '', queryString = ''] = page.url.split('?');
582
588
  const query = qs.parse(queryString);
583
- if (nextRaw === defaultValue) {
589
+ if (nextRaw === toValue(defaultValue)) {
584
590
  delete query[key]; // keep URLs clean at the default
585
591
  } else {
586
592
  query[key] = nextRaw;
@@ -765,6 +771,14 @@ useQueryObject(filters, { only: ['invoices'], debounce: { search: 300 } });
765
771
  // partial reload and the server re-renders the `invoices` prop.
766
772
  ```
767
773
 
774
+ > **The filters object never carries `page` / `per_page`.** Those keys have
775
+ > their own URL writers (the `page` / `perPage` refs of
776
+ > `usePaginatedResponseContext`, or `useRouteQuery`). Put the page ref in the
777
+ > object too and a pager click visits twice: once through the ref, once
778
+ > through this watcher. And `resetPage` stops working: `navigate()` deletes
779
+ > `page` from the query, then writes the object's value back, so a filter
780
+ > change keeps the old page, possibly past the last one.
781
+
768
782
  > **Typing: debounce the key, not the page.** Without `debounce`, "an
769
783
  > Inertia visit per change" is literal: a text field bound straight to
770
784
  > `filters.search` fires one `router.visit` per keystroke (the watcher does
@@ -799,9 +813,10 @@ the context, later callers join it — no provider component required.
799
813
  ### usePaginatedResponseContext
800
814
 
801
815
  Wraps a Laravel paginated prop (`PaginatedResponse<T>`) into a shared
802
- context: `items` (editable until next navigation), `totalItems`,
803
- `totalPages`, and URL-backed `page` / `perPage` refs. On every successful
804
- visit the context re-syncs from the fresh prop.
816
+ context: `items` (editable until the prop changes), `totalItems`,
817
+ `totalPages`, and `page` / `perPage` refs that read what the server answered
818
+ and visit when written (`page` at 1 and `per_page` at the server's default
819
+ leave the URL).
805
820
 
806
821
  ```ts
807
822
  // inertia-helpers/usePaginatedResponseContext.ts
@@ -809,9 +824,16 @@ import { useRouteQuery } from './useRouteQuery';
809
824
  import type { PaginatedResponse } from './types';
810
825
  import { isNotNil } from './utils';
811
826
  import type { PageProps } from '@inertiajs/core';
812
- import { router, usePage } from '@inertiajs/vue3';
827
+ import { usePage } from '@inertiajs/vue3';
813
828
  import { injectLocal, provideLocal } from '@vueuse/core';
814
- import { computed, onScopeDispose, ref, type ComputedRef, type Ref } from 'vue';
829
+ import {
830
+ computed,
831
+ ref,
832
+ watch,
833
+ watchEffect,
834
+ type ComputedRef,
835
+ type Ref,
836
+ } from 'vue';
815
837
 
816
838
  export type PaginatedResponseContext<T> = {
817
839
  totalItems: ComputedRef<number>;
@@ -868,11 +890,11 @@ export const usePaginatedResponseContext = <T = object>(
868
890
  // `{ [key: string]: PaginatedResponse<T> }` doesn't have and fails
869
891
  // `TS2344`. Intersecting with `PageProps` keeps the constraint satisfied
870
892
  // either way, augmented or not.
893
+ const inertiaPage = usePage<
894
+ PageProps & Record<string, PaginatedResponse<T>>
895
+ >();
871
896
  const paginated = computed(
872
- () =>
873
- usePage<PageProps & Record<string, PaginatedResponse<T>>>().props[
874
- dataKey
875
- ] as PaginatedResponse<T>
897
+ () => inertiaPage.props[dataKey] as PaginatedResponse<T>
876
898
  );
877
899
 
878
900
  const pagination = computed(() => readPagination(paginated.value));
@@ -880,11 +902,33 @@ export const usePaginatedResponseContext = <T = object>(
880
902
  const totalItems = computed(() => pagination.value.total);
881
903
  const totalPages = computed(() => pagination.value.lastPage);
882
904
 
883
- const perPage = useRouteQuery('per_page', `${pagination.value.perPage}`, {
884
- transform: Number,
905
+ // A new prop is a new answer (a visit, Back / Forward); a partial reload of
906
+ // another prop keeps this one, and the edits made to `items`.
907
+ watch(paginated, (fresh) => (items.value = fresh.data ?? []));
908
+
909
+ // The server's default page size is what it answers a URL without
910
+ // `per_page`. Until such an answer arrives it is unknown (`''` matches no
911
+ // value), so picking a size never drops the key: a server that capped
912
+ // `?per_page=500` to 100 would otherwise fall back to its default.
913
+ const defaultPerPage = ref('');
914
+ watchEffect(() => {
915
+ const [, queryString = ''] = inertiaPage.url.split('?');
916
+ if (!new URLSearchParams(queryString).has('per_page'))
917
+ defaultPerPage.value = `${pagination.value.perPage}`;
918
+ });
919
+ const pageQuery = useRouteQuery('page', '1');
920
+ const perPageQuery = useRouteQuery('per_page', defaultPerPage);
921
+
922
+ // Both read the server's answer, not the URL: a clamped `?page=99`, a
923
+ // capped `?per_page=500` or a redirect to the bare URL shows what the
924
+ // server sent. Writing one visits, and only when the URL changes.
925
+ const page = computed({
926
+ get: () => pagination.value.current,
927
+ set: (next: number) => (pageQuery.value = `${next}`),
885
928
  });
886
- const page = useRouteQuery('page', `${pagination.value.current}`, {
887
- transform: Number,
929
+ const perPage = computed({
930
+ get: () => pagination.value.perPage,
931
+ set: (next: number) => (perPageQuery.value = `${next}`),
888
932
  });
889
933
 
890
934
  const context: PaginatedResponseContext<T> = {
@@ -895,20 +939,6 @@ export const usePaginatedResponseContext = <T = object>(
895
939
  items,
896
940
  };
897
941
 
898
- // Re-sync from the fresh prop after every successful visit.
899
- const unbind = router.on('success', (event) => {
900
- const props = event.detail.page.props as {
901
- [key: string]: PaginatedResponse<T> | undefined;
902
- };
903
- const data = props[dataKey];
904
- if (!data) return;
905
- const fresh = readPagination(data);
906
- items.value = data.data ?? [];
907
- page.value = fresh.current;
908
- perPage.value = fresh.perPage;
909
- });
910
- onScopeDispose(unbind);
911
-
912
942
  provideLocal(toContextKey(dataKey), context);
913
943
 
914
944
  return context;
@@ -933,20 +963,6 @@ return Inertia::render('Admin/Users/Index', [
933
963
  one while a next page exists) and `totalPages` ends at the next page, so a
934
964
  pager shows "next" until the last page.
935
965
 
936
- > **`router.on(...)` subscribes to a global, module-level event bus — it
937
- > outlives the component that registered it unless you unbind it.** Inertia
938
- > page components are destroyed and recreated on every visit, but
939
- > `router.on()` itself is not scoped to any of them: skip the `unbind` and
940
- > every past visit's listener is still live, still firing, and still
941
- > writing into a ref that belongs to a page nobody can see anymore. A
942
- > hand-rolled `router.on('start'/'finish')` loading flag on three list
943
- > screens without this call is not three small leaks — it's three
944
- > permanently-growing sets of listeners, one pair added per visit, for the
945
- > life of the tab. Always capture the return value and pass it to
946
- > `onScopeDispose()` — as shown above, and in every `router.on(...)` example
947
- > in this guide — the same call whether the composable happens to run
948
- > inside a component's `setup()` or a plain reactive effect scope.
949
-
950
966
  ### useTableSelectionContext
951
967
 
952
968
  Shared selection state by key, in server terms: `selected` and `unselected`
@@ -1395,10 +1411,10 @@ export const useConfirmOnRouteLeave = ({
1395
1411
  })();
1396
1412
  });
1397
1413
 
1398
- // Same `unbind` contract as `usePaginatedResponseContext` above — see the
1399
- // warning there. `onScopeDispose` over `onUnmounted`: it fires on
1400
- // unmount too (`setup()` runs inside a component's own effect scope),
1401
- // but also works if this composable is ever called from outside one.
1414
+ // `router.on` is a global bus that outlives this component: unbind it.
1415
+ // `onScopeDispose` over `onUnmounted`: it fires on unmount too (`setup()`
1416
+ // runs inside a component's own effect scope), but also works if this
1417
+ // composable is ever called from outside one.
1402
1418
  onScopeDispose(unbind);
1403
1419
  };
1404
1420
  ```
@@ -1408,6 +1424,20 @@ Inertia's `before` event on hover too, and the guard lets them through (they
1408
1424
  leave nothing). The visit "Discard changes" re-sends is a plain one, never a
1409
1425
  prefetch or an `async` visit.
1410
1426
 
1427
+ > **`router.on(...)` subscribes to a global, module-level event bus — it
1428
+ > outlives the component that registered it unless you unbind it.** Inertia
1429
+ > page components are destroyed and recreated on every visit, but
1430
+ > `router.on()` itself is not scoped to any of them: skip the `unbind` and
1431
+ > every past visit's listener is still live, still firing, and still
1432
+ > writing into a ref that belongs to a page nobody can see anymore. A
1433
+ > hand-rolled `router.on('start'/'finish')` loading flag on three list
1434
+ > screens without this call is not three small leaks — it's three
1435
+ > permanently-growing sets of listeners, one pair added per visit, for the
1436
+ > life of the tab. Always capture the return value and pass it to
1437
+ > `onScopeDispose()` — as shown above — the same call whether the composable
1438
+ > happens to run inside a component's `setup()` or a plain reactive effect
1439
+ > scope.
1440
+
1411
1441
  The dialog's words and look are BbConfirm's own options — `title`, `text`,
1412
1442
  `yes`, `no` (a label, or a full button config) and `variant` — defaulting to
1413
1443
  English (`'Discard changes'` / `'Keep editing'`, `variant: 'destructive'`).