bitboss-ui 3.0.0-beta.65 → 3.0.0-beta.66

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 (528) hide show
  1. package/README.md +78 -16
  2. package/bin/bitboss-ui-mcp.mjs +8 -8
  3. package/bin/bitboss-ui.mjs +73 -12
  4. package/dist/ai/BbAccordion.md +4 -3
  5. package/dist/ai/BbAlert.md +1 -1
  6. package/dist/ai/BbBadge.md +1 -0
  7. package/dist/ai/BbBadgeButton.md +4 -3
  8. package/dist/ai/BbBaseButton.md +25 -20
  9. package/dist/ai/BbBaseCheckboxIcon.md +1 -0
  10. package/dist/ai/BbBaseRadioIcon.md +1 -0
  11. package/dist/ai/BbBaseSwitchIcon.md +1 -0
  12. package/dist/ai/BbBreadcrumbs.md +8 -0
  13. package/dist/ai/BbButton.md +67 -21
  14. package/dist/ai/BbCalendar.md +56 -3
  15. package/dist/ai/BbCheckbox.md +1 -1
  16. package/dist/ai/BbCheckboxGroup.md +44 -8
  17. package/dist/ai/BbColorInput.md +3 -2
  18. package/dist/ai/BbColorPalette.md +7 -3
  19. package/dist/ai/BbConfirm.md +36 -80
  20. package/dist/ai/BbConfirmPortal.md +1 -1
  21. package/dist/ai/BbDatePicker.md +41 -5
  22. package/dist/ai/BbDatePickerInput.md +38 -6
  23. package/dist/ai/BbDialog.md +63 -58
  24. package/dist/ai/BbDropdown.md +25 -24
  25. package/dist/ai/BbDropdownButton.md +5 -12
  26. package/dist/ai/BbDropzone.md +2 -3
  27. package/dist/ai/BbForm.md +66 -42
  28. package/dist/ai/BbHost.md +29 -41
  29. package/dist/ai/BbIcon.md +3 -0
  30. package/dist/ai/BbNumberInput.md +2 -2
  31. package/dist/ai/BbOffCanvas.md +16 -9
  32. package/dist/ai/BbPagination.md +17 -17
  33. package/dist/ai/BbPopover.md +8 -3
  34. package/dist/ai/BbPtScope.md +5 -5
  35. package/dist/ai/BbRadio.md +1 -1
  36. package/dist/ai/BbRadioGroup.md +44 -7
  37. package/dist/ai/BbRating.md +1 -0
  38. package/dist/ai/BbSelect.md +146 -21
  39. package/dist/ai/BbSelectPopover.md +16 -12
  40. package/dist/ai/BbSlider.md +5 -3
  41. package/dist/ai/BbSwitch.md +1 -1
  42. package/dist/ai/BbTable.md +51 -39
  43. package/dist/ai/BbTabs.md +127 -63
  44. package/dist/ai/BbTabsList.md +4 -2
  45. package/dist/ai/BbTabsPanels.md +3 -1
  46. package/dist/ai/BbTabsRoot.md +4 -4
  47. package/dist/ai/BbTag.md +2 -2
  48. package/dist/ai/BbTextInput.md +23 -9
  49. package/dist/ai/BbTextarea.md +3 -3
  50. package/dist/ai/BbTimePicker.md +5 -4
  51. package/dist/ai/BbTimePickerInput.md +3 -3
  52. package/dist/ai/BbToast.md +33 -87
  53. package/dist/ai/BbToastPortal.md +1 -1
  54. package/dist/ai/CommonFieldInput.md +2 -1
  55. package/dist/ai/FlatListBox.md +1 -1
  56. package/dist/ai/GroupedListBox.md +1 -1
  57. package/dist/ai/ListBox.md +1 -1
  58. package/dist/ai/OptionsContainer.md +1 -1
  59. package/dist/ai/changelog.json +366 -4
  60. package/dist/ai/components.json +87 -83
  61. package/dist/ai/composables/{useBbDialogContext.md → useBbDialog.md} +18 -18
  62. package/dist/ai/composables/{useBbDropdownContext.md → useBbDropdown.md} +31 -31
  63. package/dist/ai/composables/{useBbFormContext.md → useBbForm.md} +11 -11
  64. package/dist/ai/composables/useBbFormField.md +2 -2
  65. package/dist/ai/composables/{useBbOffCanvasContext.md → useBbOffCanvas.md} +13 -13
  66. package/dist/ai/composables/{useBbTableContext.md → useBbTable.md} +20 -20
  67. package/dist/ai/composables/{useBbTabsContext.md → useBbTabs.md} +12 -12
  68. package/dist/ai/composables/useConfirm.md +42 -54
  69. package/dist/ai/composables/useToast.md +9 -26
  70. package/dist/ai/guides/agent-contract.md +57 -43
  71. package/dist/ai/guides/ai-router.md +1 -1
  72. package/dist/ai/guides/app-layout.md +32 -23
  73. package/dist/ai/guides/coherence-playbook.md +4 -2
  74. package/dist/ai/guides/component-picker.md +35 -32
  75. package/dist/ai/guides/design-language.md +26 -12
  76. package/dist/ai/guides/design-tokens.md +73 -32
  77. package/dist/ai/guides/eslint-rules.md +8 -4
  78. package/dist/ai/guides/fetch-items-playbook.md +3 -3
  79. package/dist/ai/guides/floating-bottom-panel.md +1 -1
  80. package/dist/ai/guides/inertia-helpers.md +661 -210
  81. package/dist/ai/guides/installation-and-plugin-setup.md +6 -3
  82. package/dist/ai/guides/migration/adoption-checklist.md +44 -2
  83. package/dist/ai/guides/migration/components/bb-dialog.md +13 -13
  84. package/dist/ai/guides/migration/components/bb-dropdown.md +16 -16
  85. package/dist/ai/guides/migration/components/bb-host.md +15 -14
  86. package/dist/ai/guides/migration/components/bb-offcanvas.md +10 -10
  87. package/dist/ai/guides/migration/components/bb-pagination.md +9 -9
  88. package/dist/ai/guides/migration/components/bb-select.md +1 -1
  89. package/dist/ai/guides/migration/components/bb-table.md +12 -12
  90. package/dist/ai/guides/migration/components/bb-tabs.md +1 -1
  91. package/dist/ai/guides/migration/from-async-validator.md +9 -9
  92. package/dist/ai/guides/migration/v2-to-v3.md +158 -13
  93. package/dist/ai/guides/options-items-playbook.md +2 -2
  94. package/dist/ai/guides/page-shell.md +15 -3
  95. package/dist/ai/guides/passthrough.md +9 -5
  96. package/dist/ai/guides/preset-components.md +102 -43
  97. package/dist/ai/guides/typescript-generic-components.md +21 -5
  98. package/dist/ai/guides/validated-forms.md +20 -11
  99. package/dist/ai/guides/validation-providers.md +3 -3
  100. package/dist/ai/helpers/definePreset.json +11 -4
  101. package/dist/ai/helpers/definePreset.ts +98 -41
  102. package/dist/ai/helpers/inertia/manifest.json +234 -76
  103. package/dist/ai/helpers/inertia/useConfirmOnRouteLeave.ts +24 -12
  104. package/dist/ai/helpers/inertia/usePromiseForm.ts +38 -151
  105. package/dist/ai/helpers/inertia/usePromiseRouter.ts +295 -0
  106. package/dist/ai/helpers/inertia/useQueryObject.ts +36 -5
  107. package/dist/ai/helpers/inertia/useRouteQuery.ts +28 -9
  108. package/dist/ai/helpers/inertia/utils.ts +53 -10
  109. package/dist/ai/index.md +15 -15
  110. package/dist/ai/manifest/common.json +2 -1
  111. package/dist/ai/manifest/components/BbAccordion.tree.json +3 -1
  112. package/dist/ai/manifest/components/BbAlert.json +1 -1
  113. package/dist/ai/manifest/components/BbBadge.tree.json +3 -1
  114. package/dist/ai/manifest/components/BbBadgeButton.json +9 -4
  115. package/dist/ai/manifest/components/BbBadgeButton.tree.json +1 -0
  116. package/dist/ai/manifest/components/BbBaseButton.json +9 -4
  117. package/dist/ai/manifest/components/BbBaseCheckboxIcon.tree.json +3 -1
  118. package/dist/ai/manifest/components/BbBaseRadioIcon.tree.json +3 -1
  119. package/dist/ai/manifest/components/BbBaseSwitchIcon.tree.json +3 -1
  120. package/dist/ai/manifest/components/BbBreadcrumbs.tree.json +7 -3
  121. package/dist/ai/manifest/components/BbButton.json +9 -4
  122. package/dist/ai/manifest/components/BbButton.tree.json +5 -3
  123. package/dist/ai/manifest/components/BbCalendar.json +4 -3
  124. package/dist/ai/manifest/components/BbCalendar.tree.json +10 -1
  125. package/dist/ai/manifest/components/BbCheckbox.json +1 -1
  126. package/dist/ai/manifest/components/BbCheckbox.tree.json +1 -1
  127. package/dist/ai/manifest/components/BbCheckboxGroup.json +1 -1
  128. package/dist/ai/manifest/components/BbCheckboxGroup.tree.json +62 -3
  129. package/dist/ai/manifest/components/BbCollapsible.json +4 -1
  130. package/dist/ai/manifest/components/BbColorInput.json +1 -1
  131. package/dist/ai/manifest/components/BbColorInput.tree.json +5 -3
  132. package/dist/ai/manifest/components/BbColorPalette.json +3 -0
  133. package/dist/ai/manifest/components/BbColorPalette.tree.json +7 -2
  134. package/dist/ai/manifest/components/BbConfirm.tree.json +2 -2
  135. package/dist/ai/manifest/components/BbDatePicker.json +7 -3
  136. package/dist/ai/manifest/components/BbDatePicker.tree.json +3 -4
  137. package/dist/ai/manifest/components/BbDatePickerInput.json +4 -3
  138. package/dist/ai/manifest/components/BbDatePickerInput.tree.json +5 -3
  139. package/dist/ai/manifest/components/BbDialog.json +1 -1
  140. package/dist/ai/manifest/components/BbDialog.tree.json +2 -2
  141. package/dist/ai/manifest/components/BbDropdown.json +3 -3
  142. package/dist/ai/manifest/components/BbDropdown.tree.json +2 -2
  143. package/dist/ai/manifest/components/BbDropdownButton.json +11 -6
  144. package/dist/ai/manifest/components/BbDropdownButton.tree.json +2 -3
  145. package/dist/ai/manifest/components/BbDropzone.json +4 -1
  146. package/dist/ai/manifest/components/BbForm.json +2 -2
  147. package/dist/ai/manifest/components/BbHost.json +1 -1
  148. package/dist/ai/manifest/components/BbHost.tree.json +1 -1
  149. package/dist/ai/manifest/components/BbHoverCard.json +1 -1
  150. package/dist/ai/manifest/components/BbNumberInput.json +1 -1
  151. package/dist/ai/manifest/components/BbNumberInput.tree.json +1 -1
  152. package/dist/ai/manifest/components/BbOffCanvas.json +1 -1
  153. package/dist/ai/manifest/components/BbOffCanvas.tree.json +3 -1
  154. package/dist/ai/manifest/components/BbPagination.json +4 -4
  155. package/dist/ai/manifest/components/BbPagination.tree.json +2 -1
  156. package/dist/ai/manifest/components/BbPopover.json +1 -1
  157. package/dist/ai/manifest/components/BbPopover.tree.json +1 -1
  158. package/dist/ai/manifest/components/BbProgress.json +4 -1
  159. package/dist/ai/manifest/components/BbRadio.json +1 -1
  160. package/dist/ai/manifest/components/BbRadio.tree.json +1 -1
  161. package/dist/ai/manifest/components/BbRadioGroup.json +5 -5
  162. package/dist/ai/manifest/components/BbRadioGroup.tree.json +62 -3
  163. package/dist/ai/manifest/components/BbRating.tree.json +3 -1
  164. package/dist/ai/manifest/components/BbSelect.json +5 -5
  165. package/dist/ai/manifest/components/BbSelect.tree.json +3 -3
  166. package/dist/ai/manifest/components/BbSelectPopover.json +7 -3
  167. package/dist/ai/manifest/components/BbSelectPopover.tree.json +2 -2
  168. package/dist/ai/manifest/components/BbSlider.json +3 -3
  169. package/dist/ai/manifest/components/BbSlider.tree.json +3 -0
  170. package/dist/ai/manifest/components/BbSmoothHeight.json +4 -1
  171. package/dist/ai/manifest/components/BbSwitch.json +1 -1
  172. package/dist/ai/manifest/components/BbSwitch.tree.json +1 -1
  173. package/dist/ai/manifest/components/BbSwitchGroup.tree.json +1 -1
  174. package/dist/ai/manifest/components/BbTable.json +6 -2
  175. package/dist/ai/manifest/components/BbTable.tree.json +4 -1
  176. package/dist/ai/manifest/components/BbTabs.json +9 -12
  177. package/dist/ai/manifest/components/BbTabs.tree.json +4 -1
  178. package/dist/ai/manifest/components/BbTabsList.json +4 -7
  179. package/dist/ai/manifest/components/BbTabsList.tree.json +4 -1
  180. package/dist/ai/manifest/components/BbTabsPanels.json +1 -1
  181. package/dist/ai/manifest/components/BbTabsPanels.tree.json +4 -1
  182. package/dist/ai/manifest/components/BbTabsRoot.json +5 -5
  183. package/dist/ai/manifest/components/BbTag.json +1 -1
  184. package/dist/ai/manifest/components/BbTag.tree.json +2 -2
  185. package/dist/ai/manifest/components/BbTextInput.json +4 -4
  186. package/dist/ai/manifest/components/BbTextInput.tree.json +1 -1
  187. package/dist/ai/manifest/components/BbTextarea.json +2 -2
  188. package/dist/ai/manifest/components/BbTextarea.tree.json +1 -1
  189. package/dist/ai/manifest/components/BbTimePicker.json +4 -1
  190. package/dist/ai/manifest/components/BbTimePicker.tree.json +5 -3
  191. package/dist/ai/manifest/components/BbTimePickerInput.json +2 -2
  192. package/dist/ai/manifest/components/BbTimePickerInput.tree.json +5 -3
  193. package/dist/ai/manifest/components/BbToast.json +1 -1
  194. package/dist/ai/manifest/components/BbToast.tree.json +3 -1
  195. package/dist/ai/manifest/components/BbTooltip.json +3 -0
  196. package/dist/ai/manifest/components/ChipsBox.tree.json +1 -1
  197. package/dist/ai/manifest/components/CommonField.tree.json +1 -0
  198. package/dist/ai/manifest/components/CommonFieldInput.tree.json +4 -2
  199. package/dist/ai/manifest/components/CommonTimeSelector.tree.json +1 -0
  200. package/dist/ai/manifest/components/FlatListBox.json +1 -1
  201. package/dist/ai/manifest/components/GroupedListBox.json +1 -1
  202. package/dist/ai/manifest/components/ListBox.json +1 -1
  203. package/dist/ai/manifest/components/OptionsContainer.json +2 -2
  204. package/dist/ai/manifest/index.json +3 -3
  205. package/dist/ai/manifest/meta.json +31 -16
  206. package/dist/ai/manifest/types.advanced.json +15 -11
  207. package/dist/ai/manifest/types.api.json +2 -2
  208. package/dist/ai/recipes/inertia/approvals-inbox.md +86 -115
  209. package/dist/ai/recipes/inertia/inline-edit-workspace.md +112 -120
  210. package/dist/ai/recipes/inertia/layout-scaffold.md +15 -4
  211. package/dist/ai/recipes/inertia/onboarding.md +76 -58
  212. package/dist/ai/recipes/inertia/ownership-atlas.md +74 -105
  213. package/dist/ai/recipes/inertia/record-form.md +18 -7
  214. package/dist/ai/recipes/inertia/records-workspace.md +106 -127
  215. package/dist/ai/recipes/inertia/settings-workspace.md +131 -73
  216. package/dist/ai/recipes/inertia/upload-center.md +97 -121
  217. package/dist/ai/recipes/inertia/wizard-form.md +25 -15
  218. package/dist/ai/recipes/nuxt/approvals-inbox.md +67 -48
  219. package/dist/ai/recipes/nuxt/inline-edit-workspace.md +73 -58
  220. package/dist/ai/recipes/nuxt/layout-scaffold.md +15 -4
  221. package/dist/ai/recipes/nuxt/onboarding.md +27 -10
  222. package/dist/ai/recipes/nuxt/ownership-atlas.md +40 -22
  223. package/dist/ai/recipes/nuxt/record-form.md +20 -7
  224. package/dist/ai/recipes/nuxt/records-workspace.md +120 -96
  225. package/dist/ai/recipes/nuxt/settings-workspace.md +36 -23
  226. package/dist/ai/recipes/nuxt/upload-center.md +63 -37
  227. package/dist/ai/recipes/nuxt/wizard-form.md +28 -16
  228. package/dist/ai/recipes/vue/approvals-inbox.md +74 -46
  229. package/dist/ai/recipes/vue/inline-edit-workspace.md +83 -56
  230. package/dist/ai/recipes/vue/layout-scaffold.md +15 -4
  231. package/dist/ai/recipes/vue/onboarding.md +27 -10
  232. package/dist/ai/recipes/vue/ownership-atlas.md +40 -22
  233. package/dist/ai/recipes/vue/record-form.md +20 -7
  234. package/dist/ai/recipes/vue/records-workspace.md +132 -95
  235. package/dist/ai/recipes/vue/settings-workspace.md +36 -23
  236. package/dist/ai/recipes/vue/upload-center.md +73 -37
  237. package/dist/ai/recipes/vue/wizard-form.md +28 -16
  238. package/dist/ai/source/BbAccordion.md +36 -6
  239. package/dist/ai/source/BbAlert.md +11 -5
  240. package/dist/ai/source/BbAsterisk.md +4 -1
  241. package/dist/ai/source/BbAvatar.md +11 -5
  242. package/dist/ai/source/BbBadge.md +42 -11
  243. package/dist/ai/source/BbBadgeButton.md +41 -8
  244. package/dist/ai/source/BbBaseButton.md +57 -15
  245. package/dist/ai/source/BbBaseCheckboxIcon.md +37 -13
  246. package/dist/ai/source/BbBaseRadioIcon.md +32 -9
  247. package/dist/ai/source/BbBaseSwitchIcon.md +31 -7
  248. package/dist/ai/source/BbBreadcrumbs.md +32 -9
  249. package/dist/ai/source/BbButton.md +91 -27
  250. package/dist/ai/source/BbCalendar.md +571 -300
  251. package/dist/ai/source/BbCheckbox.md +18 -7
  252. package/dist/ai/source/BbCheckboxGroup.md +16 -5
  253. package/dist/ai/source/BbCollapsible.md +15 -6
  254. package/dist/ai/source/BbColorInput.md +68 -20
  255. package/dist/ai/source/BbColorPalette.md +107 -23
  256. package/dist/ai/source/BbConfirmPortal.md +1 -1
  257. package/dist/ai/source/BbDatePicker.md +106 -25
  258. package/dist/ai/source/BbDatePickerInput.md +105 -42
  259. package/dist/ai/source/BbDialog.md +60 -44
  260. package/dist/ai/source/BbDropdown.md +44 -32
  261. package/dist/ai/source/BbDropdownButton.md +26 -20
  262. package/dist/ai/source/BbDropdownGroup.md +5 -5
  263. package/dist/ai/source/BbDropzone.md +53 -16
  264. package/dist/ai/source/BbForm.md +18 -7
  265. package/dist/ai/source/BbHost.md +25 -12
  266. package/dist/ai/source/BbHoverCard.md +20 -9
  267. package/dist/ai/source/BbIcon.md +9 -3
  268. package/dist/ai/source/BbIndicator.md +11 -4
  269. package/dist/ai/source/BbNumberInput.md +23 -6
  270. package/dist/ai/source/BbOffCanvas.md +73 -32
  271. package/dist/ai/source/BbPagination.md +59 -31
  272. package/dist/ai/source/BbPopover.md +28 -16
  273. package/dist/ai/source/BbProgress.md +13 -5
  274. package/dist/ai/source/BbRadio.md +16 -9
  275. package/dist/ai/source/BbRadioGroup.md +15 -4
  276. package/dist/ai/source/BbRating.md +51 -10
  277. package/dist/ai/source/BbSelect.md +56 -27
  278. package/dist/ai/source/BbSelectPopover.md +81 -35
  279. package/dist/ai/source/BbSlider.md +111 -33
  280. package/dist/ai/source/BbSmoothHeight.md +16 -7
  281. package/dist/ai/source/BbSpinner.md +9 -3
  282. package/dist/ai/source/BbSwitch.md +16 -9
  283. package/dist/ai/source/BbSwitchGroup.md +18 -7
  284. package/dist/ai/source/BbTable.md +172 -38
  285. package/dist/ai/source/BbTabs.md +58 -40
  286. package/dist/ai/source/BbTabsList.md +109 -50
  287. package/dist/ai/source/BbTabsPanels.md +65 -31
  288. package/dist/ai/source/BbTabsRoot.md +35 -24
  289. package/dist/ai/source/BbTag.md +18 -4
  290. package/dist/ai/source/BbTextInput.md +20 -3
  291. package/dist/ai/source/BbTextarea.md +15 -1
  292. package/dist/ai/source/BbTimePicker.md +81 -21
  293. package/dist/ai/source/BbTimePickerInput.md +63 -15
  294. package/dist/ai/source/BbToast.md +20 -3
  295. package/dist/ai/source/BbToastPortal.md +21 -4
  296. package/dist/ai/source/BbTooltip.md +16 -8
  297. package/dist/ai/source/BbTree.md +10 -3
  298. package/dist/ai/source/ClearableButton.md +5 -1
  299. package/dist/ai/source/CommonField.md +65 -9
  300. package/dist/ai/source/CommonFieldInput.md +61 -27
  301. package/dist/ai/source/CommonPopover.md +17 -6
  302. package/dist/ai/source/CommonTimeSelector.md +21 -2
  303. package/dist/ai/source/ErrorIcon.md +4 -0
  304. package/dist/ai/source/ListBox.md +9 -1
  305. package/dist/ai/source/OptionsContainer.md +5 -1
  306. package/dist/ai/source/WarningIcon.md +4 -0
  307. package/dist/components/BbAccordion/BbAccordion.vue.d.ts +2 -1
  308. package/dist/components/BbAccordion/BbAccordion.vue_vue_type_script_setup_true_lang.js +6 -6
  309. package/dist/components/BbAlert/BbAlert.vue.d.ts +2 -1
  310. package/dist/components/BbAlert/BbAlert.vue_vue_type_script_setup_true_lang.js +10 -10
  311. package/dist/components/BbAsterisk/BbAsterisk.vue.d.ts +3 -1
  312. package/dist/components/BbAvatar/BbAvatar.vue.d.ts +3 -1
  313. package/dist/components/BbAvatar/BbAvatar.vue_vue_type_script_setup_true_lang.js +7 -7
  314. package/dist/components/BbBadge/BbBadge.vue.d.ts +5 -3
  315. package/dist/components/BbBadge/BbBadge.vue_vue_type_script_setup_true_lang.js +7 -7
  316. package/dist/components/BbBadge/BbBadgeButton.vue.d.ts +3 -1
  317. package/dist/components/BbBadge/BbBadgeButton.vue_vue_type_script_setup_true_lang.js +7 -7
  318. package/dist/components/BbBaseButton/BbBaseButton.vue.d.ts +3 -1
  319. package/dist/components/BbBaseButton/BbBaseButton.vue_vue_type_script_setup_true_lang.js +85 -85
  320. package/dist/components/BbBaseButton/types.d.ts +8 -5
  321. package/dist/components/BbBaseButton/useLinkState.d.ts +2 -0
  322. package/dist/components/BbBaseButton/useLinkState.js +21 -20
  323. package/dist/components/BbBaseCheckboxIcon/BbBaseCheckboxIcon.vue.d.ts +3 -1
  324. package/dist/components/BbBaseRadioIcon/BbBaseRadioIcon.vue.d.ts +3 -1
  325. package/dist/components/BbBaseSwitchIcon/BbBaseSwitchIcon.vue.d.ts +3 -1
  326. package/dist/components/BbBreadcrumbs/BbBreadcrumbs.vue.d.ts +3 -1
  327. package/dist/components/BbBreadcrumbs/BbBreadcrumbs.vue_vue_type_script_setup_true_lang.js +7 -7
  328. package/dist/components/BbButton/BbButton.vue.d.ts +2 -1
  329. package/dist/components/BbButton/BbButton.vue_vue_type_script_setup_true_lang.js +93 -93
  330. package/dist/components/BbButton/types.d.ts +7 -4
  331. package/dist/components/BbCalendar/BbCalendar.vue.d.ts +157 -30
  332. package/dist/components/BbCalendar/BbCalendar.vue_vue_type_script_setup_true_lang.js +364 -331
  333. package/dist/components/BbCalendar/CalendarMonthPanel.vue_vue_type_script_setup_true_lang.js +5 -5
  334. package/dist/components/BbCalendar/types.d.ts +36 -8
  335. package/dist/components/BbCalendar/useCalendarGrid.d.ts +133 -0
  336. package/dist/components/BbCalendar/useCalendarGrid.js +193 -183
  337. package/dist/components/BbCalendar/useDayGrid.d.ts +24 -19
  338. package/dist/components/BbCalendar/useDayGrid.js +105 -102
  339. package/dist/components/BbCheckbox/BbCheckbox.vue.d.ts +4 -2
  340. package/dist/components/BbCheckboxGroup/BbCheckboxGroup.vue.d.ts +327 -2
  341. package/dist/components/BbCollapsible/BbCollapsible.vue.d.ts +3 -1
  342. package/dist/components/BbCollapsible/BbCollapsible.vue_vue_type_script_setup_true_lang.js +6 -6
  343. package/dist/components/BbColorInput/BbColorInput.vue.d.ts +8 -5
  344. package/dist/components/BbColorInput/BbColorInput.vue_vue_type_script_setup_true_lang.js +5 -5
  345. package/dist/components/BbColorInput/types.d.ts +2 -0
  346. package/dist/components/BbColorPalette/BbColorPalette.vue.d.ts +7 -5
  347. package/dist/components/BbColorPalette/BbColorPalette.vue_vue_type_script_setup_true_lang.js +216 -215
  348. package/dist/components/BbConfirm/BbConfirm.vue_vue_type_script_setup_true_lang.js +25 -25
  349. package/dist/components/BbDatePicker/BbDatePicker.vue.d.ts +206 -41
  350. package/dist/components/BbDatePicker/BbDatePicker.vue_vue_type_script_setup_true_lang.js +112 -106
  351. package/dist/components/BbDatePicker/types.d.ts +27 -8
  352. package/dist/components/BbDatePickerInput/BbDatePickerInput.vue.d.ts +519 -37
  353. package/dist/components/BbDatePickerInput/BbDatePickerInput.vue_vue_type_script_setup_true_lang.js +11 -8
  354. package/dist/components/BbDatePickerInput/types.d.ts +31 -9
  355. package/dist/components/BbDialog/BbDialog.vue.d.ts +6 -5
  356. package/dist/components/BbDialog/BbDialog.vue_vue_type_script_setup_true_lang.js +231 -233
  357. package/dist/components/BbDialog/types.d.ts +7 -7
  358. package/dist/components/BbDialog/useDialogStack.d.ts +2 -0
  359. package/dist/components/BbDialog/useDialogStack.js +6 -2
  360. package/dist/components/BbDropdown/AdaptiveDropdown.vue_vue_type_script_setup_true_lang.js +25 -25
  361. package/dist/components/BbDropdown/BbDropdown.vue.d.ts +8 -6
  362. package/dist/components/BbDropdown/BbDropdown.vue_vue_type_script_setup_true_lang.js +226 -225
  363. package/dist/components/BbDropdown/BbDropdownList.vue_vue_type_script_setup_true_lang.js +49 -49
  364. package/dist/components/BbDropdown/DropdownPipelineResolver.vue_vue_type_script_setup_true_lang.js +7 -7
  365. package/dist/components/BbDropdown/normalizeGroups.js +14 -14
  366. package/dist/components/BbDropdown/types.d.ts +5 -5
  367. package/dist/components/BbDropdown/useDropdownContext.js +1 -1
  368. package/dist/components/BbDropdown/useDropdownGroupRegistry.d.ts +1 -1
  369. package/dist/components/BbDropdownButton/BbDropdownButton.vue.d.ts +6 -4
  370. package/dist/components/BbDropdownButton/BbDropdownButton.vue_vue_type_script_setup_true_lang.js +36 -38
  371. package/dist/components/BbDropdownButton/types.js +4 -4
  372. package/dist/components/BbDropzone/BbDropzone.vue.d.ts +57 -22
  373. package/dist/components/BbDropzone/BbDropzone.vue_vue_type_script_setup_true_lang.js +4 -4
  374. package/dist/components/BbDropzone/types.d.ts +16 -4
  375. package/dist/components/BbForm/BbForm.vue.d.ts +52 -4
  376. package/dist/components/BbForm/BbForm.vue_vue_type_script_setup_true_lang.js +1 -1
  377. package/dist/components/BbHost/BbHost.vue_vue_type_script_setup_true_lang.js +19 -23
  378. package/dist/components/BbHost/BbHostOpening.js +1 -1
  379. package/dist/components/BbHoverCard/BbHoverCard.vue.d.ts +5 -4
  380. package/dist/components/BbHoverCard/BbHoverCard.vue_vue_type_script_setup_true_lang.js +116 -116
  381. package/dist/components/BbIcon/BbIcon.vue.d.ts +3 -1
  382. package/dist/components/BbIcon/BbIcon.vue_vue_type_script_setup_true_lang.js +7 -7
  383. package/dist/components/BbIndicator/BbIndicator.vue.d.ts +3 -1
  384. package/dist/components/BbNumberInput/BbNumberInput.vue.d.ts +6 -3
  385. package/dist/components/BbNumberInput/types.d.ts +2 -0
  386. package/dist/components/BbOffCanvas/BbOffCanvas.vue.d.ts +5 -4
  387. package/dist/components/BbOffCanvas/BbOffCanvas.vue_vue_type_script_setup_true_lang.js +366 -369
  388. package/dist/components/BbOffCanvas/sheetAttrs.d.ts +9 -0
  389. package/dist/components/BbOffCanvas/sheetAttrs.js +10 -0
  390. package/dist/components/BbOffCanvas/types.d.ts +7 -7
  391. package/dist/components/BbOffCanvas/useOffCanvasStack.d.ts +2 -0
  392. package/dist/components/BbOffCanvas/useOffCanvasStack.js +7 -3
  393. package/dist/components/BbPagination/BbPagination.vue.d.ts +2 -1
  394. package/dist/components/BbPagination/BbPagination.vue_vue_type_script_setup_true_lang.js +8 -8
  395. package/dist/components/BbPagination/types.d.ts +5 -5
  396. package/dist/components/BbPopover/BbPopover.vue.d.ts +5 -4
  397. package/dist/components/BbPopover/BbPopover.vue_vue_type_script_setup_true_lang.js +92 -91
  398. package/dist/components/BbProgress/BbProgress.vue.d.ts +6 -1
  399. package/dist/components/BbRadio/BbRadio.vue.d.ts +4 -2
  400. package/dist/components/BbRadioGroup/BbRadioGroup.vue.d.ts +281 -1
  401. package/dist/components/BbRating/BbRating.vue.d.ts +4 -2
  402. package/dist/components/BbRating/BbRating.vue_vue_type_script_setup_true_lang.js +7 -7
  403. package/dist/components/BbSelect/BbSelect.vue.d.ts +575 -4
  404. package/dist/components/BbSelect/BbSelect.vue_vue_type_script_setup_true_lang.js +7 -7
  405. package/dist/components/BbSelect/types.d.ts +12 -2
  406. package/dist/components/BbSelectPopover/BbSelectPopover.vue.d.ts +105 -3
  407. package/dist/components/BbSelectPopover/BbSelectPopover.vue_vue_type_script_setup_true_lang.js +688 -685
  408. package/dist/components/BbSelectPopover/types.d.ts +9 -1
  409. package/dist/components/BbSlider/BbSlider.vue.d.ts +135 -33
  410. package/dist/components/BbSlider/BbSlider.vue_vue_type_script_setup_true_lang.js +5 -5
  411. package/dist/components/BbSlider/types.d.ts +19 -4
  412. package/dist/components/BbSmoothHeight/BbSmoothHeight.vue.d.ts +3 -1
  413. package/dist/components/BbSpinner/BbSpinner.vue.d.ts +3 -1
  414. package/dist/components/BbSwitch/BbSwitch.vue.d.ts +4 -2
  415. package/dist/components/BbSwitchGroup/BbSwitchGroup.vue.d.ts +131 -1
  416. package/dist/components/BbTable/BbTable.vue.d.ts +5 -2
  417. package/dist/components/BbTable/BbTable.vue_vue_type_script_setup_true_lang.js +593 -578
  418. package/dist/components/BbTable/types.d.ts +14 -1
  419. package/dist/components/BbTable/utils.d.ts +2 -1
  420. package/dist/components/BbTable/utils.js +37 -38
  421. package/dist/components/BbTabs/BbTabs.vue.d.ts +96 -2
  422. package/dist/components/BbTabs/BbTabs.vue_vue_type_script_setup_true_lang.js +8 -6
  423. package/dist/components/BbTabs/BbTabsList.vue.d.ts +11 -1
  424. package/dist/components/BbTabs/BbTabsList.vue_vue_type_script_setup_true_lang.js +102 -92
  425. package/dist/components/BbTabs/BbTabsPanels.vue.d.ts +9 -1
  426. package/dist/components/BbTabs/BbTabsPanels.vue_vue_type_script_setup_true_lang.js +20 -17
  427. package/dist/components/BbTabs/BbTabsRoot.vue_vue_type_script_setup_true_lang.js +1 -1
  428. package/dist/components/BbTabs/types.d.ts +34 -23
  429. package/dist/components/BbTag/BbTag.vue.d.ts +5 -2
  430. package/dist/components/BbTag/types.d.ts +2 -0
  431. package/dist/components/BbTextInput/BbTextInput.vue.d.ts +195 -2
  432. package/dist/components/BbTextInput/BbTextInput.vue_vue_type_script_setup_true_lang.js +5 -5
  433. package/dist/components/BbTextInput/types.d.ts +2 -0
  434. package/dist/components/BbTextarea/BbTextarea.vue.d.ts +193 -2
  435. package/dist/components/BbTextarea/types.d.ts +2 -0
  436. package/dist/components/BbTimePicker/BbTimePicker.vue.d.ts +78 -38
  437. package/dist/components/BbTimePicker/BbTimePicker.vue_vue_type_script_setup_true_lang.js +138 -137
  438. package/dist/components/BbTimePicker/types.d.ts +18 -4
  439. package/dist/components/BbTimePickerInput/BbTimePickerInput.vue.d.ts +272 -33
  440. package/dist/components/BbTimePickerInput/BbTimePickerInput.vue_vue_type_script_setup_true_lang.js +16 -16
  441. package/dist/components/BbTimePickerInput/types.d.ts +20 -5
  442. package/dist/components/BbToast/BbToastMessage.vue_vue_type_script_setup_true_lang.js +6 -6
  443. package/dist/components/BbToast/BbToastRegion.vue_vue_type_script_setup_true_lang.js +20 -20
  444. package/dist/components/BbTooltip/BbTooltip.vue.d.ts +3 -2
  445. package/dist/components/BbTooltip/BbTooltip.vue_vue_type_script_setup_true_lang.js +109 -109
  446. package/dist/components/BbTree/BbTree.vue.d.ts +1 -1
  447. package/dist/components/ClearableButton/ClearableButton.vue.d.ts +3 -1
  448. package/dist/components/CloseIcon/CloseButton.vue.d.ts +3 -1
  449. package/dist/components/CloseIcon/CloseButton.vue.js +1 -1
  450. package/dist/components/CommonField/CommonField.vue.d.ts +3 -1
  451. package/dist/components/CommonFieldInput/CommonFieldInput.vue.d.ts +5 -3
  452. package/dist/components/CommonPopover/CommonPopover.vue.d.ts +5 -4
  453. package/dist/components/CommonPopover/CommonPopover.vue_vue_type_script_setup_true_lang.js +55 -55
  454. package/dist/components/ErrorIcon/ErrorIcon.vue.d.ts +3 -1
  455. package/dist/components/FlatListBox/FlatListBox.vue_vue_type_script_setup_true_lang.js +124 -124
  456. package/dist/components/GroupedListBox/GroupedListBox.vue_vue_type_script_setup_true_lang.js +71 -71
  457. package/dist/components/ListBox/ListBox.vue.d.ts +1 -1
  458. package/dist/components/OptionsContainer/OptionsContainer.vue.d.ts +1 -1
  459. package/dist/components/OptionsContainer/OptionsContainer.vue_vue_type_script_setup_true_lang.js +4 -4
  460. package/dist/components/Transitions/Slide.vue.d.ts +1 -1
  461. package/dist/components/WarningIcon/WarningIcon.vue.d.ts +3 -1
  462. package/dist/composables/autoHost.d.ts +22 -0
  463. package/dist/composables/autoHost.js +20 -0
  464. package/dist/composables/hostOpenings.d.ts +3 -3
  465. package/dist/composables/hostOpenings.js +1 -1
  466. package/dist/composables/hostRegistry.d.ts +10 -2
  467. package/dist/composables/hostRegistry.js +5 -3
  468. package/dist/composables/overlayRegistry.d.ts +1 -1
  469. package/dist/composables/overlayRegistry.js +2 -2
  470. package/dist/composables/{useBbDialogContext.d.ts → useBbDialog.d.ts} +9 -9
  471. package/dist/composables/{useBbDialogContext.js → useBbDialog.js} +4 -4
  472. package/dist/composables/{useBbDropdownContext.d.ts → useBbDropdown.d.ts} +14 -14
  473. package/dist/composables/{useBbDropdownContext.js → useBbDropdown.js} +2 -2
  474. package/dist/composables/{useBbFormContext.d.ts → useBbForm.d.ts} +8 -8
  475. package/dist/composables/{useBbFormContext.js → useBbForm.js} +3 -3
  476. package/dist/composables/useBbOffCanvas.d.ts +23 -0
  477. package/dist/composables/{useBbOffCanvasContext.js → useBbOffCanvas.js} +3 -3
  478. package/dist/composables/{useBbTableContext.d.ts → useBbTable.d.ts} +29 -29
  479. package/dist/composables/{useBbTableContext.js → useBbTable.js} +2 -2
  480. package/dist/composables/{useBbTabsContext.d.ts → useBbTabs.d.ts} +19 -3
  481. package/dist/composables/useBbTabs.js +266 -0
  482. package/dist/composables/useConfirm.d.ts +6 -7
  483. package/dist/composables/useConfirm.js +1 -1
  484. package/dist/composables/useOnDemandOpener.d.ts +4 -4
  485. package/dist/composables/useOnDemandOpener.js +1 -1
  486. package/dist/composables/useToast.d.ts +4 -5
  487. package/dist/composables/useToast.js +1 -1
  488. package/dist/directives/bbDialog.d.ts +1 -1
  489. package/dist/directives/bbDropdown.js +3 -3
  490. package/dist/directives/bbOffCanvas.d.ts +1 -1
  491. package/dist/directives/overlayTrigger.js +18 -18
  492. package/dist/index.d.ts +15 -15
  493. package/dist/index.js +55 -55
  494. package/dist/llms-full.txt +4355 -2761
  495. package/dist/llms-medium.txt +127 -93
  496. package/dist/llms.txt +12 -12
  497. package/dist/nuxt-auto-imports.js +6 -6
  498. package/dist/nuxt.js +1 -1
  499. package/dist/plugin.js +30 -28
  500. package/dist/runtime/nuxt-plugin.js +30 -28
  501. package/dist/styles.css +2 -2
  502. package/dist/types/ShapeErased.d.ts +15 -0
  503. package/dist/types/fallthrough.d.ts +134 -0
  504. package/dist/utilities/functions/normalizeDateBound.d.ts +7 -5
  505. package/dist/utilities/functions/normalizeDateBound.js +9 -9
  506. package/dist/utils/versionCheck.js +1 -1
  507. package/llms.txt +12 -12
  508. package/package.json +1 -1
  509. package/scripts/lib/adoption-checklist.json +2 -1
  510. package/scripts/lib/css-class-surface.mjs +39 -3
  511. package/scripts/lib/eslint-disable.mjs +9 -1
  512. package/scripts/lib/eslint-plugin.d.ts +7 -1
  513. package/scripts/lib/eslint-plugin.mjs +280 -3
  514. package/scripts/lib/form-v-model.mjs +2 -2
  515. package/scripts/lib/helper-canon.mjs +34 -2
  516. package/scripts/lib/helpers-add.mjs +80 -13
  517. package/scripts/lib/hidden-label-placeholder.mjs +138 -0
  518. package/scripts/lib/html-attributes.mjs +82 -0
  519. package/scripts/lib/idiom-scan.mjs +175 -2
  520. package/scripts/lib/portal-names.mjs +3 -3
  521. package/scripts/lib/prefer-v-bb-dialog.mjs +1 -1
  522. package/scripts/lib/tab-links.mjs +209 -0
  523. package/scripts/lib/token-color-mix.mjs +114 -0
  524. package/scripts/lib/toolchain-check.mjs +34 -3
  525. package/scripts/lib/unstyled-variants.mjs +57 -0
  526. package/scripts/lib/validate-bb-markup.mjs +72 -1
  527. package/dist/composables/useBbOffCanvasContext.d.ts +0 -23
  528. package/dist/composables/useBbTabsContext.js +0 -252
package/README.md CHANGED
@@ -38,20 +38,20 @@ Full detail: `dist/ai/guides/installation-and-plugin-setup.md`.
38
38
 
39
39
  ### Composables
40
40
 
41
- | Composable | Role |
42
- | ----------------------- | --------------------------------------------------------------------- |
43
- | `useBbConfig` | `setConfig()` patches the one runtime-editable kit option: `locale`. |
44
- | `useBbDialogContext` | Open, close and read a `BbDialog` by id (nearest scope). |
45
- | `useBbDropdownContext` | Read a `BbDropdown`'s resolved groups/selections from anywhere by id. |
46
- | `useBbOffCanvasContext` | Open, close and read a `BbOffCanvas` by id (nearest scope). |
47
- | `useBbTableContext` | Imperative handle onto a `BbTable` by id. |
48
- | `useBbTabsContext` | Programmatic tab selection for a `BbTabs` by id. |
49
- | `useConfirm` | Programmatic confirm / modal flows. |
50
- | `useCountdown` | Countdown timer state. |
51
- | `useId` | SSR-safe unique ids. |
52
- | `useMobile` | Mobile / viewport-oriented behaviour. |
53
- | `useSafeArea` | Claim a screen edge for a docked panel so toasts avoid it. |
54
- | `useToast` | Toast notifications API. |
41
+ | Composable | Role |
42
+ | ---------------- | --------------------------------------------------------------------- |
43
+ | `useBbConfig` | `setConfig()` patches the one runtime-editable kit option: `locale`. |
44
+ | `useBbDialog` | Open, close and read a `BbDialog` by id (nearest scope). |
45
+ | `useBbDropdown` | Read a `BbDropdown`'s resolved groups/selections from anywhere by id. |
46
+ | `useBbOffCanvas` | Open, close and read a `BbOffCanvas` by id (nearest scope). |
47
+ | `useBbTable` | Imperative handle onto a `BbTable` by id. |
48
+ | `useBbTabs` | Programmatic tab selection for a `BbTabs` by id. |
49
+ | `useConfirm` | Programmatic confirm / modal flows. |
50
+ | `useCountdown` | Countdown timer state. |
51
+ | `useId` | SSR-safe unique ids. |
52
+ | `useMobile` | Mobile / viewport-oriented behaviour. |
53
+ | `useSafeArea` | Claim a screen edge for a docked panel so toasts avoid it. |
54
+ | `useToast` | Toast notifications API. |
55
55
 
56
56
  ### Utilities
57
57
 
@@ -84,7 +84,7 @@ Product-ready components with labels, hints, errors, and consistent styling:
84
84
  - **Overlays & panels:** `BbDialog`, `BbConfirm`, `BbConfirmPortal`, `BbOffCanvas`, `BbPopover`, `BbHoverCard`
85
85
  - **Data:** `BbTable`, `BbTree`
86
86
  - **Media & files:** `BbAvatar`, `BbDropzone`, `BbIcon`
87
- - **Forms** (`BbForm` needs the `vee-validate` peer; an app without forms needs nothing): `BbForm`, `useBbFormContext`, and the 16 form controls join the form they are inside (plus `rules` / `validation-label` / `validation-mode` / `formless`; the field's path is its `name`, else its label).
87
+ - **Forms** (`BbForm` needs the `vee-validate` peer; an app without forms needs nothing): `BbForm`, `useBbForm`, and the 16 form controls join the form they are inside (plus `rules` / `validation-label` / `validation-mode` / `formless`; the field's path is its `name`, else its label).
88
88
  - **Schema validation, no adapter:** pass a Zod, Valibot, ArkType or Yup schema (any [Standard Schema](https://standardschema.dev)) to `BbForm`'s `schema` as it is. Messages land on the field by path (`address.city`, `lines.0.qty`), `@submit` receives the schema's parsed output typed from the schema, the required asterisk comes from the schema, and a failed submit focuses the first invalid field on screen. Per-step schemas plus `keep-values-on-unmount` cover multi-step wizards. No extra runtime dependency.
89
89
  - **Passthrough scopes:** `BbPtScope` + `definePt` — a named `pt` map applied to one area of the app.
90
90
 
@@ -389,7 +389,6 @@ in place — the rule is a codemod, not just a linter:
389
389
  | `<BbTable :allow-select-all="x" />` | `<BbTable :disable-select-all="!x" />` | polarity inversion |
390
390
  | `<BbTabs :animate-x="false" />` | `<BbTabs disable-animate-x />` | inversion, literal folded |
391
391
  | `<BbSelect allow-writing="not-mobile" />` | `<BbSelect disable-writing="mobile" />` | rename + value remap |
392
- | `<BbHost />` | `<BbHost />` | value map |
393
392
  | `<BbPopover show-arrow />` | `<BbPopover />` | removed & inert → deleted |
394
393
  | `<BbBadge content="5" />` | _(unchanged — reported)_ | needs a slot: manual |
395
394
 
@@ -557,6 +556,14 @@ reports what removing cannot change.
557
556
  `bitboss-ui check` reports the same as `renamed-item-field` and
558
557
  `redundant-item-accessor`.
559
558
 
559
+ #### Tabs as links: `tab-links`
560
+
561
+ A `BbTabs` whose items have `href` / `to` is a `<nav>` of links, each going to
562
+ its own page. `bitboss-ui/tab-links` (error) flags `navigation` on it (a link
563
+ has no query parameter to sync, so it does nothing) and an item with neither
564
+ `href` nor `to` among links (it renders as a disabled link). `bitboss-ui check`
565
+ reports the same as `tab-link-navigation` and `tab-link-missing`.
566
+
560
567
  #### A trigger in BbDropdown's default slot: `dropdown-default-slot`
561
568
 
562
569
  `BbDropdown`'s default slot holds `<BbDropdownGroup>` companions, which render
@@ -604,6 +611,30 @@ script, a switch bound to the same ref and your own components are never
604
611
  reported. `BbAccordion` wires all of it for you.
605
612
  `bitboss-ui check` reports the same as `collapsible-trigger-aria`.
606
613
 
614
+ #### A hidden label with no placeholder: `hidden-label-placeholder`
615
+
616
+ `hide-label` keeps the label for screen readers, but a sighted user then sees
617
+ an empty box. `bitboss-ui/hidden-label-placeholder` (warning) reports a
618
+ library field or select with a static `hide-label` and no `placeholder`:
619
+
620
+ ```vue
621
+ <template>
622
+ <BbSelect
623
+ v-model="status"
624
+ label="Status"
625
+ hide-label
626
+ placeholder="Status"
627
+ :items="statuses"
628
+ />
629
+ </template>
630
+ ```
631
+
632
+ An `aria-labelledby`, a `#prefix` slot and an object `v-bind` count as
633
+ legible; a field inside a `BbTable` / `BbTree` slot (its column header labels
634
+ it) and one at the root of a component's template (the parent lays out its
635
+ label) are not judged. `bitboss-ui check` reports the same as
636
+ `hidden-label-placeholder`, as a warning.
637
+
607
638
  #### A dialog opened through a ref: `prefer-v-bb-dialog`
608
639
 
609
640
  A `ref(false)` whose only jobs are a `BbDialog` / `BbOffCanvas` `v-model` and
@@ -628,6 +659,37 @@ after a save) is reported without a fix: those closes become the slots'
628
659
  toggle) is never reported, since the page needs the state.
629
660
  `bitboss-ui check` reports the same as `prefer-v-bb-dialog` (a warning).
630
661
 
662
+ #### A dialog trigger inside a closing panel: `no-dialog-in-panel`
663
+
664
+ A `v-bb-dialog` (or `v-bb-off-canvas`) button that opens a component on demand
665
+ (`v-bb-dialog="{ component: PersonDialog }"`) in `BbSelect`'s `#empty`, or any
666
+ other slot of a select or dropdown panel, never opens it: the panel closes as
667
+ the dialog takes focus, the slot unmounts with it, and the opening is dismissed
668
+ with its trigger. `bitboss-ui/no-dialog-in-panel` (error) reports it, and any
669
+ bound value that is not a literal id, which may be one. A literal id opens a
670
+ placed `BbDialog` and is fine. Open a component from `<script setup>` instead:
671
+
672
+ ```vue
673
+ <script setup lang="ts">
674
+ import { useBbDialog } from 'bitboss-ui';
675
+ import CreatePersonDialog from './CreatePersonDialog.vue';
676
+
677
+ const personDialog = useBbDialog(CreatePersonDialog);
678
+ </script>
679
+ <template>
680
+ <BbSelect v-model="contactId" :items="people" label="Contact">
681
+ <template #empty="{ query }">
682
+ <BbBaseButton @click="personDialog.show({ name: query })">
683
+ Create {{ query }}
684
+ </BbBaseButton>
685
+ </template>
686
+ </BbSelect>
687
+ </template>
688
+ ```
689
+
690
+ The activators and the field slots (`#append`, `#prepend`…) stay mounted and
691
+ are not reported. No `bitboss-ui check` twin.
692
+
631
693
  #### A rule nobody registered: `no-unregistered-rule`
632
694
 
633
695
  A string rule is a vee-validate rule name, and vee-validate knows only the
@@ -1020,7 +1020,7 @@ function summarizeComponent(entry, manifest) {
1020
1020
  }
1021
1021
  : {}),
1022
1022
  ...(entry.cssProps?.length
1023
- ? { cssProps: entry.cssProps.map((c) => c.name ?? c) }
1023
+ ? { cssProps: [...new Set(entry.cssProps.map((c) => c.name ?? c))] }
1024
1024
  : {}),
1025
1025
  ...(() => {
1026
1026
  const history = historyWithCss(entry, manifest);
@@ -1417,7 +1417,7 @@ function getComponent({
1417
1417
  ? {
1418
1418
  cssProps: wanted.has('cssProps')
1419
1419
  ? entry.cssProps
1420
- : entry.cssProps.map((c) => c.name ?? c),
1420
+ : [...new Set(entry.cssProps.map((c) => c.name ?? c))],
1421
1421
  }
1422
1422
  : {}),
1423
1423
  ...(wanted.has('tree') && entry.tree ? { tree: entry.tree } : {}),
@@ -2284,11 +2284,11 @@ function getComposable({ name, sections, maxChars } = {}) {
2284
2284
  }
2285
2285
  const markdown = readFileSync(join(dir, file), 'utf-8');
2286
2286
  /*
2287
- * A composable that needs a host component says so FIRST, as a field: with
2288
- * no `<BbHost />`, `await confirm()` resolves `false` after a second and a
2289
- * toast never shows. Every blind answerer
2290
- * of "await an Are-you-sure dialog" (4 of 4, 2026-09-24) left the host out,
2291
- * although the doc's second paragraph states it.
2287
+ * A composable that needs a host component says so FIRST, as a field (its
2288
+ * summary's "Requires exactly one <Bb… />"). Every blind answerer of
2289
+ * "await an Are-you-sure dialog" (4 of 4, 2026-09-24) left `<BbHost />`
2290
+ * out; since Q82.21 the plugin renders it, so useConfirm / useToast carry
2291
+ * none.
2292
2292
  */
2293
2293
  const host = frontmatter(markdown).summary?.match(
2294
2294
  /Requires (exactly one <Bb\w+ \/>(?: host)?[^.]*)\./
@@ -3352,7 +3352,7 @@ function buildServer() {
3352
3352
  'get_composable',
3353
3353
  {
3354
3354
  description:
3355
- "Read one composable's doc (useToast, useConfirm, useBbTableContext, useMobile…): what it returns, what host it needs, examples. A long doc answers its intro and outline; pass `sections`.",
3355
+ "Read one composable's doc (useToast, useConfirm, useBbTable, useMobile…): what it returns, what host it needs, examples. A long doc answers its intro and outline; pass `sections`.",
3356
3356
  inputSchema: {
3357
3357
  name: z.string().describe("Composable name, e.g. 'useToast'."),
3358
3358
  sections: z
@@ -69,7 +69,12 @@ import {
69
69
  findHandRollHints,
70
70
  loadKnownTokens,
71
71
  } from '../scripts/lib/hand-roll-hints.mjs';
72
- import { loadAdoptionRows, scanIdioms } from '../scripts/lib/idiom-scan.mjs';
72
+ import {
73
+ loadAdoptionRows,
74
+ repeatedIdioms,
75
+ repeatOccurrences,
76
+ scanIdioms,
77
+ } from '../scripts/lib/idiom-scan.mjs';
73
78
  import {
74
79
  disabledChecker,
75
80
  ruleForFinding,
@@ -99,7 +104,9 @@ import {
99
104
  import {
100
105
  HAND_IMPORTED_STYLES_EXTENSIONS,
101
106
  handImportedStylesFindings,
107
+ readPluginConfig,
102
108
  } from '../scripts/lib/hand-imported-styles.mjs';
109
+ import { unstyledVariants } from '../scripts/lib/unstyled-variants.mjs';
103
110
  import { unknownLocaleFindings } from '../scripts/lib/locale-check.mjs';
104
111
  import {
105
112
  readShippedDefinePreset,
@@ -114,6 +121,7 @@ import {
114
121
  import { refuseLinkedTarget } from '../scripts/lib/linked-target.mjs';
115
122
  import {
116
123
  ensureCheckUnknownComponents,
124
+ strictTemplateSuggestion,
117
125
  toolchainWarnings,
118
126
  } from '../scripts/lib/toolchain-check.mjs';
119
127
  import { dirname, isAbsolute, join, relative, resolve } from 'node:path';
@@ -402,6 +410,14 @@ function aiInit({ mcp = true } = {}) {
402
410
  'MCP: skipped (--no-mcp). Re-run without it to let agents query the knowledge base through the bitboss-ui MCP server instead of reading files.'
403
411
  );
404
412
  }
413
+ // L34: the guide's strict set, suggested only (see STRICT_TEMPLATE_SET).
414
+ const strict = strictTemplateSuggestion(projectRoot);
415
+ if (strict) console.log(strict);
416
+ // Q82.15 (c): Muse skips project rules and skills in an untrusted
417
+ // workspace and reads MCP servers from its user settings only.
418
+ console.log(
419
+ 'Muse: trust the workspace (its prompt, or `--trust-workspace`) so it loads AGENTS.md and the skill; for MCP, add `bitboss-ui` under `mcpServers` in ~/.config/muse/settings.json (or ask Muse to migrate it from .mcp.json).'
420
+ );
405
421
  // Q61.7: Laravel's vue-starter-kit (and others) git-ignore these.
406
422
  console.log(
407
423
  "Some starters (Laravel's vue-starter-kit) git-ignore AGENTS.md, CLAUDE.md, .claude, .cursor and .mcp.json: teammates won't see these files until you un-ignore them."
@@ -1217,6 +1233,28 @@ async function checkCommand(
1217
1233
  }
1218
1234
  }
1219
1235
 
1236
+ // Q82.20 (b): a variant the build plugin registers that nothing paints
1237
+ // renders as the base plate (a solid primary badge). Read across the whole
1238
+ // project whatever the file scope: the paint can live in any stylesheet.
1239
+ {
1240
+ const config = readPluginConfig(projectRoot)?.config ?? 'vite.config';
1241
+ const sources = projectSources.flatMap((path) => {
1242
+ try {
1243
+ return [readText(path)];
1244
+ } catch {
1245
+ return [];
1246
+ }
1247
+ });
1248
+ for (const { option, name, className } of unstyledVariants(
1249
+ validateOptions.registeredVariants,
1250
+ sources
1251
+ ))
1252
+ warnings.push({
1253
+ file: config,
1254
+ message: `\`${option}\` registers "${name}", but no project file paints \`.${className}\` (or a \`pt\` state for it): it renders as the default variant. Style it in a stylesheet loaded after bitboss-ui/styles.css (design-language guide § Getting soft semantic badges).`,
1255
+ });
1256
+ }
1257
+
1220
1258
  // Q63.8: portal names, judged against the whole project's declarations
1221
1259
  // and call sites (scripts too: `confirm({ portal })` lives there). A full
1222
1260
  // run reads every source file; explicit paths / `--changed`, only those.
@@ -1264,6 +1302,8 @@ async function checkCommand(
1264
1302
  const exts = new Set(rows.flatMap((row) => row.ext));
1265
1303
  const TEST_FILE = /\.(?:test|spec)(?:-d)?\.[cm]?[jt]sx?$/;
1266
1304
  const scope = changed ? changed.all : globs.length ? files : projectSources;
1305
+ // Q82.4: the repeats count across files, so they are judged at the end.
1306
+ const repeats = [];
1267
1307
  for (const path of scope) {
1268
1308
  const ext = path.slice(path.lastIndexOf('.') + 1);
1269
1309
  if (!exts.has(ext) || path.endsWith('.d.ts') || TEST_FILE.test(path))
@@ -1274,9 +1314,13 @@ async function checkCommand(
1274
1314
  } catch {
1275
1315
  continue;
1276
1316
  }
1317
+ const file = relative(projectRoot, path);
1277
1318
  for (const hit of scanIdioms(content, ext, rows))
1278
- idioms.push({ file: relative(projectRoot, path), ...hit });
1319
+ idioms.push({ file, ...hit });
1320
+ for (const occurrence of repeatOccurrences(content, ext))
1321
+ repeats.push({ file, ...occurrence });
1279
1322
  }
1323
+ idioms.push(...repeatedIdioms(repeats));
1280
1324
  }
1281
1325
 
1282
1326
  for (const [name, file] of projectLocal) warnLocal(name, file);
@@ -1539,7 +1583,9 @@ Commands:
1539
1583
  merges, never overwrites other servers — and install its
1540
1584
  optional peers with the project's package manager. Sets
1541
1585
  \`vueCompilerOptions.checkUnknownComponents: true\` in the
1542
- tsconfig unless it is already named (Nuxt: says where).
1586
+ tsconfig unless it is already named (Nuxt: says where),
1587
+ and suggests (never writes) the install guide's strict
1588
+ template set when \`strictTemplates\` is not on.
1543
1589
  \`--no-mcp\` skips the server and the install. Idempotent —
1544
1590
  safe to re-run after upgrades.
1545
1591
  add <id…> | --all [--dir <path>] [--dry-run] [--json]
@@ -1563,8 +1609,9 @@ Commands:
1563
1609
  helpers update [id…] [--dry-run] [--json]
1564
1610
  Replace helper files that hold an older bitboss-ui
1565
1611
  version (formatting does not matter); keep the files
1566
- you edited; refuse a group of helpers where you edited a
1567
- file bitboss-ui also changed. \`npm update bitboss-ui\`
1612
+ you edited; keep a file you edited that bitboss-ui also
1613
+ changed, and the files that import it (exit 2), and
1614
+ update the rest of its group. \`npm update bitboss-ui\`
1568
1615
  does not touch your copies: run this after upgrading.
1569
1616
  add/helpers exit codes: 0 done or nothing to do; 1 usage
1570
1617
  error or diff found a difference; 2 refused (add wrote
@@ -1616,8 +1663,11 @@ Commands:
1616
1663
  controls, sortable headers, steppers, app sheets, app
1617
1664
  confirms, …) with file:line and the replacement: the
1618
1665
  adoption checklist's own rows, run over .vue and script
1619
- files. Report-only and opt-in: it never changes the exit
1620
- code, and plain \`check\` never runs it. Guide:
1666
+ files, and two repeats across files: one \`icon\` literal
1667
+ on 3+ BbAlert / toasts (→ a variant) and one \`pt:<part>\`
1668
+ literal on 3+ instances of a component (→ the global
1669
+ \`pt\` map). Report-only and opt-in: it never changes the
1670
+ exit code, and plain \`check\` never runs it. Guide:
1621
1671
  dist/ai/guides/migration/adoption-checklist.md.
1622
1672
 
1623
1673
  Honours ESLint disable comments in .vue files: a finding
@@ -1650,7 +1700,7 @@ Commands:
1650
1700
  \`--json\` prints \`{ findings: [...], warnings: [...], hints: [...],
1651
1701
  suppressed, files, manifestVersion, installedVersion }\`
1652
1702
  (plus \`changed: true\` under \`--changed\`, and
1653
- \`idioms: [{ file, line, id, use }]\` under \`--idioms\`).
1703
+ \`idioms: [{ file, line, id, use, count? }]\` under \`--idioms\`).
1654
1704
  Each finding: \`{ file, line, component, attr, kind,
1655
1705
  message, hint?, to? }\` (plus \`fenceIndex\`/\`fenceInfo\`
1656
1706
  inside a markdown fence; \`line\` is absolute in the file).
@@ -1666,11 +1716,15 @@ Commands:
1666
1716
  e.g. BbColorPalette \`@update:open\`), \`unknown-slot\`,
1667
1717
  \`unknown-pt-key\` (a key of the \`pt\` object form that
1668
1718
  matches no part / state; \`to\` when the part was renamed),
1669
- \`no-default-slot\`, \`inert-nav-attr\`,
1719
+ \`no-default-slot\`, \`empty-dropzone\` (a warning: a
1720
+ BbDropzone with nothing in its slot, the only surface
1721
+ it has, renders 0px tall), \`inert-nav-attr\`,
1670
1722
  \`nameless-control\` (an icon-only BbButton or BbBadge,
1671
1723
  or a BbProgress, with no accessible name),
1672
1724
  \`removed-css-local\` (a component CSS local the
1673
1725
  library removed, e.g. \`--day-slot-allowance\`),
1726
+ \`renamed-export\` (an import of a name bitboss-ui
1727
+ renamed, e.g. \`useBbFormContext\` → \`useBbForm\`),
1674
1728
  \`private-import\` (an import from inside the package's
1675
1729
  \`dist/\`), \`not-exported-type\` (a \`Pt*\` pt type
1676
1730
  imported from bitboss-ui: type pt through
@@ -1687,6 +1741,10 @@ Commands:
1687
1741
  items array: rows and crumbs take \`value\` /
1688
1742
  \`label\`, tabs \`value\`, groups \`id\`; \`--fix\`
1689
1743
  rewrites it),
1744
+ \`tab-link-navigation\` / \`tab-link-missing\` (a
1745
+ BbTabs whose items have \`href\` / \`to\` is a nav of
1746
+ links: \`navigation\` on it does nothing, and an item
1747
+ with neither renders as a disabled link),
1690
1748
  \`unknown-variant\` (a variant name from another
1691
1749
  library, e.g. \`danger\` on BbAlert / BbBadge; the
1692
1750
  message names ours),
@@ -1726,8 +1784,8 @@ Commands:
1726
1784
  other way round; literal names only, a \`:name\`
1727
1785
  binding or a non-literal call site is never judged),
1728
1786
  \`unknown-dialog\` (\`v-bb-dialog\` /
1729
- \`v-bb-off-canvas\` / \`useBbDialogContext()\` /
1730
- \`useBbOffCanvasContext()\` names an id no
1787
+ \`v-bb-off-canvas\` / \`useBbDialog()\` /
1788
+ \`useBbOffCanvas()\` names an id no
1731
1789
  \`<BbDialog | BbOffCanvas id>\` declares, or one of
1732
1790
  the other family; literal ids only),
1733
1791
  \`positional-provider\` (an \`items\` provider with
@@ -1814,7 +1872,10 @@ Commands:
1814
1872
  \`v-model\` and \`@click="x = true"\` use: give the
1815
1873
  dialog an \`id\` and put \`v-bb-dialog\` on the
1816
1874
  trigger; ESLint's \`--fix\` rewrites it when nothing
1817
- else uses the ref).
1875
+ else uses the ref), \`hidden-label-placeholder\` (a
1876
+ field or select with \`hide-label\` and no
1877
+ \`placeholder\`: an empty unlabelled box to a sighted
1878
+ user; add a \`placeholder\`).
1818
1879
  changelog [--since <version>] [--until <version>] [--json]
1819
1880
  Breaking changes between two releases — "what breaks if I
1820
1881
  bump". \`--since\` is the version you are ON, and is
@@ -610,9 +610,10 @@ States are listed in precedence order: when two are on at once and their entries
610
610
 
611
611
  Set these on the element, or on a class you put on it, to retune this component alone — the sanctioned alternative to reaching past the API with `:deep()`. They are this component's own locals — a **Set on** of `pt:<part>` means the local lives on that part's element, so set it through that entry (`pt:box="[--border-color:var(--color-green-500)]"`); the global `--bb-*` theme tokens are a separate tier (see the [design-tokens guide](./guides/design-tokens.md), or the MCP `list_tokens` tool).
612
612
 
613
- | Property | Default | What it is |
614
- | --- | --- | --- |
615
- | `--py` | `16px` | trigger padding, and the panel's bottom padding |
613
+ | Property | Set on | Default | What it is |
614
+ | --- | --- | --- | --- |
615
+ | `--ring-t` | `.bb-accordion__header` | `var(--bb-transition-medium)` | |
616
+ | `--py` | `.bb-accordion--titled` | `16px` | trigger padding, and the panel's bottom padding |
616
617
 
617
618
  ## Component tree
618
619
 
@@ -496,7 +496,7 @@ A `pt` value written in `<script>` (a constant, a preset, a wrapper's
496
496
  | Prop | Type | Default | Required | Description |
497
497
  | --- | --- | --- | --- | --- |
498
498
  | `pt:<part>`, `pt:<part>:<state>`, `pt` | `PtValue` | | | Passthrough — a class list, or `{ class, style, attrs }`, bound to one named part of the component; the state form applies only while that state is on. Parts: `close`, `icon`, `root`, `text`, `title`. States: `destructive`, `outline`, `primary`, `warning`. What each one is: _Passthrough parts and states_ below. `pt` is the object form with the same keys minus the prefix (`{ icon: '…', 'icon:loading': '…' }`). See `guides/passthrough.md`. In `<script>` a `pt` value is typed `BbAlertProps['pt']` (`PtValue` is not exported): § Typing `pt` in `<script>`. |
499
- | `ariaLive` | `"off" \| "polite" \| "assertive" \| undefined` | | | ARIA live region politeness. Unset, it follows `role` when you set one (`'alert'` → `'assertive'`, `'status'` → `'polite'`), else the variant: `'assertive'` for destructive/warning, otherwise `'polite'`. |
499
+ | `ariaLive` | `"off" \| "assertive" \| "polite" \| undefined` | | | ARIA live region politeness. Unset, it follows `role` when you set one (`'alert'` → `'assertive'`, `'status'` → `'polite'`), else the variant: `'assertive'` for destructive/warning, otherwise `'polite'`. |
500
500
  | `closeLabel` | `string \| undefined` | | | Visually hidden string used to label the close button. |
501
501
  | `hideClose` | `boolean \| undefined` | `false` | | Defines whether to hide the close button. |
502
502
  | `hideIcon` | `boolean \| undefined` | `false` | | Hide the icon, its own or its variant's; with neither it does nothing. |
@@ -965,6 +965,7 @@ Set these on the element, or on a class you put on it, to retune this component
965
965
  | `--border-disabled` | `.bb-badge` | `var(--bb-muted)` | the frame while disabled |
966
966
  | `--pad-left` | `.bb-badge` | `var(--px)` | Side-owned padding: the body and trailing wrappers carry the pill's inline padding (and its radius) so their hit areas run flush to the border. The modifiers below retune these vars instead of the pill's own padding. |
967
967
  | `--pad-right` | `.bb-badge` | `var(--px)` | |
968
+ | `--ring-t` | `.bb-badge` | `var(--bb-transition-medium)` | |
968
969
  | `--size` | `.bb-badge__icon` | `var(--icon-size)` | |
969
970
 
970
971
  ## Component tree
@@ -14,7 +14,7 @@
14
14
  | --- | --- | --- | --- | --- |
15
15
  | `pt:<part>`, `pt:<part>:<state>`, `pt` | `PtValue` | | | Passthrough — a class list, or `{ class, style, attrs }`, bound to one named part of the component; the state form applies only while that state is on. Parts: `root`. States: `activeLink`, `disabled`, `exactActiveLink`. What each one is: _Passthrough parts and states_ below. `pt` is the object form with the same keys minus the prefix (`{ icon: '…', 'icon:loading': '…' }`). See `guides/passthrough.md`. In `<script>` a `pt` value is typed `BbBadgeButtonProps['pt']` (`PtValue` is not exported): § Typing `pt` in `<script>`. |
16
16
  | `activeClass` | `string \| undefined` | `'router-link-active'` | | CSS class applied when the component renders as a link and the target of the link is the current route or the url matches partially. Ported for Inertia compatibility. |
17
- | `ariaCurrentValue` | `"page" \| "step" \| "location" \| "date" \| "time" \| "true" \| "false" \| undefined` | `'page'` | | Value forwarded to the `aria-current` attribute when the component renders as a router link and the target route is an exact match. Use to communicate the current location to assistive technologies. |
17
+ | `ariaCurrentValue` | `"time" \| "true" \| "false" \| "page" \| "step" \| "location" \| "date" \| undefined` | `'page'` | | Value forwarded to the `aria-current` attribute when the component renders as a router link and the target route is an exact match. Use to communicate the current location to assistive technologies. |
18
18
  | `async` | `boolean \| undefined` | `false` | | Inertia: runs the visit without blocking — the page stays interactive and several async visits can be in flight at once. |
19
19
  | `cacheFor` | `string \| number \| (string \| number)[] \| undefined` | | | Inertia: how long a prefetched response stays fresh before it is re-fetched. A single duration, or `[staleAfter, expiresAfter]`. Typed platform-agnostically (matching BbButton) so the library's types never require `@inertiajs/vue3` to be installed. |
20
20
  | `cacheTags` | `string \| string[] \| undefined` | | | Inertia: tags to file this visit's prefetch cache under, so a later request can invalidate the whole tagged group. |
@@ -26,7 +26,7 @@
26
26
  | `except` | `string[] \| undefined` | | | Inertia: the inverse of `only` — properties to EXCLUDE from a partial reload. Pass one or the other, not both. |
27
27
  | `external` | `boolean \| undefined` | `false` | | Forces an `href` link to render as a plain `<a>` (native navigation), bypassing Inertia/router interception, as Nuxt's `NuxtLink` `external` does. For links outside the SPA; a native-anchor signal alongside `target` and `download`. |
28
28
  | `headers` | `object \| undefined` | | | Additional HTTP headers forwarded to Inertia when navigating via `href` in an Inertia-enabled app. |
29
- | `href` | `string \| undefined` | | | Hyperlink reference used when rendering as an anchor (or as an Inertia link in Inertia-enabled apps). If provided and not disabled, the component renders as an anchor/Inertia link. |
29
+ | `href` | `string \| { url: string; method: "get" \| "post" \| "put" \| "patch" \| "delete"; } \| undefined` | | | The link target: renders an anchor (an Inertia `<Link>` under Inertia). Also takes Inertia's `{ url, method }`, a Wayfinder route: Inertia visits with its method; elsewhere the link is its `url`. |
30
30
  | `instant` | `boolean \| undefined` | `false` | | Inertia: navigate optimistically on click and reconcile when the response lands, instead of waiting for the round trip. |
31
31
  | `method` | `"get" \| "post" \| "put" \| "patch" \| "delete" \| undefined` | | | HTTP method used for Inertia navigation when `href` is provided in an Inertia-enabled app. Ignored otherwise: an Inertia POST visit is `href="/orders/5/archive" method="post"`, never `to` (a `to` link is a Vue Router link and sends no method). |
32
32
  | `onBefore` | `(() => void) \| undefined` | | | Lifecycle hook invoked by Inertia right before the request is sent. |
@@ -51,7 +51,7 @@
51
51
  | `tag` | `'button'` \| `'div'` \| `'span'` \| `'label'` | `'button'` | | Element of the plain (non-link) button: `'button'` (default), `'div'` / `'span'` (a clickable box inside a button or link) or `'label'` (a file-upload trigger). Ignored with `href` / `to`. Off `button`, native `type` / `disabled` drop (disabled stays a class). |
52
52
  | `target` | `string \| undefined` | | | Target browsing context for anchor/Inertia links (e.g. `_self`, `_blank`). Ignored when rendering as a native button. |
53
53
  | `to` | `string \| wt \| bt \| undefined` | | | Route location to navigate to. When provided (and not disabled), the component renders as a Vue Router link. |
54
- | `type` | `"button" \| "submit" \| "reset" \| undefined` | `'button'` | | Native `type` attribute used when rendering as a button (e.g. `button`, `submit`, `reset`). |
54
+ | `type` | `"button" \| "reset" \| "submit" \| undefined` | `'button'` | | Native `type` attribute used when rendering as a button (e.g. `button`, `submit`, `reset`). |
55
55
  | `viewTransition` | `boolean \| undefined` | `false` | | Inertia: run the page swap inside a View Transition, where the browser supports one. |
56
56
 
57
57
  ## Passthrough parts and states
@@ -104,6 +104,7 @@ Set these on the element, or on a class you put on it, to retune this component
104
104
  | `--border-disabled` | `.bb-badge` | `var(--bb-muted)` | the frame while disabled |
105
105
  | `--pad-left` | `.bb-badge` | `var(--px)` | Side-owned padding: the body and trailing wrappers carry the pill's inline padding (and its radius) so their hit areas run flush to the border. The modifiers below retune these vars instead of the pill's own padding. |
106
106
  | `--pad-right` | `.bb-badge` | `var(--px)` | |
107
+ | `--ring-t` | `.bb-badge` | `var(--bb-transition-medium)` | |
107
108
  | `--size` | `.bb-badge__icon` | `var(--icon-size)` | |
108
109
 
109
110
  ## Component tree
@@ -56,8 +56,10 @@ in this priority order:
56
56
  `NuxtLink` (Nuxt), or the Inertia `Link` — resolved for you from the active
57
57
  framework.
58
58
  2. **Anchor `<a>`** — when `href` is set but the above doesn't apply: external or
59
- cross-origin URLs, any `href` with a `target`, or a disabled `to` link (kept
60
- as an anchor for correct link semantics).
59
+ cross-origin URLs, a fragment (`href="#actions"`), any `href` with a
60
+ `target`, or a disabled `to` link (kept as an anchor for correct link
61
+ semantics). Those need no `external`: it is for a same-origin route the
62
+ router must not take.
61
63
  3. **Native `<button>`** — the default when there is no `href`/`to`. Polymorphic
62
64
  via `tag` (below), but a real `<button>` unless you say otherwise.
63
65
 
@@ -73,21 +75,21 @@ primitive brings no look of its own):
73
75
  <div class="flex flex-wrap items-center gap-2 text-sm">
74
76
  <!-- No href/to → a native <button>. -->
75
77
  <BbBaseButton
76
- class="rounded-(--bb-radius) bg-(--bb-primary) px-3 py-1.5 text-(--bb-primary-fg) focus-visible:ring-2 focus-visible:ring-(--bb-ring)"
78
+ class="rounded-(--bb-radius) bg-(--bb-primary) px-3 py-1.5 text-(--bb-primary-fg) focus-visible:outline-(--bb-ring)"
77
79
  @click="pinged = true"
78
80
  >
79
81
  Native button
80
82
  </BbBaseButton>
81
83
  <!-- Same-origin href → an <a>. -->
82
84
  <BbBaseButton
83
- class="rounded-(--bb-radius) px-3 py-1.5 text-(--bb-primary) underline focus-visible:ring-2 focus-visible:ring-(--bb-ring)"
85
+ class="rounded-(--bb-radius) px-3 py-1.5 text-(--bb-primary) underline focus-visible:outline-(--bb-ring)"
84
86
  href="#docs"
85
87
  >
86
88
  Anchor link
87
89
  </BbBaseButton>
88
90
  <!-- href + target → a plain <a target="_blank"> with rel secured. -->
89
91
  <BbBaseButton
90
- class="rounded-(--bb-radius) px-3 py-1.5 underline focus-visible:ring-2 focus-visible:ring-(--bb-ring)"
92
+ class="rounded-(--bb-radius) px-3 py-1.5 underline focus-visible:outline-(--bb-ring)"
91
93
  href="https://example.com"
92
94
  target="_blank"
93
95
  >
@@ -117,19 +119,21 @@ scaffold, `cursor` and transitions), `bb-base-button--block` and
117
119
  library button, tab, row and menu item draws on, and each of those paints its
118
120
  own focus; a native outline would sit on top of all of them. So a bare
119
121
  `BbBaseButton` shows **no keyboard focus until you style it**. Every class you
120
- give it needs a `:focus-visible` style too; the library's own ring is one
121
- utility pair:
122
+ give it needs a `:focus-visible` style too. The base already draws a 2px
123
+ transparent outline (the ring scaffold), so the library's own ring is one
124
+ utility that colours it:
122
125
 
123
126
  ```vue
124
127
  <BbBaseButton
125
- class="rounded-(--bb-radius) px-3 py-1.5 focus-visible:ring-2 focus-visible:ring-(--bb-ring)"
128
+ class="rounded-(--bb-radius) px-3 py-1.5 focus-visible:outline-(--bb-ring)"
126
129
  >
127
130
  Save
128
131
  </BbBaseButton>
129
132
  ```
130
133
 
131
- The ring animates in through the base's `box-shadow` transition (that is the
132
- scaffold). There is **no padding, background, border, or
134
+ The ring fades in through the base's `outline-color` transition (that is the
135
+ scaffold), as the library's own rings do: an outline, never a `box-shadow`, so
136
+ a shadow you set on the element never takes the ring with it. There is **no padding, background, border, or
133
137
  variant appearance** — that is the whole point. It sets **no text color**, so a
134
138
  `text-*` utility on the element just works with no specificity fight; the text
135
139
  inherits from its container (in anchor mode, the browser's blue-and-underlined
@@ -146,7 +150,7 @@ the right base for a clickable card or a bespoke nav item:
146
150
  <!-- Styled entirely by utility classes — neutral hover chrome. -->
147
151
  <BbBaseButton
148
152
  href="#b"
149
- class="rounded-(--bb-radius) border border-(--bb-border) px-3 py-1 font-medium hover:bg-(--bb-hover) focus-visible:ring-2 focus-visible:ring-(--bb-ring)"
153
+ class="rounded-(--bb-radius) border border-(--bb-border) px-3 py-1 font-medium hover:bg-(--bb-hover) focus-visible:outline-(--bb-ring)"
150
154
  >
151
155
  Branded pill
152
156
  </BbBaseButton>
@@ -172,7 +176,7 @@ stay outside the link:
172
176
  <article
173
177
  v-for="project in projects"
174
178
  :key="project.name"
175
- class="relative flex flex-col items-start gap-1.5 rounded-(--bb-radius) border border-(--bb-border) bg-(--bb-panel) p-3 hover:bg-(--bb-surface-hover) has-focus-visible:ring-2 has-focus-visible:ring-(--bb-ring)"
179
+ class="relative flex flex-col items-start gap-1.5 rounded-(--bb-radius) border border-(--bb-border) bg-(--bb-panel) p-3 hover:bg-(--bb-surface-hover) has-focus-visible:outline-2 has-focus-visible:outline-(--bb-ring)"
176
180
  >
177
181
  <span class="flex w-full items-center justify-between gap-2">
178
182
  <span
@@ -236,9 +240,9 @@ const projects: Project[] = [
236
240
  - **Optional links:** render the overlay only when there is a destination
237
241
  (`v-if="href"`); the card needs no other change — no `tag` switching.
238
242
  - **Focus:** the overlay is invisible, so show focus on the card
239
- (`has-focus-visible:ring-2 has-focus-visible:ring-(--bb-ring)`) and drop it
240
- from the overlay (`outline-none`; the primitive's own ring scaffold is
241
- zero-width until you style it).
243
+ (`has-focus-visible:outline-2 has-focus-visible:outline-(--bb-ring)`) and
244
+ drop it from the overlay (`outline-none`, so the scaffold's transparent
245
+ outline never paints).
242
246
 
243
247
  ### Label
244
248
 
@@ -450,7 +454,7 @@ When it renders as a native button you can retune the element:
450
454
  </p>
451
455
  <BbBaseButton
452
456
  block
453
- class="rounded-(--bb-radius) bg-(--bb-primary) px-3 py-1.5 text-sm text-(--bb-primary-fg) focus-visible:ring-2 focus-visible:ring-(--bb-ring)"
457
+ class="rounded-(--bb-radius) bg-(--bb-primary) px-3 py-1.5 text-sm text-(--bb-primary-fg) focus-visible:outline-(--bb-ring)"
454
458
  type="submit"
455
459
  >
456
460
  Create workspace
@@ -520,7 +524,8 @@ A `pt` value written in `<script>` (a constant, a preset, a wrapper's
520
524
  - `tag="div"`/`tag="span"` throws away native button semantics — only do it when a
521
525
  `<button>` is genuinely invalid, and restore keyboard/focus behavior yourself.
522
526
  - Style the focus state: the base removes the browser's ring and provides only
523
- a _scaffold_ (`box-shadow`/`outline` transitions), so a class without a
527
+ a _scaffold_ (a transparent 2px outline and its colour transition), so a
528
+ class without a
524
529
  `:focus-visible` style ships an invisible keyboard focus. See "It removes the
525
530
  browser's focus ring" above.
526
531
 
@@ -544,7 +549,7 @@ A `pt` value written in `<script>` (a constant, a preset, a wrapper's
544
549
  | --- | --- | --- | --- | --- |
545
550
  | `pt:<part>`, `pt:<part>:<state>`, `pt` | `PtValue` | | | Passthrough — a class list, or `{ class, style, attrs }`, bound to one named part of the component; the state form applies only while that state is on. Parts: `root`. States: `activeLink`, `disabled`, `exactActiveLink`. What each one is: _Passthrough parts and states_ below. `pt` is the object form with the same keys minus the prefix (`{ icon: '…', 'icon:loading': '…' }`). See `guides/passthrough.md`. In `<script>` a `pt` value is typed `BbBaseButtonProps['pt']` (`PtValue` is not exported): § Typing `pt` in `<script>`. |
546
551
  | `activeClass` | `string \| undefined` | `'router-link-active'` | | CSS class applied when the component renders as a link and the target of the link is the current route or the url matches partially. Ported for Inertia compatibility. |
547
- | `ariaCurrentValue` | `"page" \| "step" \| "location" \| "date" \| "time" \| "true" \| "false" \| undefined` | `'page'` | | Value forwarded to the `aria-current` attribute when the component renders as a router link and the target route is an exact match. Use to communicate the current location to assistive technologies. |
552
+ | `ariaCurrentValue` | `"time" \| "true" \| "false" \| "page" \| "step" \| "location" \| "date" \| undefined` | `'page'` | | Value forwarded to the `aria-current` attribute when the component renders as a router link and the target route is an exact match. Use to communicate the current location to assistive technologies. |
548
553
  | `async` | `boolean \| undefined` | `false` | | Inertia: runs the visit without blocking — the page stays interactive and several async visits can be in flight at once. |
549
554
  | `block` | `boolean \| undefined` | `false` | | Makes the component take the full available width (block-level layout) and centres its label; an anchor becomes `display: block` so the width applies. Adds the `bb-base-button--block` modifier class. |
550
555
  | `cacheFor` | `string \| number \| (string \| number)[] \| undefined` | | | Inertia: how long a prefetched response stays fresh before it is re-fetched. A single duration, or `[staleAfter, expiresAfter]`. Typed platform-agnostically (matching BbButton) so the library's types never require `@inertiajs/vue3` to be installed. |
@@ -557,7 +562,7 @@ A `pt` value written in `<script>` (a constant, a preset, a wrapper's
557
562
  | `except` | `string[] \| undefined` | | | Inertia: the inverse of `only` — properties to EXCLUDE from a partial reload. Pass one or the other, not both. |
558
563
  | `external` | `boolean \| undefined` | `false` | | Forces an `href` link to render as a plain `<a>` (native navigation), bypassing Inertia/router interception, as Nuxt's `NuxtLink` `external` does. For links outside the SPA; a native-anchor signal alongside `target` and `download`. |
559
564
  | `headers` | `object \| undefined` | | | Additional HTTP headers forwarded to Inertia when navigating via `href` in an Inertia-enabled app. |
560
- | `href` | `string \| undefined` | | | Hyperlink reference used when rendering as an anchor (or as an Inertia link in Inertia-enabled apps). If provided and not disabled, the component renders as an anchor/Inertia link. |
565
+ | `href` | `string \| { url: string; method: "get" \| "post" \| "put" \| "patch" \| "delete"; } \| undefined` | | | The link target: renders an anchor (an Inertia `<Link>` under Inertia). Also takes Inertia's `{ url, method }`, a Wayfinder route: Inertia visits with its method; elsewhere the link is its `url`. |
561
566
  | `instant` | `boolean \| undefined` | `false` | | Inertia: navigate optimistically on click and reconcile when the response lands, instead of waiting for the round trip. |
562
567
  | `method` | `"get" \| "post" \| "put" \| "patch" \| "delete" \| undefined` | | | HTTP method used for Inertia navigation when `href` is provided in an Inertia-enabled app. Ignored otherwise: an Inertia POST visit is `href="/orders/5/archive" method="post"`, never `to` (a `to` link is a Vue Router link and sends no method). |
563
568
  | `onBefore` | `(() => void) \| undefined` | | | Lifecycle hook invoked by Inertia right before the request is sent. |
@@ -583,7 +588,7 @@ A `pt` value written in `<script>` (a constant, a preset, a wrapper's
583
588
  | `target` | `string \| undefined` | | | Target browsing context for anchor/Inertia links (e.g. `_self`, `_blank`). Ignored when rendering as a native button. |
584
589
  | `text` | `string \| undefined` | | | Fallback text content rendered when no default slot is provided. |
585
590
  | `to` | `string \| wt \| bt \| undefined` | | | Route location to navigate to. When provided (and not disabled), the component renders as a Vue Router link. |
586
- | `type` | `"button" \| "submit" \| "reset" \| undefined` | `"button"` | | Native `type` attribute used when rendering as a button (e.g. `button`, `submit`, `reset`). |
591
+ | `type` | `"button" \| "reset" \| "submit" \| undefined` | `"button"` | | Native `type` attribute used when rendering as a button (e.g. `button`, `submit`, `reset`). |
587
592
  | `viewTransition` | `boolean \| undefined` | `false` | | Inertia: run the page swap inside a View Transition, where the browser supports one. |
588
593
 
589
594
  ## Passthrough parts and states
@@ -294,6 +294,7 @@ Set these on the element, or on a class you put on it, to retune this component
294
294
  | `--elev` | `var(--bb-elev-sm)` | Resting lift; a no-op until a theme pins `--bb-elev`. |
295
295
  | `--bg` | `var(--bb-panel)` | The glyph plate. DECLARED here, not consumed bare, because this glyph renders inside surfaces that declare `--bg` themselves — a table row or header cell, a dialog, an off-canvas sheet. Without the declaration it would inherit that surface's fill, which happens to match at the shipped default and would diverge the moment anyone writes `.my-table { --bg: … }`. Identical to the raw tokens it replaces at every theme. |
296
296
  | `--border-color` | `var(--bb-border)` | Resting border colour of the glyph; re-pointed by error and warning states. |
297
+ | `--ring-t` | `var(--bb-transition-medium)` | |
297
298
 
298
299
  ## See Also
299
300
 
@@ -306,6 +306,7 @@ Set these on the element, or on a class you put on it, to retune this component
306
306
  | `--elev` | `var(--bb-elev-sm)` | Same resting lift as the checkbox glyph — see BbBaseCheckboxIcon. |
307
307
  | `--bg` | `var(--bb-panel)` | The glyph plate. DECLARED here, not consumed bare, because this glyph renders inside surfaces that declare `--bg` themselves — a table row or header cell, a dialog, an off-canvas sheet. Without the declaration it would inherit that surface's fill, which happens to match at the shipped default and would diverge the moment anyone writes `.my-table { --bg: … }`. Identical to the raw tokens it replaces at every theme. |
308
308
  | `--border-color` | `var(--bb-border)` | |
309
+ | `--ring-t` | `var(--bb-transition-medium)` | |
309
310
 
310
311
  ## See Also
311
312
 
@@ -307,6 +307,7 @@ Set these on the element, or on a class you put on it, to retune this component
307
307
  | `--thumb` | `min(16px, calc(var(--h) - 2 * var(--bw)))` | Capped by the track's inner height, so a thick-hairline theme shrinks the thumb instead of overflowing it. Unclamped, a 6px plate hairline leaves a 12px inner track carrying a 16px thumb; `--inset` then goes negative and the thumb paints over its own border. `16px` at every hairline the library ships, so no shipped pixel moves. Do NOT floor `--inset` at 0 instead: that keeps the oversized thumb and pushes it out of the bottom of the track (measured +1px protrusion at a 6px hairline), and it uncancels `--bw` from `--travel`, which is a constant 14px by construction. |
308
308
  | `--inset` | `calc((var(--h) - 2 * var(--bw) - var(--thumb)) / 2)` | Equal gap around the thumb — centres it vertically by construction, and is reused as the resting left/right inset. |
309
309
  | `--travel` | `calc(var(--w) - 2 * var(--bw) - var(--thumb) - 2 * var(--inset))` | How far the thumb slides between off and on (inset ↔ inset). |
310
+ | `--ring-t` | `var(--bb-transition-medium)` | |
310
311
 
311
312
  ## See Also
312
313