bitboss-ui 3.0.0-beta.46 → 3.0.0-beta.48

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 (202) hide show
  1. package/README.md +2 -2
  2. package/bin/bitboss-ui-mcp.mjs +5 -1
  3. package/bin/bitboss-ui.mjs +66 -7
  4. package/dist/ai/BbAccordion.md +25 -3
  5. package/dist/ai/BbButton.md +12 -3
  6. package/dist/ai/BbCalendar.md +13 -2
  7. package/dist/ai/BbCollapsible.md +1 -1
  8. package/dist/ai/BbColorPalette.md +2 -2
  9. package/dist/ai/BbConfirm.md +8 -0
  10. package/dist/ai/BbConfirmPortal.md +1 -1
  11. package/dist/ai/BbDatePicker.md +2 -2
  12. package/dist/ai/BbDatePickerInput.md +5 -3
  13. package/dist/ai/BbDialog.md +1 -1
  14. package/dist/ai/BbDropdown.md +14 -2
  15. package/dist/ai/BbDropdownButton.md +1 -1
  16. package/dist/ai/BbHoverCard.md +525 -0
  17. package/dist/ai/BbHoverCardPortal.md +29 -0
  18. package/dist/ai/BbOffCanvas.md +1 -1
  19. package/dist/ai/BbPopover.md +128 -4
  20. package/dist/ai/BbPopoverPortal.md +29 -0
  21. package/dist/ai/BbSelectPopover.md +1 -1
  22. package/dist/ai/BbTable.md +16 -8
  23. package/dist/ai/BbTabs.md +40 -2
  24. package/dist/ai/BbTabsRoot.md +2 -1
  25. package/dist/ai/BbTooltip.md +27 -9
  26. package/dist/ai/CommonPopover.md +1 -1
  27. package/dist/ai/changelog.json +86 -5
  28. package/dist/ai/components.json +43 -26
  29. package/dist/ai/guides/ai-router.md +23 -22
  30. package/dist/ai/guides/component-picker.md +17 -11
  31. package/dist/ai/guides/installation-and-plugin-setup.md +11 -6
  32. package/dist/ai/guides/migration/components/bb-date-picker-input.md +5 -2
  33. package/dist/ai/guides/migration/v2-to-v3.md +68 -14
  34. package/dist/ai/guides/migration/v3-beta-css-classes.md +29 -27
  35. package/dist/ai/guides/passthrough.md +7 -8
  36. package/dist/ai/guides/typescript-generic-components.md +87 -0
  37. package/dist/ai/index.md +5 -1
  38. package/dist/ai/manifest/components/BbAccordion.json +2 -1
  39. package/dist/ai/manifest/components/BbAccordion.tree.json +1 -0
  40. package/dist/ai/manifest/components/BbBreadcrumbs.tree.json +1 -1
  41. package/dist/ai/manifest/components/BbButton.json +1 -0
  42. package/dist/ai/manifest/components/BbButton.tree.json +1 -1
  43. package/dist/ai/manifest/components/BbCalendar.json +1 -1
  44. package/dist/ai/manifest/components/BbCollapsible.json +1 -1
  45. package/dist/ai/manifest/components/BbColorPalette.json +1 -1
  46. package/dist/ai/manifest/components/BbConfirmPortal.json +5 -2
  47. package/dist/ai/manifest/components/BbDatePicker.json +1 -1
  48. package/dist/ai/manifest/components/BbDatePickerInput.json +1 -1
  49. package/dist/ai/manifest/components/BbDropdown.json +1 -1
  50. package/dist/ai/manifest/components/BbDropdown.tree.json +1 -1
  51. package/dist/ai/manifest/components/BbDropdownButton.json +1 -1
  52. package/dist/ai/manifest/components/BbDropdownButton.tree.json +1 -1
  53. package/dist/ai/manifest/components/BbHoverCard.json +63 -0
  54. package/dist/ai/manifest/components/BbHoverCard.tree.json +31 -0
  55. package/dist/ai/manifest/components/BbHoverCardPortal.json +21 -0
  56. package/dist/ai/manifest/components/BbPopover.json +2 -2
  57. package/dist/ai/manifest/components/BbPopoverPortal.json +21 -0
  58. package/dist/ai/manifest/components/BbSelect.tree.json +2 -2
  59. package/dist/ai/manifest/components/BbSelectPopover.tree.json +1 -1
  60. package/dist/ai/manifest/components/BbTable.json +1 -1
  61. package/dist/ai/manifest/components/BbTabs.json +2 -1
  62. package/dist/ai/manifest/components/BbTabsRoot.json +2 -1
  63. package/dist/ai/manifest/components/BbTag.tree.json +1 -1
  64. package/dist/ai/manifest/components/BbTooltip.json +1 -1
  65. package/dist/ai/manifest/components/ChipsBox.tree.json +1 -1
  66. package/dist/ai/manifest/components/CommonPopover.json +1 -1
  67. package/dist/ai/manifest/index.json +6 -3
  68. package/dist/ai/manifest/meta.json +14 -0
  69. package/dist/ai/manifest/types.advanced.json +5 -0
  70. package/dist/ai/manifest/types.api.json +6 -3
  71. package/dist/ai/manifest/types.wrapper.json +4 -0
  72. package/dist/ai/source/BbAccordion.md +44 -12
  73. package/dist/ai/source/BbBadge.md +12 -8
  74. package/dist/ai/source/BbBadgeButton.md +12 -8
  75. package/dist/ai/source/BbButton.md +13 -5
  76. package/dist/ai/source/BbCalendar.md +7 -4
  77. package/dist/ai/source/BbCollapsible.md +2 -1
  78. package/dist/ai/source/BbColorPalette.md +2 -1
  79. package/dist/ai/source/BbConfirm.md +17 -0
  80. package/dist/ai/source/BbConfirmPortal.md +19 -5
  81. package/dist/ai/source/BbDatePicker.md +4 -3
  82. package/dist/ai/source/BbDatePickerInput.md +6 -2
  83. package/dist/ai/source/BbDialog.md +5 -2
  84. package/dist/ai/source/BbDropdown.md +45 -17
  85. package/dist/ai/source/BbDropdownGroup.md +2 -1
  86. package/dist/ai/source/BbDropzone.md +3 -2
  87. package/dist/ai/source/BbHoverCard.md +975 -0
  88. package/dist/ai/source/BbHoverCardPortal.md +314 -0
  89. package/dist/ai/source/BbOffCanvas.md +5 -2
  90. package/dist/ai/source/BbPopover.md +62 -19
  91. package/dist/ai/source/BbPopoverPortal.md +376 -0
  92. package/dist/ai/source/BbRating.md +1 -1
  93. package/dist/ai/source/BbSelect.md +4 -2
  94. package/dist/ai/source/BbSelectPopover.md +10 -2
  95. package/dist/ai/source/BbSlider.md +4 -3
  96. package/dist/ai/source/BbTable.md +91 -12
  97. package/dist/ai/source/BbTabs.md +25 -1
  98. package/dist/ai/source/BbTabsList.md +19 -1
  99. package/dist/ai/source/BbTabsPanels.md +19 -1
  100. package/dist/ai/source/BbTabsRoot.md +25 -1
  101. package/dist/ai/source/BbTimePickerInput.md +2 -1
  102. package/dist/ai/source/BbTooltip.md +71 -7
  103. package/dist/ai/source/CommonPopover.md +18 -3
  104. package/dist/components/BbAccordion/BbAccordion.vue_vue_type_script_setup_true_lang.js +33 -29
  105. package/dist/components/BbAccordion/types.d.ts +8 -0
  106. package/dist/components/BbButton/BbButton.vue_vue_type_script_setup_true_lang.js +8 -3
  107. package/dist/components/BbButton/types.d.ts +8 -3
  108. package/dist/components/BbButton/types.js +5 -1
  109. package/dist/components/BbCalendar/BbCalendar.vue.d.ts +0 -1
  110. package/dist/components/BbCalendar/BbCalendar.vue_vue_type_script_setup_true_lang.js +182 -181
  111. package/dist/components/BbCalendar/types.d.ts +4 -2
  112. package/dist/components/BbCalendar/useCalendarGrid.d.ts +5 -2
  113. package/dist/components/BbCalendar/useCalendarGrid.js +119 -119
  114. package/dist/components/BbCalendar/useDayGrid.d.ts +5 -2
  115. package/dist/components/BbCalendar/useDayGrid.js +89 -89
  116. package/dist/components/BbCalendar/useDayjsLocale.d.ts +10 -0
  117. package/dist/components/BbCalendar/useDayjsLocale.js +7 -7
  118. package/dist/components/BbCollapsible/types.d.ts +2 -1
  119. package/dist/components/BbColorPalette/types.d.ts +2 -1
  120. package/dist/components/BbConfirm/BbConfirmPortal.vue.d.ts +2 -5
  121. package/dist/components/BbConfirm/types.d.ts +15 -0
  122. package/dist/components/BbDatePicker/BbDatePicker.vue.d.ts +0 -1
  123. package/dist/components/BbDatePicker/BbDatePicker.vue_vue_type_script_setup_true_lang.js +1 -1
  124. package/dist/components/BbDatePicker/types.d.ts +4 -2
  125. package/dist/components/BbDatePickerInput/BbDatePickerInput.vue_vue_type_script_setup_true_lang.js +2 -1
  126. package/dist/components/BbDatePickerInput/types.d.ts +4 -1
  127. package/dist/components/BbDialog/BbDialog.vue_vue_type_script_setup_true_lang.js +2 -1
  128. package/dist/components/BbDropdown/BbDropdown.vue_vue_type_script_setup_true_lang.js +347 -338
  129. package/dist/components/BbDropdown/types.d.ts +2 -1
  130. package/dist/components/BbDropzone/BbDropzone.vue_vue_type_script_setup_true_lang.js +1 -1
  131. package/dist/components/BbHoverCard/BbHoverCard.vue.d.ts +43 -0
  132. package/dist/components/BbHoverCard/BbHoverCard.vue.js +6 -0
  133. package/dist/components/BbHoverCard/BbHoverCard.vue_vue_type_script_setup_true_lang.js +300 -0
  134. package/dist/components/BbHoverCard/BbHoverCardPortal.vue.d.ts +23 -0
  135. package/dist/components/BbHoverCard/BbHoverCardPortal.vue.js +5 -0
  136. package/dist/components/BbHoverCard/BbHoverCardPortal.vue_vue_type_script_setup_true_lang.js +13 -0
  137. package/dist/components/BbHoverCard/hoverCardFocus.d.ts +29 -0
  138. package/dist/components/BbHoverCard/hoverCardFocus.js +29 -0
  139. package/dist/components/BbHoverCard/types.d.ts +188 -0
  140. package/dist/components/BbHoverCard/types.js +13 -0
  141. package/dist/components/BbOffCanvas/BbOffCanvas.vue_vue_type_script_setup_true_lang.js +2 -1
  142. package/dist/components/BbPopover/BbPopover.vue_vue_type_script_setup_true_lang.js +175 -166
  143. package/dist/components/BbPopover/BbPopoverPortal.vue.d.ts +23 -0
  144. package/dist/components/BbPopover/BbPopoverPortal.vue.js +5 -0
  145. package/dist/components/BbPopover/BbPopoverPortal.vue_vue_type_script_setup_true_lang.js +13 -0
  146. package/dist/components/BbPopover/types.d.ts +15 -1
  147. package/dist/components/BbRating/BbRating.vue_vue_type_script_setup_true_lang.js +1 -1
  148. package/dist/components/BbSelect/BbSelect.vue_vue_type_script_setup_true_lang.js +1 -1
  149. package/dist/components/BbSelectPopover/BbSelectPopover.vue_vue_type_script_setup_true_lang.js +4 -1
  150. package/dist/components/BbSlider/BbSlider.vue_vue_type_script_setup_true_lang.js +2 -2
  151. package/dist/components/BbTable/BbTable.vue_vue_type_script_setup_true_lang.js +1003 -974
  152. package/dist/components/BbTable/BbTableDataRow.d.ts +2 -0
  153. package/dist/components/BbTable/BbTableDataRow.js +1 -1
  154. package/dist/components/BbTable/BbTableSelectToggle.d.ts +12 -4
  155. package/dist/components/BbTable/BbTableSelectToggle.js +19 -10
  156. package/dist/components/BbTable/types.d.ts +1 -1
  157. package/dist/components/BbTabs/BbTabs.vue_vue_type_script_setup_true_lang.js +4 -0
  158. package/dist/components/BbTabs/BbTabsRoot.vue_vue_type_script_setup_true_lang.js +4 -0
  159. package/dist/components/BbTabs/types.d.ts +19 -1
  160. package/dist/components/BbTimePickerInput/BbTimePickerInput.vue_vue_type_script_setup_true_lang.js +2 -1
  161. package/dist/components/BbTooltip/BbTooltip.vue_vue_type_script_setup_true_lang.js +105 -92
  162. package/dist/components/BbTooltip/types.d.ts +3 -1
  163. package/dist/components/CommonPopover/CommonPopover.vue_vue_type_script_setup_true_lang.js +18 -16
  164. package/dist/components/CommonPopover/types.d.ts +2 -1
  165. package/dist/composables/useBbTabsContext.js +47 -36
  166. package/dist/composables/useOverlayYield.d.ts +23 -0
  167. package/dist/composables/useOverlayYield.js +20 -0
  168. package/dist/directives/bbDropdown.js +22 -12
  169. package/dist/directives/bbHoverCard.d.ts +59 -0
  170. package/dist/directives/bbHoverCard.js +33 -0
  171. package/dist/directives/bbPopover.d.ts +60 -0
  172. package/dist/directives/bbPopover.js +40 -0
  173. package/dist/directives/bbTooltip.d.ts +7 -5
  174. package/dist/directives/createPopoverDirective.d.ts +24 -0
  175. package/dist/directives/createPopoverDirective.js +74 -61
  176. package/dist/directives/directivePortal.d.ts +75 -0
  177. package/dist/directives/directivePortal.js +37 -0
  178. package/dist/directives/renderingInstance.d.ts +2 -0
  179. package/dist/directives/renderingInstance.js +25 -0
  180. package/dist/index.d.ts +11 -2
  181. package/dist/index.js +61 -56
  182. package/dist/llms-full.txt +1155 -139
  183. package/dist/llms-medium.txt +55 -40
  184. package/dist/llms.txt +2 -1
  185. package/dist/nuxt-auto-imports.js +1 -1
  186. package/dist/plugin.js +18 -16
  187. package/dist/runtime/nuxt-plugin.js +19 -17
  188. package/dist/styles.css +2 -2
  189. package/dist/types/passthrough.d.ts +1 -1
  190. package/dist/types/ptComponentMap.d.ts +2 -1
  191. package/dist/utils/overlayEscapeStack.d.ts +30 -2
  192. package/dist/utils/overlayEscapeStack.js +19 -10
  193. package/dist/utils/versionCheck.js +1 -1
  194. package/llms.txt +2 -1
  195. package/package.json +1 -1
  196. package/scripts/lib/eslint-disable.mjs +7 -0
  197. package/scripts/lib/eslint-plugin.d.ts +6 -0
  198. package/scripts/lib/eslint-plugin.mjs +192 -6
  199. package/scripts/lib/portal-names.mjs +458 -0
  200. package/scripts/lib/toolchain-check.mjs +12 -19
  201. package/scripts/lib/unimported-components.mjs +263 -0
  202. package/scripts/lib/validate-bb-markup.mjs +90 -1
package/README.md CHANGED
@@ -57,7 +57,7 @@ Full detail: `dist/ai/guides/installation-and-plugin-setup.md`.
57
57
 
58
58
  ### Directives
59
59
 
60
- `vBbTooltip`, `vBbDropdown`, `vBbColor`, `vBbDate`, `vBbTime` — plus a
60
+ `vBbTooltip`, `vBbDropdown`, `vBbColor`, `vBbDate`, `vBbTime`, `vBbHoverCard`, `vBbPopover` — plus a
61
61
  `Bb*DirectivePlugin` for each, for app-level registration. Prefer the directive
62
62
  over the component for simple no-slot cases.
63
63
 
@@ -79,7 +79,7 @@ Product-ready components with labels, hints, errors, and consistent styling:
79
79
  - **Forms & actions:** `BbTextInput`, `BbTextarea`, `BbNumberInput`, `BbSelect`, `BbSelectPopover`, `BbCheckbox`, `BbCheckboxGroup`, `BbRadio`, `BbRadioGroup`, `BbSwitch`, `BbSwitchGroup`, `BbSlider`, `BbRating`, `BbColorInput`, `BbColorPalette`, `BbCalendar`, `BbDatePicker`, `BbDatePickerInput`, `BbTimePicker`, `BbTimePickerInput`, `BbButton`, `BbBadge`, `BbBadgeButton`, `BbIndicator`, `BbTag`, `BbDropdown`, `BbDropdownGroup`, `BbDropdownButton`, `BbAsterisk`
80
80
  - **Feedback:** `BbAlert`, `BbProgress`, `BbSpinner`, `BbToast`, `BbToastPortal`, `BbTooltip`
81
81
  - **Layout & navigation:** `BbAccordion`, `BbCollapsible`, `BbTabs` (+ `BbTabsRoot`, `BbTabsList`, `BbTabsPanels`), `BbBreadcrumbs`, `BbPagination`, `BbSmoothHeight`
82
- - **Overlays & panels:** `BbDialog`, `BbConfirm`, `BbConfirmPortal`, `BbOffCanvas`, `BbPopover`
82
+ - **Overlays & panels:** `BbDialog`, `BbConfirm`, `BbConfirmPortal`, `BbOffCanvas`, `BbPopover`, `BbHoverCard`
83
83
  - **Data:** `BbTable`, `BbTree`
84
84
  - **Media & files:** `BbAvatar`, `BbDropzone`, `BbIcon`
85
85
  - **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).
@@ -1188,7 +1188,11 @@ function getComponent({
1188
1188
  // A directive (`v-bb-tooltip`, `vBbTooltip`) — review D3-13.
1189
1189
  const directiveName = String(name ?? '')
1190
1190
  .trim()
1191
- .replace(/^vBb([A-Z]\w*)$/, (_, word) => `v-bb-${word.toLowerCase()}`)
1191
+ .replace(
1192
+ /^vBb([A-Z]\w*)$/,
1193
+ // `vBbHoverCard` → `v-bb-hover-card`, the registered name.
1194
+ (_, word) => `v-bb-${word.replace(/(?<!^)([A-Z])/g, '-$1')}`
1195
+ )
1192
1196
  .toLowerCase();
1193
1197
  const directive = (manifest.directives ?? []).find(
1194
1198
  (d) => d.name === directiveName
@@ -77,6 +77,12 @@ import {
77
77
  } from '../scripts/lib/local-components.mjs';
78
78
  import { applyBitbossFixes } from '../scripts/lib/check-fix.mjs';
79
79
  import { stringControlsFor } from '../scripts/lib/text-null-value.mjs';
80
+ import { projectResolution } from '../scripts/lib/unimported-components.mjs';
81
+ import {
82
+ MAY_HAVE_PORTALS,
83
+ portalFindings,
84
+ projectPortalIndex,
85
+ } from '../scripts/lib/portal-names.mjs';
80
86
  import { cssClassFindings } from '../scripts/lib/css-class-check.mjs';
81
87
  import {
82
88
  cssLocalFindings,
@@ -1049,6 +1055,8 @@ async function checkCommand(
1049
1055
  ...validateOptions,
1050
1056
  // The app's null-value policy, from the project bitboss-ui.d.ts.
1051
1057
  stringControls: stringControlsFor(file),
1058
+ // Q61.19: what the project registers globally.
1059
+ unimported: { project: projectResolution(projectRoot) },
1052
1060
  });
1053
1061
  // Q46.9: a finding the author silenced for ESLint (`eslint-disable*`,
1054
1062
  // usually with a reason) is silenced here too, or `check` cannot gate
@@ -1080,9 +1088,47 @@ async function checkCommand(
1080
1088
  }
1081
1089
  }
1082
1090
 
1091
+ // Q63.8: portal names, judged against the whole project's declarations
1092
+ // and call sites (scripts too: `confirm({ portal })` lives there). A full
1093
+ // run reads every source file; explicit paths / `--changed`, only those.
1094
+ // Markdown fences are never read: a doc names portals it never declares.
1095
+ {
1096
+ const portalIndex = projectPortalIndex(projectRoot);
1097
+ const PORTAL_SOURCE = /\.(?:vue|[cm]?[jt]sx?)$/;
1098
+ const TEST_FILE = /\.(?:test|spec)(?:-d)?\.[cm]?[jt]sx?$/;
1099
+ const portalScope = (
1100
+ changed ? changed.all : globs.length ? files : projectSources
1101
+ ).filter(
1102
+ (path) =>
1103
+ PORTAL_SOURCE.test(path) &&
1104
+ !path.endsWith('.d.ts') &&
1105
+ !TEST_FILE.test(path)
1106
+ );
1107
+ for (const path of portalScope) {
1108
+ let content;
1109
+ try {
1110
+ content = readText(path);
1111
+ } catch {
1112
+ continue;
1113
+ }
1114
+ if (!MAY_HAVE_PORTALS.test(content)) continue;
1115
+ const isDisabled = disabledChecker(content);
1116
+ for (const finding of portalFindings(content, path, portalIndex)) {
1117
+ if (isDisabled(finding.line, ruleForFinding(finding))) {
1118
+ suppressed++;
1119
+ continue;
1120
+ }
1121
+ const entry = { file: relative(projectRoot, path), ...finding };
1122
+ if (finding.severity === 'warning') warnings.push(entry);
1123
+ else findings.push(entry);
1124
+ }
1125
+ }
1126
+ }
1127
+
1083
1128
  for (const [name, file] of projectLocal) warnLocal(name, file);
1084
- // Q60.6: a `vue-tsc` below 3 and a missing `checkUnknownComponents`, read
1085
- // from package.json and the tsconfig. One line each, never fatal.
1129
+ // Q60.6: a `vue-tsc` below 3, read from package.json. One line, never
1130
+ // fatal. (A missing `checkUnknownComponents` is no longer warned about:
1131
+ // `unimported-component` covers it, Q61.19.)
1086
1132
  warnings.push(...toolchainWarnings(projectRoot));
1087
1133
 
1088
1134
  // Q25: a hand import of `bitboss-ui/styles.css` while the runtime plugin
@@ -1393,12 +1439,26 @@ Commands:
1393
1439
  \`duplicate-field-identity\` (two validated fields in
1394
1440
  one \`BbForm\` on the same path: the same \`name\`,
1395
1441
  or the same label with no \`name\`),
1442
+ \`unimported-component\` (a \`.vue\` file uses a
1443
+ bitboss-ui tag it never imports and the project never
1444
+ registers globally: it renders as an empty element),
1396
1445
  \`reactive-v-model\` (a \`v-model\` on a \`<script
1397
1446
  setup>\` \`const x = reactive(…)\`: a production build
1398
1447
  rejects the write-back; hold it in a \`ref()\`),
1399
1448
  \`form-v-model\` (\`v-model\`, \`:model-value\` or an
1400
1449
  \`@update:model-value\` listener on a \`BbForm\`: it
1401
1450
  takes its object one way, \`:model="draft"\`),
1451
+ \`bare-portal-name\` (\`v-bb-popover="user-card"\` /
1452
+ \`v-bb-hover-card="user-card"\` without the inner
1453
+ quotes: an expression, not a portal name; write
1454
+ \`"'user-card'"\`),
1455
+ \`unknown-portal\` (\`v-bb-hover-card\` /
1456
+ \`v-bb-popover\` / \`confirm()\` names a portal no
1457
+ \`<…Portal name>\` in the project declares; did-you-mean
1458
+ in the message), \`portal-family-mismatch\` (a
1459
+ hover-card portal opened by \`v-bb-popover\`, or the
1460
+ other way round; literal names only, a \`:name\`
1461
+ binding or a non-literal call site is never judged),
1402
1462
  \`positional-provider\` (an \`items\` provider with
1403
1463
  positional arguments: it receives one object,
1404
1464
  \`({ query, reason, modelValue, signal })\`),
@@ -1459,12 +1519,11 @@ Commands:
1459
1519
  component uses the \`Bb\` prefix; rename it),
1460
1520
  \`single-reason\` (an \`items\` provider that tests
1461
1521
  \`reason\` against one cause other than \`'search'\`;
1462
- check \`reason !== 'search'\`), \`vue-tsc-major\`
1522
+ check \`reason !== 'search'\`), \`unused-portal\` (a
1523
+ \`<…Portal name>\` nothing opens: no call site and the
1524
+ name in no string of the project), \`vue-tsc-major\`
1463
1525
  (\`vue-tsc\` below 3 in package.json: the generic
1464
- components' props go unchecked),
1465
- \`check-unknown-components\` (no
1466
- \`vueCompilerOptions.checkUnknownComponents: true\` in
1467
- the tsconfig; \`ai-init\` writes it).
1526
+ components' props go unchecked).
1468
1527
  changelog [--since <version>] [--until <version>] [--json]
1469
1528
  Breaking changes between two releases — "what breaks if I
1470
1529
  bump". \`--since\` is the version you are ON, and is
@@ -39,7 +39,8 @@ Step down the ladder when the composed header doesn't fit:
39
39
  **`BbSmoothHeight`** (`./BbSmoothHeight.md`).
40
40
 
41
41
  The public surface is small on purpose: `v-model` (boolean), `eager`,
42
- `transition-duration`, `id`, two slots, and the `update:modelValue` event.
42
+ `transition-duration`, `id`, `heading-level`, two slots, and the
43
+ `update:modelValue` event.
43
44
  Everything else is composition.
44
45
 
45
46
  ### Composing an FAQ
@@ -489,6 +490,25 @@ references): the body region gets your id and the header gets `<id>_header`,
489
490
  already cross-wired via `aria-controls`/`aria-labelledby`. Omitted, a unique id
490
491
  is generated for you.
491
492
 
493
+ ### Headers in the page outline
494
+
495
+ Set `heading-level` when the accordion's headers are section titles a screen
496
+ reader user should find by jumping between headings: an FAQ, a settings page's
497
+ sections. The header button then sits inside `<h1>`–`<h6>` (the APG accordion
498
+ shape), named after your header text. Match the page outline: under an `<h2>`
499
+ the panels take `3`, never a level picked for its size, because the heading
500
+ looks the same at every level (its margins and font are reset). Leave it out
501
+ for accordions inside a form, a card or a side panel, where the headers are
502
+ controls, not titles.
503
+
504
+ ```vue
505
+ <h2>Billing questions</h2>
506
+ <BbAccordion v-model="open" :heading-level="3">
507
+ <template #header>Can I change plans?</template>
508
+ Yes, at any time.
509
+ </BbAccordion>
510
+ ```
511
+
492
512
  ### Restyling with passthrough
493
513
 
494
514
  `pt` reaches a named part with a class list — or, in the object form, a
@@ -606,7 +626,8 @@ A `pt` value written in `<script>` (a constant, a preset, a wrapper's
606
626
  - The header is a real `button` with `aria-expanded`/`aria-controls`; the body
607
627
  is a `role="region"` labelled by the header via `aria-labelledby`. You add
608
628
  nothing — and you must not wrap the header slot in another interactive
609
- element.
629
+ element. `heading-level` puts the button inside a heading (above); never wrap
630
+ the accordion in your own `<hN>` instead.
610
631
  - Keyboard comes free with the native button: Tab to the header, Enter/Space
611
632
  toggles. Closed content is `inert`, so it can never be tabbed into.
612
633
  - Provide a visible, meaningful header label; the chevron is decorative (mark
@@ -622,7 +643,8 @@ A `pt` value written in `<script>` (a constant, a preset, a wrapper's
622
643
  | Prop | Type | Default | Required | Description |
623
644
  | --- | --- | --- | --- | --- |
624
645
  | `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`. In `<script>` a `pt` value is typed `BbAccordionProps['pt']` (`PtValue` is not exported): § Typing `pt` in `<script>`. |
625
- | `eager` | `boolean \| undefined` | `false` | | Prevents rendering content before it's made visible. |
646
+ | `eager` | `boolean \| undefined` | `false` | | Renders the content at mount, while closed, instead of on the first open. Closed content is `inert` and `aria-hidden` either way. |
647
+ | `headingLevel` | `1 \| 2 \| 3 \| 4 \| 5 \| 6 \| undefined` | | | Wraps the header button in a heading of this level (`<h1>`–`<h6>`), the APG accordion shape, so the header joins the page's outline. Match the level to where the accordion sits (a section under an `<h2>` takes `3`). No visual change: the heading's margins and font are reset. Omitted, there is no heading. |
626
648
  | `id` | `string \| undefined` | | | The root's `id`; the header button's id (`<id>_header`) derives from it. Generated when omitted. |
627
649
  | `modelValue` | `boolean \| undefined` | `false` | | Used by v-model to trigger opening / closing the collapsible. An accordion with no `v-model` starts closed. |
628
650
  | `transitionDuration` | `number \| undefined` | `250` | | How long the transition has to last in milliseconds |
@@ -494,6 +494,11 @@ const activeView = ref<IssueView>('list');
494
494
  </script>
495
495
  ```
496
496
 
497
+ A toggle that is on carries `aria-pressed="true"` and the class
498
+ `bb-button--pressed`. Restyle that state with `pt:root:pressed` (or
499
+ `pt:icon:pressed`, `pt:text:pressed`), not with a selector of your own: it is
500
+ the state's contract.
501
+
497
502
  Listen to `update:modelValue` only if you need side effects; state itself is
498
503
  handled. For form-ish multi-selection prefer `BbCheckboxGroup` /
499
504
  `BbRadioGroup`; toggle buttons are for immediate, tool-bar-like state.
@@ -835,8 +840,11 @@ label span). Typography inherits from `root`, so reach for `text` only when a
835
840
  class must apply to the label ALONE — `truncate` on a long label that must not
836
841
  clip the icons beside it. That span also carries the margin the label slides by
837
842
  while the spinner is in, so a margin of your own fights the slide. States:
838
- `loading`, `disabled`. A name outside that list is a type error and an ESLint
839
- error.
843
+ `loading`, `disabled`, `pressed` (a `v-model` toggle that is on). A name
844
+ outside that list is a type error and an ESLint error. There is no `active`
845
+ state: a pointer press is Tailwind's `active:` variant (`pt:root="active:scale-95"`).
846
+ There is no `current` state either: a link to the current route is
847
+ `active-class` / `exact-active-class` (see Active state above).
840
848
 
841
849
  **pt: a part, a part while loading, the object form**
842
850
 
@@ -1090,7 +1098,7 @@ Anti-patterns:
1090
1098
 
1091
1099
  | Prop | Type | Default | Required | Description |
1092
1100
  | --- | --- | --- | --- | --- |
1093
- | `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`, `spinner`, `text`. States: `disabled`, `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`. In `<script>` a `pt` value is typed `BbButtonProps['pt']` (`PtValue` is not exported): § Typing `pt` in `<script>`. |
1101
+ | `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`, `spinner`, `text`. States: `disabled`, `loading`, `pressed`. 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 `BbButtonProps['pt']` (`PtValue` is not exported): § Typing `pt` in `<script>`. |
1094
1102
  | `activeClass` | `string \| undefined` | | | Class to apply when the link is active. |
1095
1103
  | `append:icon` | `string \| undefined` | | | Icon to be added on the right of the text. |
1096
1104
  | `ariaCurrentValue` | `"page" \| "step" \| "location" \| "date" \| "time" \| "true" \| "false" \| undefined` | `'page'` | | Value passed to the attribute `aria-current` when the link is exact active. |
@@ -1160,6 +1168,7 @@ States are listed in precedence order: when two are on at once and their entries
1160
1168
 
1161
1169
  | State | When it is on |
1162
1170
  | --- | --- |
1171
+ | `pressed` | Component-wide: a toggle button (`v-model`) is on — `aria-pressed="true"`, `--pressed` on the root. |
1163
1172
  | `disabled` | Component-wide: the button is `disabled`. |
1164
1173
  | `loading` | Component-wide: `loading` is on — the spinner shows and the button ignores the pointer. |
1165
1174
 
@@ -493,11 +493,22 @@ const isOpen = (date: string) => !closed.has(date);
493
493
  </style>
494
494
  ```
495
495
 
496
+ ### The first day of the week
497
+
498
+ The grid's week starts on the active locale's day, from the dayjs pack the
499
+ plugin bundled: Monday for `it`, `de`, `fr`, `es` or `en-gb`, Sunday for bare
500
+ `en` (US English) and `pt` (Brazil), and Sunday for a locale with no pack. The
501
+ weekday headers follow, and so does a locale switch at runtime. Pass
502
+ `first-day-of-week` (`0` = Sunday … `6` = Saturday) when the app's week is not
503
+ its language's — an `en` app for a European audience takes
504
+ `:first-day-of-week="1"`. `BbDatePicker` and `BbDatePickerInput` take the same
505
+ prop and the same default.
506
+
496
507
  ### Keyboard and accessibility
497
508
 
498
509
  The calendar is an ordinary control in the tab order: **one tab stop** lands
499
510
  on the day under the cursor (the value, or today), arrows move by day and
500
- week, Home / End jump to the week's ends, PageUp / PageDown page by month
511
+ week, Home / End jump to the ends of the grid's row, PageUp / PageDown page by month
501
512
  (with Shift, by year), typing a day number jumps to it, Enter or Space picks.
502
513
  The grid is a `role="grid"` of `role="row"` / `gridcell` nodes; a picked day
503
514
  carries `aria-selected` and says "selected" in its name, a pending range
@@ -580,7 +591,7 @@ the page is `BbDatePicker`.
580
591
  | `activeSegment` | `'start'` \| `'end'` | | | Which end the time rail edits in range + `type="datetime"` (`v-model:active-segment`). Standalone use manages this internally; an embedding host (the date input) drives it from its focused field. Ignored outside range + datetime. |
581
592
  | `ampm` | `boolean \| undefined` | `false` | | 12-hour display with an AM/PM column (requires `type="datetime"`); emits stay 24h. |
582
593
  | `disabled` | `boolean \| undefined` | `false` | | Disables every cell, the navigation and the time rail. |
583
- | `firstDayOfWeek` | `0 \| 1 \| 2 \| 3 \| 4 \| 5 \| 6 \| undefined` | `1` | | First day of the week (0 = Sunday … 6 = Saturday). |
594
+ | `firstDayOfWeek` | `0 \| 1 \| 2 \| 3 \| 4 \| 5 \| 6 \| undefined` | `the locale's week start` | | First day of the week (0 = Sunday … 6 = Saturday). Omitted, the active locale's week start: Monday for `it`, `de`, `fr`, `en-gb`…, Sunday for bare `en` (US) and `pt` (Brazil). |
584
595
  | `floating` | `boolean \| undefined` | `false` | | Emit plain calendar strings instead of zoned ISO instants. Implied (and forced) by `type="month"` and `type="year"`. |
585
596
  | `max` | `string \| undefined` | | | Maximum selectable value, in this `type`'s shape. A finer bound is accepted and ceiled to the unit, with a warning. With `datetime`, on its own day the time rail disables the times after it. |
586
597
  | `min` | `string \| undefined` | | | Minimum selectable value, in this `type`'s shape — `YYYY-MM-DD` (`YYYY-MM-DDTHH:mm` with `datetime`, `YYYY-MM` with `month`, `YYYY` with `year`). A finer bound is accepted and floored to the unit, with a warning. With `datetime`, the grid disables the days before it and, on its own day, the time rail disables the times before it. |
@@ -525,7 +525,7 @@ A `pt` value written in `<script>` (a constant, a preset, a wrapper's
525
525
  | Prop | Type | Default | Required | Description |
526
526
  | --- | --- | --- | --- | --- |
527
527
  | `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: `content`, `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`. In `<script>` a `pt` value is typed `BbCollapsibleProps['pt']` (`PtValue` is not exported): § Typing `pt` in `<script>`. |
528
- | `eager` | `boolean \| undefined` | `false` | | Prevents rendering content before it's made visible. |
528
+ | `eager` | `boolean \| undefined` | `false` | | Renders the content at mount, while closed, instead of on the first open. Closed content is `inert` and `aria-hidden` either way. |
529
529
  | `modelValue` | `boolean \| undefined` | `false` | | Used by v-model to trigger opening / closing the collapsible. Optional, matching the runtime: `withDefaults` supplies `false`, so an omitted binding renders closed and Vue never warns. It was typed required while carrying that default, which made the manifest publish a row that was `required: true` AND `default: false` — a contradiction that read as a generator bug. |
530
530
  | `tag` | `'div'` \| `'span'` | `"span"` | | Element rendered as the root, and mirrored by the inner animating element — so the pair is span-in-span or div-in-div, both valid. Keep the default inside phrasing content (a `<p>`); use `'div'` when the body is block content (paragraphs, lists, forms), which a `span` may not contain. |
531
531
  | `transitionDuration` | `number \| undefined` | `250` | | How long the transition has to last in milliseconds |
@@ -760,7 +760,7 @@ A `pt` value written in `<script>` (a constant, a preset, a wrapper's
760
760
  | `boundary` | `ElementOrComponentRefOrSelector \| undefined` | | | Constrains the popover within a bounding element. Accepts an HTMLElement, a Vue component ref, or a CSS selector string. |
761
761
  | `disabled` | `boolean \| undefined` | `false` | | Disable all interaction (activator and palette). |
762
762
  | `disableFlip` | `boolean \| undefined` | `false` | | Disables the automatic flip to the opposite side when the popover would overflow (flipping is on by default). |
763
- | `eager` | `boolean \| undefined` | `false` | | Prevents rendering content before it's made visible. |
763
+ | `eager` | `boolean \| undefined` | `false` | | Renders the palette panel at mount instead of on the first open (the phone sheet's too). |
764
764
  | `eyeDropper` | `boolean \| undefined` | `false` | | Show an eyedropper button inside the palette to sample any color on screen. Uses the native EyeDropper API — hidden automatically on unsupported browsers. |
765
765
  | `label` | `string \| undefined` | | | Accessible label. The activator is named by it followed by the activator's own text, through `aria-labelledby`. Defaults to the locale string for "Open color picker" when omitted. |
766
766
  | `modelValue` | `string \| null` | | yes | v-model: the current color as a `#RRGGBB` hex string (or `#RRGGBBAA` when `alpha` is enabled), or `null` when empty. |
@@ -827,4 +827,4 @@ Set these on the element, or on a class you put on it, to retune this component
827
827
  ## See Also
828
828
 
829
829
  - [BbColorInput](./BbColorInput.md) — Captures color values through input controls.
830
- - [BbPopover](./BbPopover.md) — Anchors floating content to reference elements.
830
+ - [BbPopover](./BbPopover.md) — Anchors floating content to reference elements; also the v-bb-popover directive (its body is a BbPopoverPortal or a component).
@@ -654,6 +654,14 @@ const removeMember = async () => {
654
654
  When the portal owns its own action buttons, pass `actions: false` to hide the
655
655
  standard footer and resolve from inside the slot with its `yes` / `no` helpers.
656
656
 
657
+ **Names are checked.** `bitboss-ui check` and the ESLint rule
658
+ `bitboss-ui/portal-names` (in `recommended`) read every literal
659
+ `confirm({ portal: 'name' })` in your scripts against the
660
+ `<BbConfirmPortal name>`s in your templates: a name no file declares fails,
661
+ with a did-you-mean, and `bitboss-ui/unused-portal` warns on a portal nothing
662
+ opens. A `portal` held in a variable, or `confirm(options)`, is never judged.
663
+ The slot's `props` is `any` per key, so `props.member.name` needs no cast.
664
+
657
665
  ### Size, fullscreen and focus
658
666
 
659
667
  - `size` picks a maximum-width preset (`'xs'` … `'2xl'`, resolvable through
@@ -20,7 +20,7 @@
20
20
 
21
21
  ## Slots
22
22
 
23
- - `default` — scope: `{ yes: () => void; no: () => void; props: Record<string, unknown>; }`
23
+ - `default` — scope: `BbConfirmPortalSlotProps` `{ props: P; yes: () => void; no: () => void }`
24
24
 
25
25
  ## See Also
26
26
 
@@ -420,7 +420,7 @@ and digit typeahead; the time rail exposes labelled columns. Always pass a
420
420
  | `disabled` | `boolean \| undefined` | `false` | | Disables the activator and the calendar. |
421
421
  | `disableFlip` | `boolean \| undefined` | `false` | | Disable the automatic flip to the opposite side on overflow. |
422
422
  | `eager` | `boolean \| undefined` | `false` | | Render popover content before it is first shown. |
423
- | `firstDayOfWeek` | `0 \| 1 \| 2 \| 3 \| 4 \| 5 \| 6 \| undefined` | `1` | | First day of the week (0 = Sunday … 6 = Saturday). |
423
+ | `firstDayOfWeek` | `0 \| 1 \| 2 \| 3 \| 4 \| 5 \| 6 \| undefined` | `the locale's week start` | | First day of the week (0 = Sunday … 6 = Saturday). Omitted, the active locale's week start: Monday for `it`, `de`, `fr`, `en-gb`…, Sunday for bare `en` (US) and `pt` (Brazil). |
424
424
  | `floating` | `boolean \| undefined` | `false` | | Emit plain calendar strings instead of zoned ISO instants. Implied (and forced) by `type="month"` and `type="year"`. |
425
425
  | `label` | `string \| undefined` | | | Accessible label. The activator is named by it followed by the activator's own text ("Due date 12 Sep"), through `aria-labelledby`. |
426
426
  | `max` | `string \| undefined` | | | Maximum selectable value, in this `type`'s shape. A finer bound is accepted and ceiled to the unit, with a warning. |
@@ -542,4 +542,4 @@ Set these on the element, or on a class you put on it, to retune this component
542
542
  - [BbCalendar](./BbCalendar.md) — A calendar in place — the month grid (or month / year grid, or day grid plus time rail) with no popover and no field chrome; v-model of a day, range, set, month, year or datetime.
543
543
  - [BbDatePickerInput](./BbDatePickerInput.md) — Combines date selection with text input behavior.
544
544
  - [BbColorPalette](./BbColorPalette.md) — Opens an anchored popover color palette for color picking interactions.
545
- - [BbPopover](./BbPopover.md) — Anchors floating content to reference elements.
545
+ - [BbPopover](./BbPopover.md) — Anchors floating content to reference elements; also the v-bb-popover directive (its body is a BbPopoverPortal or a component).
@@ -213,8 +213,10 @@ to catch config mistakes early — always pass the `YYYY-MM-DD` shape.
213
213
 
214
214
  For non-contiguous rules (no weekends, no holidays, only in-stock slots), pass a
215
215
  `selectable` predicate: it receives each date string and returns `false` to
216
- disable that day. `firstDayOfWeek` shifts the calendar grid (`0` = Sunday …
217
- `6` = Saturday).
216
+ disable that day. The grid's week starts on the locale's day (Monday for
217
+ `it` or `de`, Sunday for bare `en` and `pt`); `firstDayOfWeek` pins it
218
+ (`0` = Sunday … `6` = Saturday) when the app's week differs from its
219
+ language's.
218
220
 
219
221
  The example below combines a rolling `min`/`max` window, a weekdays-only
220
222
  predicate, `floating` output, and the `day:append` slot to dot specific days.
@@ -872,7 +874,7 @@ label>')` matches nothing; query each segment by its own label instead. See
872
874
  | `disabled` | `boolean \| undefined` | `false` | | Disables the component. |
873
875
  | `disableWriting` | `boolean \| "mobile" \| "desktop" \| undefined` | `false` | | Disables typing into the input. Use `'mobile'` to disable typing only on mobile, `'desktop'` to disable typing only on desktop. |
874
876
  | `errors` | `string \| string[] \| undefined` | | | Can be a string or an array of string containing the messages to display. They render in an `aria-live="polite"` region (announced when they appear) and, while the list is non-empty, are referenced FIRST from the control's `aria-describedby`, so the reason the field is invalid is re-read whenever the control regains focus. |
875
- | `firstDayOfWeek` | `0 \| 1 \| 2 \| 3 \| 4 \| 5 \| 6 \| undefined` | | | Defines the first day of the week with `0` meaning Sunday and `6` meaning Saturday. |
877
+ | `firstDayOfWeek` | `0 \| 1 \| 2 \| 3 \| 4 \| 5 \| 6 \| undefined` | `the locale's week start` | | First day of the week (0 = Sunday … 6 = Saturday). Omitted, the active locale's week start: Monday for `it`, `de`, `fr`, `en-gb`…, Sunday for bare `en` (US) and `pt` (Brazil). |
876
878
  | `floating` | `boolean \| undefined` | `false` | | If true the date will have a format YYYY-MM-DD instead of the default ISO string. |
877
879
  | `formless` | `boolean \| undefined` | `false` | | Keep this control out of the enclosing `BbForm` entirely: not submitted, not dirty, not reset, not validated. For a control that is not form data (a filter, a "show advanced" switch). |
878
880
  | `hasErrors` | `boolean \| undefined` | `false` | | Define if the component should be in an error state. It usually attaches a CSS class for styling purposes. |
@@ -1214,4 +1214,4 @@ Set these on the element, or on a class you put on it, to retune this component
1214
1214
 
1215
1215
  - [BbOffCanvas](./BbOffCanvas.md) — Shows side-panel overlay content outside normal layout flow.
1216
1216
  - [BbConfirm](./BbConfirm.md) — Prompts users to confirm or cancel critical actions (includes co-located BbConfirmPortal export).
1217
- - [BbPopover](./BbPopover.md) — Anchors floating content to reference elements.
1217
+ - [BbPopover](./BbPopover.md) — Anchors floating content to reference elements; also the v-bb-popover directive (its body is a BbPopoverPortal or a component).
@@ -1661,6 +1661,18 @@ listeners attach to the referenced element. ARIA — `aria-haspopup`,
1661
1661
  too, the same as it would to the slot's `props`; don't hand-write your own
1662
1662
  `aria-*` attributes on it, or you get a double-set conflict.)
1663
1663
 
1664
+ **One per row is fine, even thousands.** Until someone presses, focuses or
1665
+ right-clicks the element, the directive builds no component: the element
1666
+ carries `aria-haspopup` / `aria-expanded` itself, and a handful of listeners on
1667
+ `document` serve every sleeping menu. A menu of plain action rows (no
1668
+ selectable group, no fetched `items`) goes back to sleep once it has closed, or
1669
+ when focus leaves an element whose menu never opened, so only the open menu
1670
+ is ever a component. Measured on 3,000 elements: mount and re-render cost
1671
+ about the same as the bare elements. Two things opt a binding out: `eager`, and
1672
+ an explicit `id` (it must stay resolvable by `useBbDropdownContext(id)`). Each
1673
+ then mounts a full `BbDropdown` (about 1 ms per element), so leave both off on
1674
+ long lists.
1675
+
1664
1676
  **Menu on any element, no wrapper**
1665
1677
 
1666
1678
  ```vue
@@ -2146,7 +2158,7 @@ A `pt` value written in `<script>` (a constant, a preset, a wrapper's
2146
2158
  | `boundary` | `string \| Record<string, any> \| HTMLElement \| null \| undefined` | | | Constrains the dropdown within a bounding element. Accepts an HTMLElement, a Vue component ref, or a CSS selector string. |
2147
2159
  | `compact` | `boolean \| undefined` | `false` | | Apply the compact density variant — the same ladder `BbSelect` uses, on both surfaces: flyout rows go 28px → 24px, sheet rows 44px → 36px. The label size does not change; density here is height, as it is for a select. A menu row is a touch target in a way a select option is not quite — a mis-tap fires the neighbouring COMMAND rather than picking the wrong value — so the compact sheet stops at 36px and never follows the flyout down to 24px. That is the same floor the select's sheet holds. |
2148
2160
  | `disabled` | `boolean \| undefined` | `false` | | Disables the component |
2149
- | `eager` | `boolean \| undefined` | `false` | | Prevents rendering content before it's made visible. |
2161
+ | `eager` | `boolean \| undefined` | `false` | | Renders the menu panel at mount instead of on the first open (the phone sheet's too). |
2150
2162
  | `emptyText` | `string \| undefined` | | | Default placeholder text shown when a pipeline group resolves to no items. A group's own `emptyText` overrides this; both fall back to the localized `common.emptyText` (`'No data to display'`). |
2151
2163
  | `enforceCoherence` | `boolean \| undefined` | `false` | | Default for pipeline groups: drop selections that are no longer present in a group's current items (e.g. after a `dependencies` re-fetch) from the selection and `v-model`. A group's own `enforceCoherence` overrides this. |
2152
2164
  | `failedText` | `string \| undefined` | | | Default placeholder text shown when a pipeline group's latest load FAILED (its `items` getter threw). A group's own `failedText` overrides this; both fall back to the localized `common.failedText` (`"Couldn't load items"`). |
@@ -2249,5 +2261,5 @@ Set these on the element, or on a class you put on it, to retune this component
2249
2261
 
2250
2262
  - [BbDropdownButton](./BbDropdownButton.md) — A button with primary action and all other actions collected in a dropdown.
2251
2263
  - [BbButton](./BbButton.md) — Button with loading state, tooltip, and icon support.
2252
- - [BbPopover](./BbPopover.md) — Anchors floating content to reference elements.
2264
+ - [BbPopover](./BbPopover.md) — Anchors floating content to reference elements; also the v-bb-popover directive (its body is a BbPopoverPortal or a component).
2253
2265
  - [BbBaseButton](./BbBaseButton.md) — Unstyled button/link primitive: element resolution (button/anchor/router link) and the full navigation engine, with no visual chrome. Use for any clickable or navigable surface that is not a variant-first BbButton — cards, list rows, custom links.
@@ -637,7 +637,7 @@ A `pt` value written in `<script>` (a constant, a preset, a wrapper's
637
637
  | `compact` | `boolean \| undefined` | `false` | | Apply the compact density variant — the same ladder `BbSelect` uses, on both surfaces: flyout rows go 28px → 24px, sheet rows 44px → 36px. The label size does not change; density here is height, as it is for a select. A menu row is a touch target in a way a select option is not quite — a mis-tap fires the neighbouring COMMAND rather than picking the wrong value — so the compact sheet stops at 36px and never follows the flyout down to 24px. That is the same floor the select's sheet holds. |
638
638
  | `disableAutoLoading` | `boolean \| undefined` | `false` | | Disables the automatic loading state that tracks async actions (enabled by default). Only affects the main action button: the split toggle half still mirrors the dropdown's internal async-action loading state. |
639
639
  | `disabled` | `boolean \| undefined` | `false` | | Disables the component |
640
- | `eager` | `boolean \| undefined` | `false` | | Prevents rendering content before it's made visible. |
640
+ | `eager` | `boolean \| undefined` | `false` | | Renders the menu panel at mount instead of on the first open (the phone sheet's too). |
641
641
  | `id` | `string \| undefined` | | | Names this dropdown: the activator's id (unless it already has one), the menu's `menu_<id>`, and the key `useBbDropdownContext(id)` and a companion `BbDropdownGroup` pair by. Generated when omitted. |
642
642
  | `items` | `BbDropdownItem[]` | `[]` | yes | Array used to render each dropdown button. They can act as `button`, as `a`, or as `router-link` as they are based on the functionality provided by `BbBaseButton`. Pass a flat array for a single group, nest arrays for divider-separated groups, or pass {@link InternalGroup} objects for titled / selectable sections. An item may carry its own `items` to open a submenu. The shapes can be mixed. |
643
643
  | `loading` | `boolean \| undefined` | `false` | | Triggers a loading indicator. |