bitboss-ui 3.0.0-beta.28 → 3.0.0-beta.30

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (289) hide show
  1. package/bin/bitboss-ui.mjs +1 -1
  2. package/dist/ai/BbAccordion.md +18 -2
  3. package/dist/ai/BbAlert.md +14 -2
  4. package/dist/ai/BbAsterisk.md +9 -1
  5. package/dist/ai/BbAvatar.md +11 -2
  6. package/dist/ai/BbBadge.md +21 -3
  7. package/dist/ai/BbBadgeButton.md +16 -2
  8. package/dist/ai/BbBaseButton.md +51 -17
  9. package/dist/ai/BbBaseCheckboxIcon.md +22 -1
  10. package/dist/ai/BbBaseRadioIcon.md +21 -1
  11. package/dist/ai/BbBaseSwitchIcon.md +24 -3
  12. package/dist/ai/BbBreadcrumbs.md +24 -6
  13. package/dist/ai/BbButton.md +89 -8
  14. package/dist/ai/BbCalendar.md +548 -0
  15. package/dist/ai/BbCheckbox.md +28 -2
  16. package/dist/ai/BbCheckboxGroup.md +48 -3
  17. package/dist/ai/BbCollapsible.md +16 -1
  18. package/dist/ai/BbColorInput.md +40 -5
  19. package/dist/ai/BbColorPalette.md +22 -4
  20. package/dist/ai/BbConfirm.md +34 -4
  21. package/dist/ai/BbDatePicker.md +66 -21
  22. package/dist/ai/BbDatePickerInput.md +61 -9
  23. package/dist/ai/BbDialog.md +65 -10
  24. package/dist/ai/BbDropdown.md +134 -8
  25. package/dist/ai/BbDropdownButton.md +32 -6
  26. package/dist/ai/BbDropzone.md +20 -1
  27. package/dist/ai/BbIcon.md +9 -1
  28. package/dist/ai/BbIndicator.md +11 -2
  29. package/dist/ai/BbNumberInput.md +33 -3
  30. package/dist/ai/BbOffCanvas.md +68 -9
  31. package/dist/ai/BbPagination.md +19 -2
  32. package/dist/ai/BbPopover.md +26 -4
  33. package/dist/ai/BbProgress.md +9 -1
  34. package/dist/ai/BbRadio.md +27 -2
  35. package/dist/ai/BbRadioGroup.md +111 -6
  36. package/dist/ai/BbRating.md +26 -2
  37. package/dist/ai/BbSelect.md +75 -11
  38. package/dist/ai/BbSelectPopover.md +57 -10
  39. package/dist/ai/BbSlider.md +27 -3
  40. package/dist/ai/BbSmoothHeight.md +9 -1
  41. package/dist/ai/BbSpinner.md +9 -1
  42. package/dist/ai/BbSwitch.md +29 -3
  43. package/dist/ai/BbSwitchGroup.md +45 -4
  44. package/dist/ai/BbTable.md +132 -4
  45. package/dist/ai/BbTabs.md +331 -17
  46. package/dist/ai/BbTabsList.md +19 -9
  47. package/dist/ai/BbTabsPanes.md +15 -7
  48. package/dist/ai/BbTabsRoot.md +34 -8
  49. package/dist/ai/BbTag.md +36 -5
  50. package/dist/ai/BbTextInput.md +33 -3
  51. package/dist/ai/BbTextarea.md +33 -3
  52. package/dist/ai/BbTimePicker.md +22 -4
  53. package/dist/ai/BbTimePickerInput.md +42 -6
  54. package/dist/ai/BbToast.md +16 -4
  55. package/dist/ai/BbToastPortal.md +1 -1
  56. package/dist/ai/BbTooltip.md +17 -2
  57. package/dist/ai/BbTree.md +16 -1
  58. package/dist/ai/ChipsBox.md +3 -3
  59. package/dist/ai/CommonField.md +1 -1
  60. package/dist/ai/CommonFieldInput.md +1 -1
  61. package/dist/ai/CommonTimeSelector.md +1 -1
  62. package/dist/ai/FlatListBox.md +3 -3
  63. package/dist/ai/GroupedListBox.md +3 -3
  64. package/dist/ai/ListBox.md +5 -4
  65. package/dist/ai/OptionsContainer.md +1 -1
  66. package/dist/ai/changelog.json +129 -4
  67. package/dist/ai/components.json +5700 -660
  68. package/dist/ai/guides/agent-contract.md +35 -3
  69. package/dist/ai/guides/ai-router.md +16 -16
  70. package/dist/ai/guides/component-picker.md +2 -1
  71. package/dist/ai/guides/design-language.md +48 -35
  72. package/dist/ai/guides/design-tokens.md +47 -10
  73. package/dist/ai/guides/installation-and-plugin-setup.md +63 -1
  74. package/dist/ai/guides/migration/components/bb-date-picker-input.md +6 -0
  75. package/dist/ai/guides/migration/components/bb-dialog.md +10 -5
  76. package/dist/ai/guides/migration/components/bb-select-popover.md +8 -0
  77. package/dist/ai/guides/migration/components/bb-select.md +13 -0
  78. package/dist/ai/guides/migration/components/bb-tabs.md +53 -11
  79. package/dist/ai/guides/migration/components/bb-text-input.md +2 -2
  80. package/dist/ai/guides/migration/v2-to-v3.md +83 -40
  81. package/dist/ai/guides/passthrough.md +249 -61
  82. package/dist/ai/guides/validated-forms.md +5 -0
  83. package/dist/ai/index.md +1 -0
  84. package/dist/ai/recipes/inertia/records-workspace.md +103 -0
  85. package/dist/ai/recipes/inertia/wizard-form.md +63 -0
  86. package/dist/ai/recipes/nuxt/records-workspace.md +105 -0
  87. package/dist/ai/recipes/nuxt/wizard-form.md +63 -0
  88. package/dist/ai/recipes/vue/records-workspace.md +99 -0
  89. package/dist/ai/recipes/vue/wizard-form.md +60 -0
  90. package/dist/ai/source/BbAccordion.md +13 -5
  91. package/dist/ai/source/BbAlert.md +9 -1
  92. package/dist/ai/source/BbAsterisk.md +5 -1
  93. package/dist/ai/source/BbAvatar.md +7 -1
  94. package/dist/ai/source/BbBadge.md +28 -19
  95. package/dist/ai/source/BbBadgeButton.md +28 -19
  96. package/dist/ai/source/BbBaseButton.md +11 -2
  97. package/dist/ai/source/BbBaseCheckboxIcon.md +6 -1
  98. package/dist/ai/source/BbBaseRadioIcon.md +6 -1
  99. package/dist/ai/source/BbBaseSwitchIcon.md +9 -4
  100. package/dist/ai/source/BbBreadcrumbs.md +18 -2
  101. package/dist/ai/source/BbButton.md +74 -18
  102. package/dist/ai/source/BbCalendar.md +1617 -0
  103. package/dist/ai/source/BbCheckboxGroup.md +25 -7
  104. package/dist/ai/source/BbCollapsible.md +10 -2
  105. package/dist/ai/source/BbColorInput.md +26 -11
  106. package/dist/ai/source/BbColorPalette.md +40 -4
  107. package/dist/ai/source/BbConfirm.md +23 -10
  108. package/dist/ai/source/BbConfirmPortal.md +23 -10
  109. package/dist/ai/source/BbDatePicker.md +172 -1298
  110. package/dist/ai/source/BbDatePickerInput.md +44 -3
  111. package/dist/ai/source/BbDialog.md +119 -32
  112. package/dist/ai/source/BbDropdown.md +85 -9
  113. package/dist/ai/source/BbDropdownButton.md +58 -9
  114. package/dist/ai/source/BbDropdownGroup.md +84 -9
  115. package/dist/ai/source/BbDropzone.md +14 -2
  116. package/dist/ai/source/BbIcon.md +5 -4
  117. package/dist/ai/source/BbIndicator.md +10 -3
  118. package/dist/ai/source/BbOffCanvas.md +199 -43
  119. package/dist/ai/source/BbPagination.md +15 -2
  120. package/dist/ai/source/BbPopover.md +32 -4
  121. package/dist/ai/source/BbProgress.md +5 -1
  122. package/dist/ai/source/BbRadioGroup.md +25 -7
  123. package/dist/ai/source/BbRating.md +24 -2
  124. package/dist/ai/source/BbSelect.md +97 -12
  125. package/dist/ai/source/BbSelectPopover.md +162 -24
  126. package/dist/ai/source/BbSlider.md +26 -6
  127. package/dist/ai/source/BbSmoothHeight.md +2 -0
  128. package/dist/ai/source/BbSpinner.md +5 -1
  129. package/dist/ai/source/BbSwitchGroup.md +8 -3
  130. package/dist/ai/source/BbTable.md +35 -5
  131. package/dist/ai/source/BbTabs.md +67 -9
  132. package/dist/ai/source/BbTabsList.md +89 -17
  133. package/dist/ai/source/BbTabsPanes.md +66 -9
  134. package/dist/ai/source/BbTabsRoot.md +67 -9
  135. package/dist/ai/source/BbTag.md +6 -1
  136. package/dist/ai/source/BbTimePicker.md +40 -4
  137. package/dist/ai/source/BbTimePickerInput.md +47 -5
  138. package/dist/ai/source/BbToast.md +12 -3
  139. package/dist/ai/source/BbToastPortal.md +12 -3
  140. package/dist/ai/source/BbTooltip.md +10 -2
  141. package/dist/ai/source/BbTree.md +12 -2
  142. package/dist/ai/source/CommonTimeSelector.md +3 -3
  143. package/dist/ai/source/FlatListBox.md +54 -28
  144. package/dist/ai/source/GroupedListBox.md +71 -43
  145. package/dist/ai/source/ListBox.md +4 -3
  146. package/dist/ai/source/OptionsContainer.md +23 -8
  147. package/dist/components/BbAccordion/types.d.ts +13 -5
  148. package/dist/components/BbAlert/types.d.ts +9 -1
  149. package/dist/components/BbAsterisk/types.d.ts +5 -1
  150. package/dist/components/BbAvatar/types.d.ts +7 -1
  151. package/dist/components/BbBadge/types.d.ts +17 -8
  152. package/dist/components/BbBaseButton/types.d.ts +11 -2
  153. package/dist/components/BbBaseCheckboxIcon/types.d.ts +6 -1
  154. package/dist/components/BbBaseRadioIcon/types.d.ts +6 -1
  155. package/dist/components/BbBaseSwitchIcon/types.d.ts +6 -1
  156. package/dist/components/BbBreadcrumbs/types.d.ts +18 -2
  157. package/dist/components/BbButton/types.d.ts +31 -11
  158. package/dist/components/BbCalendar/BbCalendar.vue.d.ts +34 -0
  159. package/dist/components/BbCalendar/BbCalendar.vue.js +6 -0
  160. package/dist/components/BbCalendar/BbCalendar.vue_vue_type_script_setup_true_lang.js +576 -0
  161. package/dist/components/BbCalendar/CalendarMonthPanel.vue.js +5 -0
  162. package/dist/components/{BbDatePicker/DatePickerMonthPanel.vue_vue_type_script_setup_true_lang.js → BbCalendar/CalendarMonthPanel.vue_vue_type_script_setup_true_lang.js} +13 -13
  163. package/dist/components/BbCalendar/CalendarYearPanel.vue.js +5 -0
  164. package/dist/components/{BbDatePicker/DatePickerYearPanel.vue_vue_type_script_setup_true_lang.js → BbCalendar/CalendarYearPanel.vue_vue_type_script_setup_true_lang.js} +14 -14
  165. package/dist/components/BbCalendar/calendarHost.d.ts +29 -0
  166. package/dist/components/BbCalendar/calendarHost.js +10 -0
  167. package/dist/components/BbCalendar/types.d.ts +211 -0
  168. package/dist/components/BbCalendar/types.js +28 -0
  169. package/dist/components/{BbDatePicker/useDatePickerContext.d.ts → BbCalendar/useCalendarContext.d.ts} +8 -8
  170. package/dist/components/BbCalendar/useCalendarContext.js +11 -0
  171. package/dist/components/{BbDatePicker → BbCalendar}/useCalendarGrid.d.ts +14 -14
  172. package/dist/components/{BbDatePicker → BbCalendar}/useCalendarGrid.js +3 -3
  173. package/dist/components/{BbDatePicker → BbCalendar}/useDayGrid.d.ts +2 -2
  174. package/dist/components/{BbDatePicker → BbCalendar}/useDayGrid.js +2 -2
  175. package/dist/components/BbCheckboxGroup/BbCheckboxGroup.vue_vue_type_script_setup_true_lang.js +12 -5
  176. package/dist/components/BbCheckboxGroup/types.d.ts +9 -5
  177. package/dist/components/BbCollapsible/types.d.ts +10 -2
  178. package/dist/components/BbColorInput/types.d.ts +26 -11
  179. package/dist/components/BbColorPalette/BbColorPalette.vue_vue_type_script_setup_true_lang.js +200 -199
  180. package/dist/components/BbColorPalette/types.d.ts +31 -2
  181. package/dist/components/BbConfirm/types.d.ts +23 -10
  182. package/dist/components/BbDatePicker/BbDatePicker.vue.d.ts +5 -6
  183. package/dist/components/BbDatePicker/BbDatePicker.vue_vue_type_script_setup_true_lang.js +159 -526
  184. package/dist/components/BbDatePicker/types.d.ts +55 -22
  185. package/dist/components/BbDatePicker/types.js +4 -3
  186. package/dist/components/BbDatePickerInput/BbDatePickerInput.vue_vue_type_script_setup_true_lang.js +18 -2
  187. package/dist/components/BbDatePickerInput/types.d.ts +41 -4
  188. package/dist/components/BbDatePickerInput/types.js +1 -0
  189. package/dist/components/BbDialog/BbDialog.vue_vue_type_script_setup_true_lang.js +114 -102
  190. package/dist/components/BbDialog/types.d.ts +42 -4
  191. package/dist/components/BbDialog/types.js +1 -1
  192. package/dist/components/BbDialog/useDialogStack.d.ts +12 -0
  193. package/dist/components/BbDialog/useDialogStack.js +9 -2
  194. package/dist/components/BbDropdown/AdaptiveDropdown.vue_vue_type_script_setup_true_lang.js +42 -41
  195. package/dist/components/BbDropdown/BbDropdown.vue_vue_type_script_setup_true_lang.js +11 -7
  196. package/dist/components/BbDropdown/BbDropdownList.vue_vue_type_script_setup_true_lang.js +1 -1
  197. package/dist/components/BbDropdown/types.d.ts +55 -7
  198. package/dist/components/BbDropdown/types.js +1 -0
  199. package/dist/components/BbDropdownButton/BbDropdownButton.vue_vue_type_script_setup_true_lang.js +4 -4
  200. package/dist/components/BbDropdownButton/types.d.ts +39 -6
  201. package/dist/components/BbDropzone/types.d.ts +14 -2
  202. package/dist/components/BbIcon/types.d.ts +5 -4
  203. package/dist/components/BbIndicator/types.d.ts +8 -1
  204. package/dist/components/BbOffCanvas/BbOffCanvas.vue_vue_type_script_setup_true_lang.js +211 -194
  205. package/dist/components/BbOffCanvas/types.d.ts +26 -4
  206. package/dist/components/BbOffCanvas/types.js +1 -1
  207. package/dist/components/BbPagination/types.d.ts +15 -2
  208. package/dist/components/BbPopover/BbPopover.vue_vue_type_script_setup_true_lang.js +162 -161
  209. package/dist/components/BbPopover/types.d.ts +28 -2
  210. package/dist/components/BbProgress/types.d.ts +5 -1
  211. package/dist/components/BbRadioGroup/BbRadioGroup.vue_vue_type_script_setup_true_lang.js +12 -5
  212. package/dist/components/BbRadioGroup/types.d.ts +9 -5
  213. package/dist/components/BbRating/types.d.ts +24 -2
  214. package/dist/components/BbSelect/BbSelect.vue_vue_type_script_setup_true_lang.js +145 -129
  215. package/dist/components/BbSelect/types.d.ts +54 -11
  216. package/dist/components/BbSelect/types.js +1 -0
  217. package/dist/components/BbSelectPopover/BbSelectPopover.vue_vue_type_script_setup_true_lang.js +346 -330
  218. package/dist/components/BbSelectPopover/types.d.ts +69 -10
  219. package/dist/components/BbSelectPopover/types.js +1 -0
  220. package/dist/components/BbSlider/types.d.ts +22 -2
  221. package/dist/components/BbSmoothHeight/types.d.ts +2 -0
  222. package/dist/components/BbSpinner/types.d.ts +5 -1
  223. package/dist/components/BbSwitchGroup/BbSwitchGroup.vue_vue_type_script_setup_true_lang.js +12 -5
  224. package/dist/components/BbSwitchGroup/types.d.ts +1 -1
  225. package/dist/components/BbTable/BbTable.vue_vue_type_script_setup_true_lang.js +1 -1
  226. package/dist/components/BbTable/BbTableDataRow.js +1 -1
  227. package/dist/components/BbTable/types.d.ts +28 -5
  228. package/dist/components/BbTabs/BbTabs.vue_vue_type_script_setup_true_lang.js +3 -2
  229. package/dist/components/BbTabs/BbTabsList.vue.d.ts +3 -10
  230. package/dist/components/BbTabs/BbTabsList.vue_vue_type_script_setup_true_lang.js +32 -30
  231. package/dist/components/BbTabs/BbTabsRoot.vue_vue_type_script_setup_true_lang.js +3 -2
  232. package/dist/components/BbTabs/types.d.ts +56 -9
  233. package/dist/components/BbTag/types.d.ts +6 -1
  234. package/dist/components/BbTimePicker/BbTimePicker.vue_vue_type_script_setup_true_lang.js +77 -76
  235. package/dist/components/BbTimePicker/types.d.ts +31 -2
  236. package/dist/components/BbTimePickerInput/BbTimePickerInput.vue_vue_type_script_setup_true_lang.js +215 -205
  237. package/dist/components/BbTimePickerInput/types.d.ts +35 -4
  238. package/dist/components/BbTimePickerInput/types.js +1 -0
  239. package/dist/components/BbToast/types.d.ts +10 -1
  240. package/dist/components/BbTooltip/types.d.ts +10 -2
  241. package/dist/components/BbTree/BbTree.vue.d.ts +1 -1
  242. package/dist/components/BbTree/types.d.ts +12 -2
  243. package/dist/components/FlatListBox/FlatListBox.vue_vue_type_script_setup_true_lang.js +35 -35
  244. package/dist/components/FlatListBox/types.d.ts +4 -3
  245. package/dist/components/GroupedListBox/GroupedListBox.vue_vue_type_script_setup_true_lang.js +10 -10
  246. package/dist/components/GroupedListBox/types.d.ts +4 -3
  247. package/dist/components/ListBox/types.d.ts +4 -3
  248. package/dist/components/OptionsContainer/OptionsContainer.vue_vue_type_script_setup_true_lang.js +5 -5
  249. package/dist/components/OptionsContainer/types.d.ts +5 -4
  250. package/dist/composables/useBbTabsContext.d.ts +6 -0
  251. package/dist/composables/useBbTabsContext.js +2 -0
  252. package/dist/composables/usePassthrough.d.ts +18 -2
  253. package/dist/composables/usePassthrough.js +132 -109
  254. package/dist/index.d.ts +5 -1
  255. package/dist/index.js +59 -58
  256. package/dist/llms-full.txt +4139 -673
  257. package/dist/llms-medium.txt +165 -56
  258. package/dist/nuxt-auto-imports.js +1 -1
  259. package/dist/nuxt-module.d.ts +1 -0
  260. package/dist/styles.css +1 -1
  261. package/dist/tabs-variants.d.ts +18 -0
  262. package/dist/types/Config.d.ts +13 -0
  263. package/dist/types/TabsVariant.d.ts +17 -0
  264. package/dist/types/passthrough.d.ts +125 -12
  265. package/dist/types/passthrough.js +1 -0
  266. package/dist/types/ptComponentMap.d.ts +11 -10
  267. package/dist/utilities/functions/hasVnodeListener.d.ts +16 -0
  268. package/dist/utilities/functions/hasVnodeListener.js +12 -0
  269. package/dist/utils/passthrough.d.ts +29 -0
  270. package/dist/utils/passthrough.js +35 -24
  271. package/dist/validated/BbCheckboxGroup.vue.d.ts +13 -5
  272. package/dist/validated/BbCheckboxGroup.vue_vue_type_script_setup_true_lang.js +11 -4
  273. package/dist/validated/BbDatePickerInput.vue_vue_type_script_setup_true_lang.js +16 -0
  274. package/dist/validated/BbRadioGroup.vue.d.ts +13 -5
  275. package/dist/validated/BbRadioGroup.vue_vue_type_script_setup_true_lang.js +11 -4
  276. package/dist/validated/BbSelect.vue.d.ts +16 -6
  277. package/dist/validated/BbSelect.vue_vue_type_script_setup_true_lang.js +17 -5
  278. package/dist/validated/BbSwitchGroup.vue.d.ts +13 -5
  279. package/dist/validated/BbSwitchGroup.vue_vue_type_script_setup_true_lang.js +11 -4
  280. package/dist/validated/BbTimePickerInput.vue_vue_type_script_setup_true_lang.js +9 -0
  281. package/dist/validated/index.d.ts +1 -0
  282. package/dist/vite-plugin.d.ts +30 -1
  283. package/dist/vite.js +224 -197
  284. package/package.json +5 -4
  285. package/dist/components/BbDatePicker/DatePickerMonthPanel.vue.js +0 -5
  286. package/dist/components/BbDatePicker/DatePickerYearPanel.vue.js +0 -5
  287. package/dist/components/BbDatePicker/useDatePickerContext.js +0 -11
  288. /package/dist/components/{BbDatePicker/DatePickerMonthPanel.vue.d.ts → BbCalendar/CalendarMonthPanel.vue.d.ts} +0 -0
  289. /package/dist/components/{BbDatePicker/DatePickerYearPanel.vue.d.ts → BbCalendar/CalendarYearPanel.vue.d.ts} +0 -0
@@ -101,7 +101,7 @@ function coreRules(version) {
101
101
  5. **Icons**: discover names first; never invent them (\`${KNOWLEDGE_BASE}/guides/icons-policy.md\`).
102
102
  6. **Item-driven components**: declarative \`items\` / \`item-text\` / \`item-value\`, \`dependencies\`, \`enforce-coherence\` — no manual watchers for coherence.
103
103
  7. **Whole pages**: one recipe under \`${KNOWLEDGE_BASE}/recipes/{vue|nuxt|inertia}/\` (see the router table).
104
- 8. **CSS near components**: \`${KNOWLEDGE_BASE}/guides/design-language.md\`. Two token tiers, and reaching for the wrong one is why apps end up re-skinning by class: \`--bb-*\` is the small GLOBAL theme tier (brand knobs, ~90 names, no numeric ramp — there is no \`--bb-primary-800\`), while each component declares its own **unprefixed** \`--*\` tokens for its look (\`.bb-table { --cell-h: 32px }\`). A missing \`--bb-*\` name is not a gap in the library — it means the knob you want is a component token. Set it on the element that DECLARES it (grep \`${KNOWLEDGE_BASE}/source/<ComponentName>.md\`); a value set further out is masked, not inherited. Never override \`.bb-*__*\` internals, and never target \`.bb-base-*\` / \`.bb-common-*\` at all. **A Tailwind utility on a \`Bb*\` component that does nothing** is not a library bug: Tailwind v4 emits layered CSS and unlayered CSS outranks it, whatever the specificity. The fix is in the BUILD plugin, not in CSS — \`cssLayers: TAILWIND_V4_LAYERS\` (imported from \`bitboss-ui/vite\`) in \`vite.config.*\` / \`nuxt.config.*\`; see \`${KNOWLEDGE_BASE}/guides/installation-and-plugin-setup.md\` § Cascade layers. One primary action per view region.
104
+ 8. **CSS near components**: \`${KNOWLEDGE_BASE}/guides/design-language.md\`. Two token tiers, and reaching for the wrong one is why apps end up re-skinning by class: \`--bb-*\` is the small GLOBAL theme tier (brand knobs, ~90 names, no numeric ramp — there is no \`--bb-primary-800\`), while each component declares its own **unprefixed** \`--*\` tokens for its look (\`.bb-table { --cell-h: 32px }\`). A missing \`--bb-*\` name is not a gap in the library — it means the knob you want is a component token. Set it on the element that DECLARES it (grep \`${KNOWLEDGE_BASE}/source/<ComponentName>.md\`); a value set further out is masked, not inherited. Prefer tokens, variants and \`pt\`; CSS on \`.bb-*__*\` internals is allowed for fine-tuning but unsupported: it can break on upgrade. \`.bb-common-*\` / \`.bb-field*\` internals: expect it to break. (\`.bb-base-button\` and the three \`.bb-base-*-icon\` glyph classes are consumer API — a supported hook, not an internal.) An override on an internal is a signal to check for a \`pt\` part or request one. **A Tailwind utility on a \`Bb*\` component that does nothing** is not a library bug: Tailwind v4 emits layered CSS and unlayered CSS outranks it, whatever the specificity. The fix is in the BUILD plugin, not in CSS — \`cssLayers: TAILWIND_V4_LAYERS\` (imported from \`bitboss-ui/vite\`) in \`vite.config.*\` / \`nuxt.config.*\`; see \`${KNOWLEDGE_BASE}/guides/installation-and-plugin-setup.md\` § Cascade layers. One primary action per view region.
105
105
  9. **Variants are yours to add**: the shipped \`variant\` names are a floor, not a ceiling. When the design needs a colour the library doesn't ship (soft status badges, a brand button tone), **register the name** in the build plugin's \`badgeVariants\`/\`buttonVariants\`/\`alertVariants\`/… and **style \`.bb-badge--<name>\`** (etc.) in a project stylesheet loaded after \`bitboss-ui/styles.css\`. Do both halves — a registered name with no CSS ships an unstyled pill, and CSS with no registration fails \`vue-tsc\`. Never write an unregistered name, and never downgrade the design to a neutral shipped variant to avoid registering. Canonical palette + snippet: \`${KNOWLEDGE_BASE}/guides/design-language.md\` § Getting soft semantic badges.
106
106
  10. **After writing bitboss-ui markup**, run \`npx bitboss-ui check\` — validates \`Bb*\` usage against the installed \`components.json\` and catches invented/removed props before review.
107
107
 
@@ -10,7 +10,7 @@
10
10
 
11
11
  ## Reachable through `BbAccordion`
12
12
 
13
- `BbAccordion` mounts other components (all of them: _Component tree_, near the end). These are the parts of its API that land inside them. Use them — never `:deep()` on an inner class, never an import of an internal component.
13
+ `BbAccordion` mounts other components (all of them: _Component tree_, near the end). These are the parts of its API that land inside them. Prefer these over `:deep()` on an inner class (allowed, unsupported: it can break on upgrade) — and never an import of an internal component.
14
14
 
15
15
  | pt part | Lands on | In |
16
16
  | --- | --- | --- |
@@ -617,12 +617,28 @@ grammar, the merge rules and the global map are in the
617
617
 
618
618
  | Prop | Type | Default | Required | Description |
619
619
  | --- | --- | --- | --- | --- |
620
- | `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: `header`, `panel`, `root`. States: `open`. `pt` is the object form with the same keys minus the prefix (`{ icon: '…', 'icon:loading': '…' }`). See `guides/passthrough.md`. |
620
+ | `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: `header`, `panel`, `root`. States: `open`. 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`. |
621
621
  | `eager` | `boolean \| undefined` | `false` | | Prevents rendering content before it's made visible. |
622
622
  | `id` | `string \| undefined` | | | The identifier of the component. |
623
623
  | `modelValue` | `boolean \| undefined` | `false` | | Used by v-model to trigger opening / closing the collapsible. An accordion with no `v-model` starts closed. |
624
624
  | `transitionDuration` | `number \| undefined` | `250` | | How long the transition has to last in milliseconds |
625
625
 
626
+ ## Passthrough parts and states
627
+
628
+ `pt:<part>="…"` restyles a part; `pt:<part>:<state>="…"` applies only while the state is on. A component-wide state is on for every part at once; a _per node_ state resolves on each node of a broadcast part (one row, one option, one day). Grammar and merge rules: `guides/passthrough.md`.
629
+
630
+ | Part | What it is |
631
+ | --- | --- |
632
+ | `root` | The accordion's outer element: the header and its panel. |
633
+ | `header` | The trigger button that opens and closes the panel. Its content is your slot markup — there is no chevron of ours, so no `icon` part. |
634
+ | `panel` | The region the header controls (the ARIA accordion panel). |
635
+
636
+ States are listed in precedence order: when two are on at once and their entries conflict, the later one wins.
637
+
638
+ | State | When it is on |
639
+ | --- | --- |
640
+ | `open` | Component-wide: the panel is open (follows `v-model`). |
641
+
626
642
  ## Events
627
643
 
628
644
  - `update:modelValue` — `(event: "update:modelValue", value: boolean): void`
@@ -10,7 +10,7 @@
10
10
 
11
11
  ## Reachable through `BbAlert`
12
12
 
13
- `BbAlert` mounts other components (all of them: _Component tree_, near the end). These are the parts of its API that land inside them. Use them — never `:deep()` on an inner class, never an import of an internal component.
13
+ `BbAlert` mounts other components (all of them: _Component tree_, near the end). These are the parts of its API that land inside them. Prefer these over `:deep()` on an inner class (allowed, unsupported: it can break on upgrade) — and never an import of an internal component.
14
14
 
15
15
  | pt part | Lands on | In |
16
16
  | --- | --- | --- |
@@ -448,7 +448,7 @@ full grammar, the merge rules and the global map are in the
448
448
 
449
449
  | Prop | Type | Default | Required | Description |
450
450
  | --- | --- | --- | --- | --- |
451
- | `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: . `pt` is the object form with the same keys minus the prefix (`{ icon: '…', 'icon:loading': '…' }`). See `guides/passthrough.md`. |
451
+ | `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: —. 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`. |
452
452
  | `ariaLive` | `"off" \| "polite" \| "assertive" \| undefined` | | | ARIA live region politeness. Defaults to `'assertive'` for destructive/warning variants, otherwise `'polite'`. |
453
453
  | `closeLabel` | `string \| undefined` | | | Visually hidden string used to label the close button. |
454
454
  | `hideClose` | `boolean \| undefined` | `false` | | Defines whether to hide the close button. |
@@ -461,6 +461,18 @@ full grammar, the merge rules and the global map are in the
461
461
  | `transitionDuration` | `number \| undefined` | `250` | | Transition duration in milliseconds for enter/leave. |
462
462
  | `variant` | `keyof AlertVariantRegistry \| undefined` | `"outline"` | | Visual variant of the alert. |
463
463
 
464
+ ## Passthrough parts and states
465
+
466
+ `pt:<part>="…"` restyles a part; `pt:<part>:<state>="…"` applies only while the state is on. A component-wide state is on for every part at once; a _per node_ state resolves on each node of a broadcast part (one row, one option, one day). Grammar and merge rules: `guides/passthrough.md`.
467
+
468
+ | Part | What it is |
469
+ | --- | --- |
470
+ | `root` | The alert box. |
471
+ | `icon` | The leading glyph — rendered only when an `icon` is set. |
472
+ | `title` | The heading line. |
473
+ | `text` | The body copy. |
474
+ | `close` | The ✕ that dismisses the alert. |
475
+
464
476
  ## Events
465
477
 
466
478
  - `update:modelValue` — `(event: "update:modelValue", value: boolean): void`
@@ -79,7 +79,15 @@ The full grammar, the merge rules and the global map are in the
79
79
 
80
80
  | Prop | Type | Default | Required | Description |
81
81
  | --- | --- | --- | --- | --- |
82
- | `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: . `pt` is the object form with the same keys minus the prefix (`{ icon: '…', 'icon:loading': '…' }`). See `guides/passthrough.md`. |
82
+ | `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: —. 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`. |
83
+
84
+ ## Passthrough parts and states
85
+
86
+ `pt:<part>="…"` restyles a part; `pt:<part>:<state>="…"` applies only while the state is on. A component-wide state is on for every part at once; a _per node_ state resolves on each node of a broadcast part (one row, one option, one day). Grammar and merge rules: `guides/passthrough.md`.
87
+
88
+ | Part | What it is |
89
+ | --- | --- |
90
+ | `root` | The required-marker span. |
83
91
 
84
92
  ## Events
85
93
 
@@ -10,7 +10,7 @@
10
10
 
11
11
  ## Reachable through `BbAvatar`
12
12
 
13
- `BbAvatar` mounts other components (all of them: _Component tree_, near the end). These are the parts of its API that land inside them. Use them — never `:deep()` on an inner class, never an import of an internal component.
13
+ `BbAvatar` mounts other components (all of them: _Component tree_, near the end). These are the parts of its API that land inside them. Prefer these over `:deep()` on an inner class (allowed, unsupported: it can break on upgrade) — and never an import of an internal component.
14
14
 
15
15
  | pt part | Lands on | In |
16
16
  | --- | --- | --- |
@@ -614,7 +614,7 @@ available in visible text or an adjacent label.
614
614
 
615
615
  | Prop | Type | Default | Required | Description |
616
616
  | --- | --- | --- | --- | --- |
617
- | `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: `icon`, `root`. States: . `pt` is the object form with the same keys minus the prefix (`{ icon: '…', 'icon:loading': '…' }`). See `guides/passthrough.md`. |
617
+ | `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: `icon`, `root`. States: —. 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`. |
618
618
  | `alt` | `string \| undefined` | `""` | | Alternative text for the image, used for accessibility. |
619
619
  | `size` | `number \| ({ size?: any; } & string) \| keyof Sizes \| undefined` | `"md"` | | Defines the component size. Accepted values: - A key from the provided size map (`keyof T`), e.g. `'sm' \| 'md' \| 'lg'` - A custom CSS size string (e.g. `'20px'`, `'1.5rem'`, `'2em'`) - A number, typically interpreted as pixels by size par… |
620
620
  | `sizes` | `string \| undefined` | | | Sizes attribute for the image, used with `srcset`. |
@@ -622,6 +622,15 @@ available in visible text or an adjacent label.
622
622
  | `srcset` | `string \| undefined` | | | Responsive image source set. |
623
623
  | `timeout` | `number \| undefined` | `400` | | Milliseconds to wait after mount before checking whether the image loaded correctly (SSR fallback). |
624
624
 
625
+ ## Passthrough parts and states
626
+
627
+ `pt:<part>="…"` restyles a part; `pt:<part>:<state>="…"` applies only while the state is on. A component-wide state is on for every part at once; a _per node_ state resolves on each node of a broadcast part (one row, one option, one day). Grammar and merge rules: `guides/passthrough.md`.
628
+
629
+ | Part | What it is |
630
+ | --- | --- |
631
+ | `root` | The avatar frame, with the image or the fallback inside. |
632
+ | `icon` | The default user glyph — rendered only while there is no image to show and the default slot is not overridden, so it lands nowhere otherwise. |
633
+
625
634
  ## Events
626
635
 
627
636
  - None.
@@ -10,7 +10,7 @@
10
10
 
11
11
  ## Reachable through `BbBadge`
12
12
 
13
- `BbBadge` mounts other components (all of them: _Component tree_, near the end). These are the parts of its API that land inside them. Use them — never `:deep()` on an inner class, never an import of an internal component.
13
+ `BbBadge` mounts other components (all of them: _Component tree_, near the end). These are the parts of its API that land inside them. Prefer these over `:deep()` on an inner class (allowed, unsupported: it can break on upgrade) — and never an import of an internal component.
14
14
 
15
15
  | pt part | Lands on | In |
16
16
  | --- | --- | --- |
@@ -839,7 +839,7 @@ The full grammar, the merge rules and the global map are in the
839
839
 
840
840
  | Prop | Type | Default | Required | Description |
841
841
  | --- | --- | --- | --- | --- |
842
- | `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: `clear`, `icon`, `root`, `spinner`, `text`. States: `loading`. `pt` is the object form with the same keys minus the prefix (`{ icon: '…', 'icon:loading': '…' }`). See `guides/passthrough.md`. |
842
+ | `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: `clear`, `icon`, `root`, `spinner`, `text`. States: `loading`. 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`. |
843
843
  | `append:icon` | `string \| undefined` | | | Icon rendered after the label. On a `clearable` badge it shares the trailing slot with the clear button: the icon shows at rest and the clear button reveals over it on hover/focus. |
844
844
  | `clearable` | `boolean \| undefined` | `false` | | Renders a trailing clear button and emits `click:clear` when pressed — turns the badge into a dismissible token (the pattern formerly served by `BbChip`). |
845
845
  | `clearableLabel` | `string \| undefined` | | | Accessible label for the clear button. Rarely needed: unset, the name is **composed** from the localized `badge.clearLabel` verb and the badge's own text — "Remove Italy", not a bare "Remove" — which is already the right name in almost ever… |
@@ -849,6 +849,24 @@ The full grammar, the merge rules and the global map are in the
849
849
  | `size` | `keyof Sizes \| undefined` | `"md"` | | Preset size of the badge. |
850
850
  | `variant` | `keyof BadgeVariantRegistry \| undefined` | `"primary"` | | Visual variant: `primary`, `secondary`, `destructive`, or `outline`. Register more via the vite plugin `badgeVariants` option and style `.bb-badge--<variant>` (set `--bg` / `--fg`). |
851
851
 
852
+ ## Passthrough parts and states
853
+
854
+ `pt:<part>="…"` restyles a part; `pt:<part>:<state>="…"` applies only while the state is on. A component-wide state is on for every part at once; a _per node_ state resolves on each node of a broadcast part (one row, one option, one day). Grammar and merge rules: `guides/passthrough.md`.
855
+
856
+ | Part | What it is |
857
+ | --- | --- |
858
+ | `root` | The badge. |
859
+ | `icon` | Every content glyph — the `icon`-mode glyph, `prepend:icon`, `append:icon` — a broadcast. The clear ✕ is not in it. |
860
+ | `spinner` | The loading glyph. It REPLACES an icon while `loading` (on a button it joins one instead). |
861
+ | `text` | The label span; it owns the truncation. |
862
+ | `clear` | The ✕ that removes the badge (`clearable`). |
863
+
864
+ States are listed in precedence order: when two are on at once and their entries conflict, the later one wins.
865
+
866
+ | State | When it is on |
867
+ | --- | --- |
868
+ | `loading` | Component-wide: `loading` is on; the spinner takes an icon's place. |
869
+
852
870
  ## Events
853
871
 
854
872
  - `click:clear` — `(event: "click:clear", event: MouseEvent): void`
@@ -871,7 +889,7 @@ Set these on the element, or on a class you put on it, to retune this component
871
889
  | `--min-size-md` | `.bb-badge` | `16px` | The md value. Only the default --min-size below reads it; the size modifiers set --min-size directly. |
872
890
  | `--min-size` | `.bb-badge` | `var(--min-size-md)` | pill min height and min width |
873
891
  | `--elev` | `.bb-badge` | `var(--bb-elev-sm)` | Resting lift. Invisible while `--bb-elev` is its default transparent layer. A chip is small enough that a theme wanting a different lift here than on a button sets `--elev` on this class. |
874
- | `--radius` | `.bb-badge` | `calc(var(--bb-radius) * 0.5)` | Pill corners; the body and trailing wrappers round their outer edges to match |
892
+ | `--r` | `.bb-badge` | `calc(var(--bb-radius) * 0.5)` | Pill corners; the body and trailing wrappers round their outer edges to match |
875
893
  | `--font-size` | `.bb-badge` | `10px` | label |
876
894
  | `--icon-size` | `.bb-badge` | `12px` | leading/append icons (passed to BbIcon as --size) |
877
895
  | `--gap` | `.bb-badge` | `3px` | space between label, icons and the trailing side |
@@ -12,7 +12,7 @@
12
12
 
13
13
  | Prop | Type | Default | Required | Description |
14
14
  | --- | --- | --- | --- | --- |
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: `disabled`. `pt` is the object form with the same keys minus the prefix (`{ icon: '…', 'icon:loading': '…' }`). See `guides/passthrough.md`. |
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: `disabled`. 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`. |
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
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. |
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. |
@@ -54,6 +54,20 @@
54
54
  | `type` | `"button" \| "submit" \| "reset" \| 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
+ ## Passthrough parts and states
58
+
59
+ `pt:<part>="…"` restyles a part; `pt:<part>:<state>="…"` applies only while the state is on. A component-wide state is on for every part at once; a _per node_ state resolves on each node of a broadcast part (one row, one option, one day). Grammar and merge rules: `guides/passthrough.md`.
60
+
61
+ | Part | What it is |
62
+ | --- | --- |
63
+ | `root` | Whichever element renders — the `<button>`, the `<a>` or the router link. A `class` on the component lands here too. The label is your slot markup. |
64
+
65
+ States are listed in precedence order: when two are on at once and their entries conflict, the later one wins.
66
+
67
+ | State | When it is on |
68
+ | --- | --- |
69
+ | `disabled` | Component-wide: the button is `disabled`. |
70
+
57
71
  ## Events
58
72
 
59
73
  - None.
@@ -76,7 +90,7 @@ Set these on the element, or on a class you put on it, to retune this component
76
90
  | `--min-size-md` | `.bb-badge` | `16px` | The md value. Only the default --min-size below reads it; the size modifiers set --min-size directly. |
77
91
  | `--min-size` | `.bb-badge` | `var(--min-size-md)` | pill min height and min width |
78
92
  | `--elev` | `.bb-badge` | `var(--bb-elev-sm)` | Resting lift. Invisible while `--bb-elev` is its default transparent layer. A chip is small enough that a theme wanting a different lift here than on a button sets `--elev` on this class. |
79
- | `--radius` | `.bb-badge` | `calc(var(--bb-radius) * 0.5)` | Pill corners; the body and trailing wrappers round their outer edges to match |
93
+ | `--r` | `.bb-badge` | `calc(var(--bb-radius) * 0.5)` | Pill corners; the body and trailing wrappers round their outer edges to match |
80
94
  | `--font-size` | `.bb-badge` | `10px` | label |
81
95
  | `--icon-size` | `.bb-badge` | `12px` | leading/append icons (passed to BbIcon as --size) |
82
96
  | `--gap` | `.bb-badge` | `3px` | space between label, icons and the trailing side |
@@ -10,7 +10,7 @@
10
10
 
11
11
  ## Reachable through `BbBaseButton`
12
12
 
13
- `BbBaseButton` mounts other components (all of them: _Component tree_, near the end). These are the parts of its API that land inside them. Use them — never `:deep()` on an inner class, never an import of an internal component.
13
+ `BbBaseButton` mounts other components (all of them: _Component tree_, near the end). These are the parts of its API that land inside them. Prefer these over `:deep()` on an inner class (allowed, unsupported: it can break on upgrade) — and never an import of an internal component.
14
14
 
15
15
  | pt part | Lands on | In |
16
16
  | --- | --- | --- |
@@ -135,21 +135,26 @@ the right base for a clickable card or a bespoke nav item:
135
135
  </div>
136
136
  ```
137
137
 
138
- A whole card as a single navigable element — the primitive's signature use:
138
+ A clickable card — the primitive's signature use. The card stays a plain box
139
+ and one **overlay** `BbBaseButton` covers it (the stretched-link pattern), so
140
+ the link's accessible name is a short visually-hidden phrase rather than the
141
+ card's entire content, and the badge, the meta line and any nested control
142
+ stay outside the link:
139
143
 
140
144
  **A clickable card built on the primitive**
141
145
 
142
146
  ```vue
143
147
  <template>
144
148
  <div class="grid max-w-md gap-2 sm:grid-cols-2">
145
- <!-- The whole card is ONE navigable element — a BbBaseButton rendered as an
146
- anchor, styled entirely by these utility classes. No wrapper <a>, no
147
- @click; navigation rides on `href` (a `to`/Inertia target works the same). -->
148
- <BbBaseButton
149
+ <!-- The card is a plain box; ONE overlay BbBaseButton covers it (the
150
+ stretched-link pattern). Its accessible name is the short sr-only
151
+ text, not the card's whole content; the badge stays outside the link.
152
+ Focus shows on the card via `has-focus-visible:`, never on the
153
+ invisible overlay (`outline-none`). -->
154
+ <article
149
155
  v-for="project in projects"
150
156
  :key="project.name"
151
- class="project-card flex flex-col items-start gap-1.5 rounded-(--bb-radius) border border-(--bb-border) bg-(--bb-panel) p-3 text-left hover:bg-(--bb-surface-hover)"
152
- :href="project.href"
157
+ 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)"
153
158
  >
154
159
  <span class="flex w-full items-center justify-between gap-2">
155
160
  <span
@@ -161,7 +166,14 @@ A whole card as a single navigable element — the primitive's signature use:
161
166
  </span>
162
167
  <span class="text-sm font-medium">{{ project.name }}</span>
163
168
  <span class="text-xs text-(--bb-text-muted)">{{ project.meta }}</span>
164
- </BbBaseButton>
169
+
170
+ <BbBaseButton
171
+ class="absolute inset-0 rounded-[inherit] outline-none"
172
+ :href="project.href"
173
+ >
174
+ <span class="sr-only">Open {{ project.name }}</span>
175
+ </BbBaseButton>
176
+ </article>
165
177
  </div>
166
178
  </template>
167
179
 
@@ -193,15 +205,23 @@ const projects: Project[] = [
193
205
  },
194
206
  ];
195
207
  </script>
196
-
197
- <style scoped>
198
- /* Visible focus uses the base ring scaffold (box-shadow / --bb-ring). */
199
- .project-card:focus-visible {
200
- box-shadow: 0 0 0 var(--bb-ring-size) var(--bb-ring);
201
- }
202
- </style>
203
208
  ```
204
209
 
210
+ - **Overlay when** the card has several pieces of information, badges,
211
+ nested controls or long text. One `BbBaseButton` with `absolute inset-0`
212
+ and an `sr-only` name (`Open {{ project.name }}`) covers the box; nested
213
+ controls sit above it with `relative z-10` and stay clickable.
214
+ - **Wrap when** the row's whole content _is_ its label — "Manage
215
+ subscription ›", a menu-like list row, an icon plus a word. Then the
216
+ element's own text is the right accessible name, and `BbBaseButton` wraps
217
+ it as in the pill above.
218
+ - **Optional links:** render the overlay only when there is a destination
219
+ (`v-if="href"`); the card needs no other change — no `tag` switching.
220
+ - **Focus:** the overlay is invisible, so show focus on the card
221
+ (`has-focus-visible:ring-2 has-focus-visible:ring-(--bb-ring)`) and drop it
222
+ from the overlay (`outline-none`; the primitive's own ring scaffold is
223
+ zero-width until you style it).
224
+
205
225
  ### Label
206
226
 
207
227
  Same as `BbButton`: **prefer the default slot** (`<BbBaseButton>Label</BbBaseButton>`);
@@ -485,7 +505,7 @@ The full grammar, the merge rules and the global map are in the
485
505
 
486
506
  | Prop | Type | Default | Required | Description |
487
507
  | --- | --- | --- | --- | --- |
488
- | `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: `disabled`. `pt` is the object form with the same keys minus the prefix (`{ icon: '…', 'icon:loading': '…' }`). See `guides/passthrough.md`. |
508
+ | `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: `disabled`. 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`. |
489
509
  | `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. |
490
510
  | `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. |
491
511
  | `async` | `boolean \| undefined` | `false` | | Inertia: runs the visit without blocking — the page stays interactive and several async visits can be in flight at once. |
@@ -529,6 +549,20 @@ The full grammar, the merge rules and the global map are in the
529
549
  | `type` | `"button" \| "submit" \| "reset" \| undefined` | `"button"` | | Native `type` attribute used when rendering as a button (e.g. `button`, `submit`, `reset`). |
530
550
  | `viewTransition` | `boolean \| undefined` | `false` | | Inertia: run the page swap inside a View Transition, where the browser supports one. |
531
551
 
552
+ ## Passthrough parts and states
553
+
554
+ `pt:<part>="…"` restyles a part; `pt:<part>:<state>="…"` applies only while the state is on. A component-wide state is on for every part at once; a _per node_ state resolves on each node of a broadcast part (one row, one option, one day). Grammar and merge rules: `guides/passthrough.md`.
555
+
556
+ | Part | What it is |
557
+ | --- | --- |
558
+ | `root` | Whichever element renders — the `<button>`, the `<a>` or the router link. A `class` on the component lands here too. The label is your slot markup. |
559
+
560
+ States are listed in precedence order: when two are on at once and their entries conflict, the later one wins.
561
+
562
+ | State | When it is on |
563
+ | --- | --- |
564
+ | `disabled` | Component-wide: the button is `disabled`. |
565
+
532
566
  ## Events
533
567
 
534
568
  - None.
@@ -202,7 +202,7 @@ The full grammar, the merge rules and the global map are in the
202
202
 
203
203
  | Prop | Type | Default | Required | Description |
204
204
  | --- | --- | --- | --- | --- |
205
- | `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: `checked`, `disabled`, `errors`, `focus-visible`, `focused`, `indeterminate`, `readonly`, `warnings`. `pt` is the object form with the same keys minus the prefix (`{ icon: '…', 'icon:loading': '…' }`). See `guides/passthrough.md`. |
205
+ | `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: `checked`, `disabled`, `errors`, `focus-visible`, `focused`, `indeterminate`, `readonly`, `warnings`. 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`. |
206
206
  | `checked` | `boolean \| undefined` | `false` | | Renders the checked state (fills the box and draws the checkmark). |
207
207
  | `disabled` | `boolean \| undefined` | `false` | | Disables the glyph (muted fill, not-allowed cursor). Purely visual. |
208
208
  | `focused` | `boolean \| undefined` | `false` | | Whether the paired native input has focus — any focus, mouse included. Paints `--focused`, the hook the `focused` passthrough state aliases (T19); draws nothing by itself — the ring stays on `focusVisible`. |
@@ -212,6 +212,27 @@ The full grammar, the merge rules and the global map are in the
212
212
  | `indeterminate` | `boolean \| undefined` | `false` | | Renders the indeterminate state (filled box with a dash instead of the checkmark). Takes visual precedence over `checked`. |
213
213
  | `readonly` | `boolean \| undefined` | `false` | | Renders the read-only affordance (default cursor instead of pointer). |
214
214
 
215
+ ## Passthrough parts and states
216
+
217
+ `pt:<part>="…"` restyles a part; `pt:<part>:<state>="…"` applies only while the state is on. A component-wide state is on for every part at once; a _per node_ state resolves on each node of a broadcast part (one row, one option, one day). Grammar and merge rules: `guides/passthrough.md`.
218
+
219
+ | Part | What it is |
220
+ | --- | --- |
221
+ | `root` | The drawn glyph — the box and its checkmark. Its states are the conditions it paints as it resolves them (`warnings` is off while `errors` is on), not the raw props. |
222
+
223
+ States are listed in precedence order: when two are on at once and their entries conflict, the later one wins.
224
+
225
+ | State | When it is on |
226
+ | --- | --- |
227
+ | `checked` | Component-wide: the toggle is on. |
228
+ | `indeterminate` | Component-wide: the mixed state (the `indeterminate` prop) — neither on nor off. |
229
+ | `readonly` | Component-wide: the toggle is `readonly` — focusable, cannot change. |
230
+ | `disabled` | Component-wide: the toggle is `disabled`. |
231
+ | `warnings` | Component-wide: the toggle shows warnings and no errors. |
232
+ | `errors` | Component-wide: the toggle shows errors — the glyph and the message line turn red. |
233
+ | `focused` | Component-wide: the native input has focus — any focus, mouse included, like the `focused` slot prop. |
234
+ | `focus-visible` | Component-wide: that focus is keyboard-visible — where a focus ring belongs. |
235
+
215
236
  ## Events
216
237
 
217
238
  - None.
@@ -217,7 +217,7 @@ The full grammar, the merge rules and the global map are in the
217
217
 
218
218
  | Prop | Type | Default | Required | Description |
219
219
  | --- | --- | --- | --- | --- |
220
- | `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: `checked`, `disabled`, `errors`, `focus-visible`, `focused`, `readonly`, `warnings`. `pt` is the object form with the same keys minus the prefix (`{ icon: '…', 'icon:loading': '…' }`). See `guides/passthrough.md`. |
220
+ | `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: `checked`, `disabled`, `errors`, `focus-visible`, `focused`, `readonly`, `warnings`. 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`. |
221
221
  | `checked` | `boolean \| undefined` | `false` | | Renders the checked state (grows the inner dot). |
222
222
  | `disabled` | `boolean \| undefined` | `false` | | Disables the glyph (muted fill, not-allowed cursor). Purely visual. |
223
223
  | `focused` | `boolean \| undefined` | `false` | | Whether the paired native input has focus — any focus, mouse included. Paints `--focused`, the hook the `focused` passthrough state aliases (T19); draws nothing by itself — the ring stays on `focusVisible`. |
@@ -226,6 +226,26 @@ The full grammar, the merge rules and the global map are in the
226
226
  | `hasWarnings` | `boolean \| undefined` | `false` | | Puts the glyph into the warning state (warn border and ring color). Errors take priority when both are set. |
227
227
  | `readonly` | `boolean \| undefined` | `false` | | Renders the read-only affordance (default cursor instead of pointer). |
228
228
 
229
+ ## Passthrough parts and states
230
+
231
+ `pt:<part>="…"` restyles a part; `pt:<part>:<state>="…"` applies only while the state is on. A component-wide state is on for every part at once; a _per node_ state resolves on each node of a broadcast part (one row, one option, one day). Grammar and merge rules: `guides/passthrough.md`.
232
+
233
+ | Part | What it is |
234
+ | --- | --- |
235
+ | `root` | The drawn glyph — the ring and its dot. Its states are the conditions it paints as it resolves them (`warnings` is off while `errors` is on), not the raw props. |
236
+
237
+ States are listed in precedence order: when two are on at once and their entries conflict, the later one wins.
238
+
239
+ | State | When it is on |
240
+ | --- | --- |
241
+ | `checked` | Component-wide: the toggle is on. |
242
+ | `readonly` | Component-wide: the toggle is `readonly` — focusable, cannot change. |
243
+ | `disabled` | Component-wide: the toggle is `disabled`. |
244
+ | `warnings` | Component-wide: the toggle shows warnings and no errors. |
245
+ | `errors` | Component-wide: the toggle shows errors — the glyph and the message line turn red. |
246
+ | `focused` | Component-wide: the native input has focus — any focus, mouse included, like the `focused` slot prop. |
247
+ | `focus-visible` | Component-wide: that focus is keyboard-visible — where a focus ring belongs. |
248
+
229
249
  ## Events
230
250
 
231
251
  - None.
@@ -122,7 +122,7 @@ Restyle by overriding the glyph's CSS custom properties on it:
122
122
  - `--thumb` — thumb diameter (default `16px`)
123
123
  - `--accent` — track fill when checked (default `--bb-primary`)
124
124
  - `--bg` — track fill when off (default `--bb-track`)
125
- - `--radius` — track/thumb rounding (default `999px`)
125
+ - `--r` — track/thumb rounding (default `999px`)
126
126
 
127
127
  **On the element itself, not an ancestor.** Each of these is declared on the
128
128
  glyph's own class, and a declaration on the element always beats one inherited
@@ -213,7 +213,7 @@ The full grammar, the merge rules and the global map are in the
213
213
 
214
214
  | Prop | Type | Default | Required | Description |
215
215
  | --- | --- | --- | --- | --- |
216
- | `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: `checked`, `disabled`, `errors`, `focus-visible`, `focused`, `indeterminate`, `readonly`, `warnings`. `pt` is the object form with the same keys minus the prefix (`{ icon: '…', 'icon:loading': '…' }`). See `guides/passthrough.md`. |
216
+ | `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: `checked`, `disabled`, `errors`, `focus-visible`, `focused`, `indeterminate`, `readonly`, `warnings`. 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`. |
217
217
  | `checked` | `boolean \| undefined` | `false` | | Renders the checked state (fills the track and slides the thumb to the end). |
218
218
  | `disabled` | `boolean \| undefined` | `false` | | Disables the glyph (muted track, not-allowed cursor). Purely visual. |
219
219
  | `focused` | `boolean \| undefined` | `false` | | Whether the paired native input has focus — any focus, mouse included. Paints `--focused`, the hook the `focused` passthrough state aliases (T19); draws nothing by itself — the ring stays on `focusVisible`. |
@@ -223,6 +223,27 @@ The full grammar, the merge rules and the global map are in the
223
223
  | `indeterminate` | `boolean \| undefined` | `false` | | Renders the indeterminate state (filled track with the thumb parked at the midpoint of its travel). Takes visual precedence over `checked`. |
224
224
  | `readonly` | `boolean \| undefined` | `false` | | Renders the read-only affordance. Reserved for parity with the other glyphs; currently has no distinct visual. |
225
225
 
226
+ ## Passthrough parts and states
227
+
228
+ `pt:<part>="…"` restyles a part; `pt:<part>:<state>="…"` applies only while the state is on. A component-wide state is on for every part at once; a _per node_ state resolves on each node of a broadcast part (one row, one option, one day). Grammar and merge rules: `guides/passthrough.md`.
229
+
230
+ | Part | What it is |
231
+ | --- | --- |
232
+ | `root` | The drawn glyph — the track and its thumb. Its states are the conditions it paints as it resolves them (`warnings` is off while `errors` is on), not the raw props. |
233
+
234
+ States are listed in precedence order: when two are on at once and their entries conflict, the later one wins.
235
+
236
+ | State | When it is on |
237
+ | --- | --- |
238
+ | `checked` | Component-wide: the toggle is on. |
239
+ | `indeterminate` | Component-wide: the mixed state (the `indeterminate` prop) — neither on nor off. |
240
+ | `readonly` | Component-wide: the toggle is `readonly` — focusable, cannot change. |
241
+ | `disabled` | Component-wide: the toggle is `disabled`. |
242
+ | `warnings` | Component-wide: the toggle shows warnings and no errors. |
243
+ | `errors` | Component-wide: the toggle shows errors — the glyph and the message line turn red. |
244
+ | `focused` | Component-wide: the native input has focus — any focus, mouse included, like the `focused` slot prop. |
245
+ | `focus-visible` | Component-wide: that focus is keyboard-visible — where a focus ring belongs. |
246
+
226
247
  ## Events
227
248
 
228
249
  - None.
@@ -240,7 +261,7 @@ Set these on the element, or on a class you put on it, to retune this component
240
261
  | `--accent` | `var(--bb-primary)` | Track fill and border once checked or indeterminate; --errors, --warnings and --disabled re-point it. |
241
262
  | `--bg` | `var(--bb-track)` | track fill while off |
242
263
  | `--ring-color` | `color-mix( in oklab, currentColor var(--bb-ring-opacity), transparent )` | focus ring; follows the accent colour (a consumer text colour too) — --errors / --warnings set their own |
243
- | `--radius` | `999px` | track corners; the thumb rounds to 80% of it |
264
+ | `--r` | `999px` | track corners; the thumb rounds to 80% of it |
244
265
  | `--bw` | `var(--bb-border-w-sm)` | Geometry — change --h / --w / --thumb freely: everything else is derived, so the thumb stays vertically centred and travels flush-to-flush at any size. --bw is the track border; the box is border-box, so the border eats into the inner track… |
245
266
  | `--h` | `18px` | track height, border included (border-box) |
246
267
  | `--w` | `32px` | track width, border included |
@@ -10,7 +10,7 @@
10
10
 
11
11
  ## Reachable through `BbBreadcrumbs`
12
12
 
13
- `BbBreadcrumbs` mounts other components (all of them: _Component tree_, near the end). These are the parts of its API that land inside them. Use them — never `:deep()` on an inner class, never an import of an internal component.
13
+ `BbBreadcrumbs` mounts other components (all of them: _Component tree_, near the end). These are the parts of its API that land inside them. Prefer these over `:deep()` on an inner class (allowed, unsupported: it can break on upgrade) — and never an import of an internal component.
14
14
 
15
15
  | pt part | Lands on | In |
16
16
  | --- | --- | --- |
@@ -668,7 +668,7 @@ The full grammar, the merge rules and the global map are in the
668
668
 
669
669
  | Prop | Type | Default | Required | Description |
670
670
  | --- | --- | --- | --- | --- |
671
- | `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: `icon`, `item`, `root`, `text`. States: `active`, `disabled`. `pt` is the object form with the same keys minus the prefix (`{ icon: '…', 'icon:loading': '…' }`). See `guides/passthrough.md`. |
671
+ | `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: `icon`, `item`, `root`, `text`. States: `active`, `disabled`. 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`. |
672
672
  | `disabled` | `boolean \| undefined` | `false` | | Disables the component |
673
673
  | `dividerWidth` | `number \| undefined` | `16` | | Width of the divider in pixels. |
674
674
  | `ellipsisWidth` | `number \| undefined` | | | Explicit width used by the estimator for the ellipsis activator. |
@@ -677,6 +677,24 @@ The full grammar, the merge rules and the global map are in the
677
677
  | `items` | `BbBreadcrumbsItem[]` | | yes | Array of items that describe how the breadcrumbs should behave. Compatible with navigating through `a` or `router-link`. |
678
678
  | `offsetWidth` | `number \| undefined` | `0` | | Extra one-off width in pixels added to the total estimate (e.g. prepend/append/item slot content). |
679
679
 
680
+ ## Passthrough parts and states
681
+
682
+ `pt:<part>="…"` restyles a part; `pt:<part>:<state>="…"` applies only while the state is on. A component-wide state is on for every part at once; a _per node_ state resolves on each node of a broadcast part (one row, one option, one day). Grammar and merge rules: `guides/passthrough.md`.
683
+
684
+ | Part | What it is |
685
+ | --- | --- |
686
+ | `root` | The `<nav>`. |
687
+ | `item` | One crumb — a broadcast resolved per crumb; the overflow ellipsis crumb counts. The dividers are chrome, not a part. |
688
+ | `icon` | A crumb's `prepend:icon` / `append:icon` glyphs — a broadcast. |
689
+ | `text` | A crumb's label inside its link, without the glyphs beside it — a broadcast resolved per crumb, like `item`. |
690
+
691
+ States are listed in precedence order: when two are on at once and their entries conflict, the later one wins.
692
+
693
+ | State | When it is on |
694
+ | --- | --- |
695
+ | `disabled` | Per node: a crumb that is disabled on its own; component-wide while the whole component is `disabled`. |
696
+ | `active` | Per node, on each crumb's `item` / `text`: the current page — the last crumb. |
697
+
680
698
  ## Events
681
699
 
682
700
  - None.
@@ -701,13 +719,13 @@ The full grammar, the merge rules and the global map are in the
701
719
 
702
720
  - `BbBreadcrumbs` _(this component)_ — its own template binds: `item` → `li.bb-breadcrumbs__item`, `icon` → `BbIcon`, `text` → `span.bb-breadcrumbs__text`
703
721
  - `BbBaseButton` _(public — [contract](./BbBaseButton.md))_ — its own pt parts (`BbBaseButton`): `root` → `RouterComponent`, `root` → `a`, `root` → `component`; also mounts `RouterComponent`
704
- - `BbDropdown` _(public — [contract](./BbDropdown.md))_ — its own pt parts (`BbDropdown`): `panel` → `CommonPopover`, `root` → `CommonPopover`, `header` → `div.bb-dropdown__header`, `footer` → `div.bb-dropdown__footer`; documented CSS variables: `--menu-inset`; also mounts `CommonPopover`, `DropdownPipelineResolver`
722
+ - `BbDropdown` _(public — [contract](./BbDropdown.md))_ — its own pt parts (`BbDropdown`): `panel` → `CommonPopover`, `root` → `CommonPopover`, `header` → `div.bb-dropdown__header`, `list` → `span.bb-dropdown__items-container`, `footer` → `div.bb-dropdown__footer`; documented CSS variables: `--menu-inset`; also mounts `CommonPopover`, `DropdownPipelineResolver`
705
723
  - `BbDropdownList` _(internal — not importable, reach it through `BbDropdown`)_ — also mounts `BbBaseButton`, `BbIcon`, `CommonPopover`, `BbDropdownList`
706
- - `BbBadge` _(public — [contract](./BbBadge.md))_ — its own pt parts (`BbBadge`): `spinner` → `BbSpinner`, `icon` → `BbIcon`, `clear` → `button.bb-badge__clear-button`; documented CSS variables: `--bg`, `--fg`, `--border-width`, `--ring`, `--min-size-md`, `--min-size`, `--elev`, `--radius`, `--font-size`, `--icon-size`, `--gap`, `--padding-inline`, `--clear-size`, `--pad-left`; also mounts `BbIcon`, `BbSpinner`, `BadgeBodyContent`
724
+ - `BbBadge` _(public — [contract](./BbBadge.md))_ — its own pt parts (`BbBadge`): `spinner` → `BbSpinner`, `icon` → `BbIcon`, `clear` → `button.bb-badge__clear-button`; documented CSS variables: `--bg`, `--fg`, `--border-width`, `--ring`, `--min-size-md`, `--min-size`, `--elev`, `--r`, `--font-size`, `--icon-size`, `--gap`, `--padding-inline`, `--clear-size`, `--pad-left`; also mounts `BbIcon`, `BbSpinner`, `BadgeBodyContent`
707
725
  - `AdaptiveDropdown` _(internal — not importable, reach it through `BbDropdown`)_ — hands `BbOffCanvas` the pt map `{ header: 'header', footer: 'footer', sheet: 'root' }` (ours → theirs); also mounts `BbSmoothHeight`, `BbDropdownList`
708
- - `BbOffCanvas` _(public — [contract](./BbOffCanvas.md))_ — its own pt parts (`BbOffCanvas`): `header` → `div.bb-offcanvas__header`, `title` → `span.bb-offcanvas__title`, `description` → `p.bb-offcanvas__description`, `close` → `CloseButton`, `content` → `div.bb-offcanvas__body`, `footer` → `div.bb-offcanvas__footer`; documented CSS variables: `--stack-x`, `--stack-fill`, `--stack-transition-duration`, `--px`, `--close-size`
726
+ - `BbOffCanvas` _(public — [contract](./BbOffCanvas.md))_ — its own pt parts (`BbOffCanvas`): `header` → `div.bb-offcanvas__header`, `title` → `span.bb-offcanvas__title`, `description` → `p.bb-offcanvas__description`, `close` → `CloseButton`, `content` → `div.bb-offcanvas__body`, `footer` → `div.bb-offcanvas__footer`; documented CSS variables: `--stack-x`, `--stack-fill`, `--stack-transition-duration`, `--px`, `--handle-w`, `--handle-h`, `--handle-bg`, `--close-size`
709
727
  - `CloseButton` _(internal — not importable, reach it through `BbOffCanvas`)_ — documented CSS variables: `--size`, `--p`
710
- - `BbButton` _(public — [contract](./BbButton.md))_ — its own pt parts (`BbButton`): `root` → `BbBaseButton`, `spinner` → `BbSpinner`, `icon` → `BbIcon`, `text` → `span.bb-button__content`; documented CSS variables: `--h-xs`, `--h`, `--icon-size`, `--px`, `--fs`, `--r`, `--gap`, `--bg`, `--bg-hover`, `--bg-pressed`, `--fg`, `--border-color`, `--ring`, `--bw`, `--elev-tier`, `--elev`; also mounts `BbIcon`, `BbBaseButton`, `BbSpinner`
728
+ - `BbButton` _(public — [contract](./BbButton.md))_ — its own pt parts (`BbButton`): `root` → `BbBaseButton`, `spinner` → `BbSpinner`, `icon` → `BbIcon`, `text` → `span.bb-button__content`; documented CSS variables: `--h-xs`, `--h`, `--icon-size`, `--px`, `--fs`, `--r`, `--gap`, `--bg`, `--bg-hover`, `--bg-pressed`, `--fg`, `--border-color`, `--ring`, `--bw`, `--fg-hover`, `--border-hover`, `--fg-pressed`, `--border-pressed`, `--bg-disabled`, `--fg-disabled`, `--border-disabled`, `--opacity-disabled`, `--elev-tier`, `--elev`; also mounts `BbIcon`, `BbBaseButton`, `BbSpinner`
711
729
  - Also mounts `BbIcon`
712
730
 
713
731
  ## See Also