bitboss-ui 3.0.0-beta.63 → 3.0.0-beta.64
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +25 -20
- package/bin/bitboss-ui.mjs +73 -7
- package/dist/ai/BbAlert.md +10 -1
- package/dist/ai/BbBadge.md +35 -3
- package/dist/ai/BbBadgeButton.md +4 -2
- package/dist/ai/BbBaseButton.md +9 -3
- package/dist/ai/BbBreadcrumbs.md +2 -2
- package/dist/ai/BbButton.md +113 -8
- package/dist/ai/BbCheckbox.md +1 -1
- package/dist/ai/BbCheckboxGroup.md +94 -6
- package/dist/ai/BbColorInput.md +4 -1
- package/dist/ai/BbColorPalette.md +2 -1
- package/dist/ai/BbConfirm.md +7 -3
- package/dist/ai/BbDatePicker.md +2 -1
- package/dist/ai/BbDatePickerInput.md +4 -1
- package/dist/ai/BbDialog.md +12 -11
- package/dist/ai/BbDropdown.md +189 -38
- package/dist/ai/BbDropdownButton.md +27 -7
- package/dist/ai/BbForm.md +55 -22
- package/dist/ai/BbHost.md +2 -2
- package/dist/ai/BbHoverCard.md +7 -3
- package/dist/ai/BbIcon.md +12 -6
- package/dist/ai/BbIndicator.md +11 -1
- package/dist/ai/BbNumberInput.md +4 -1
- package/dist/ai/BbOffCanvas.md +37 -3
- package/dist/ai/BbPopover.md +2 -1
- package/dist/ai/BbRadio.md +1 -1
- package/dist/ai/BbRadioGroup.md +102 -10
- package/dist/ai/BbSelect.md +52 -17
- package/dist/ai/BbSelectPopover.md +93 -26
- package/dist/ai/BbSwitch.md +1 -1
- package/dist/ai/BbSwitchGroup.md +30 -3
- package/dist/ai/BbTable.md +17 -10
- package/dist/ai/BbTabs.md +8 -3
- package/dist/ai/BbTabsList.md +4 -1
- package/dist/ai/BbTag.md +5 -2
- package/dist/ai/BbTextInput.md +4 -1
- package/dist/ai/BbTextarea.md +4 -1
- package/dist/ai/BbTimePicker.md +2 -1
- package/dist/ai/BbTimePickerInput.md +4 -1
- package/dist/ai/BbToast.md +9 -3
- package/dist/ai/BbTooltip.md +71 -9
- package/dist/ai/ChipsBox.md +1 -1
- package/dist/ai/CommonField.md +1 -1
- package/dist/ai/OptionsContainer.md +42 -0
- package/dist/ai/changelog.json +416 -6
- package/dist/ai/components.json +50 -48
- package/dist/ai/composables/useConfirm.md +39 -1
- package/dist/ai/design-tokens.json +6 -6
- package/dist/ai/guides/agent-contract.md +2 -2
- package/dist/ai/guides/ai-router.md +24 -23
- package/dist/ai/guides/app-layout.md +5 -0
- package/dist/ai/guides/component-picker.md +9 -2
- package/dist/ai/guides/design-language.md +24 -24
- package/dist/ai/guides/design-tokens.md +15 -8
- package/dist/ai/guides/icons-policy.md +9 -2
- package/dist/ai/guides/inertia-helpers.md +79 -49
- package/dist/ai/guides/installation-and-plugin-setup.md +12 -2
- package/dist/ai/guides/migration/adoption-checklist.md +235 -0
- package/dist/ai/guides/migration/components/bb-checkbox-group.md +16 -15
- package/dist/ai/guides/migration/components/bb-dialog.md +9 -9
- package/dist/ai/guides/migration/components/bb-dropdown.md +7 -2
- package/dist/ai/guides/migration/components/bb-popover.md +4 -2
- package/dist/ai/guides/migration/components/bb-select.md +19 -0
- package/dist/ai/guides/migration/components/bb-table.md +1 -0
- package/dist/ai/guides/migration/components/bb-toast.md +4 -0
- package/dist/ai/guides/migration/components/bb-tooltip.md +15 -12
- package/dist/ai/guides/migration/components/use-confirm.md +25 -2
- package/dist/ai/guides/migration/v2-to-v3.md +163 -9
- package/dist/ai/guides/migration/v3-beta-css-classes.md +7 -3
- package/dist/ai/guides/options-items-playbook.md +2 -1
- package/dist/ai/guides/passthrough.md +147 -85
- package/dist/ai/guides/preset-components.md +140 -15
- package/dist/ai/helpers/definePreset.json +7 -0
- package/dist/ai/helpers/definePreset.ts +123 -11
- package/dist/ai/helpers/inertia/manifest.json +15 -9
- package/dist/ai/helpers/inertia/useConfirmOnRouteLeave.ts +4 -4
- package/dist/ai/helpers/inertia/usePaginatedResponseContext.ts +39 -24
- package/dist/ai/helpers/inertia/useRouteQuery.ts +10 -4
- package/dist/ai/index.md +1 -0
- package/dist/ai/manifest/common.json +0 -1
- package/dist/ai/manifest/components/BbAlert.json +7 -2
- package/dist/ai/manifest/components/BbBadge.json +13 -4
- package/dist/ai/manifest/components/BbBadge.tree.json +2 -0
- package/dist/ai/manifest/components/BbBadgeButton.json +4 -2
- package/dist/ai/manifest/components/BbBaseButton.json +4 -2
- package/dist/ai/manifest/components/BbBreadcrumbs.tree.json +1 -1
- package/dist/ai/manifest/components/BbButton.json +14 -3
- package/dist/ai/manifest/components/BbButton.tree.json +5 -1
- package/dist/ai/manifest/components/BbCheckboxGroup.json +13 -8
- package/dist/ai/manifest/components/BbCheckboxGroup.tree.json +11 -1
- package/dist/ai/manifest/components/BbColorInput.json +18 -15
- package/dist/ai/manifest/components/BbColorPalette.json +1 -1
- package/dist/ai/manifest/components/BbConfirm.json +4 -2
- package/dist/ai/manifest/components/BbConfirm.tree.json +1 -1
- package/dist/ai/manifest/components/BbDatePicker.json +1 -1
- package/dist/ai/manifest/components/BbDatePickerInput.json +17 -14
- package/dist/ai/manifest/components/BbDialog.tree.json +2 -1
- package/dist/ai/manifest/components/BbDropdown.json +24 -19
- package/dist/ai/manifest/components/BbDropdown.tree.json +9 -2
- package/dist/ai/manifest/components/BbDropdownButton.json +33 -20
- package/dist/ai/manifest/components/BbDropdownButton.tree.json +2 -2
- package/dist/ai/manifest/components/BbForm.json +2 -2
- package/dist/ai/manifest/components/BbHost.tree.json +1 -1
- package/dist/ai/manifest/components/BbHoverCard.json +1 -1
- package/dist/ai/manifest/components/BbIndicator.json +8 -2
- package/dist/ai/manifest/components/BbNumberInput.json +5 -2
- package/dist/ai/manifest/components/BbOffCanvas.json +2 -2
- package/dist/ai/manifest/components/BbOffCanvas.tree.json +1 -1
- package/dist/ai/manifest/components/BbPopover.json +1 -1
- package/dist/ai/manifest/components/BbRadioGroup.json +17 -12
- package/dist/ai/manifest/components/BbRadioGroup.tree.json +8 -1
- package/dist/ai/manifest/components/BbSelect.json +21 -18
- package/dist/ai/manifest/components/BbSelect.tree.json +2 -2
- package/dist/ai/manifest/components/BbSelectPopover.json +10 -10
- package/dist/ai/manifest/components/BbSelectPopover.tree.json +3 -2
- package/dist/ai/manifest/components/BbSwitchGroup.json +1 -1
- package/dist/ai/manifest/components/BbSwitchGroup.tree.json +3 -1
- package/dist/ai/manifest/components/BbTable.tree.json +14 -1
- package/dist/ai/manifest/components/BbTabs.json +9 -6
- package/dist/ai/manifest/components/BbTabs.tree.json +1 -1
- package/dist/ai/manifest/components/BbTabsList.json +6 -3
- package/dist/ai/manifest/components/BbTag.json +19 -16
- package/dist/ai/manifest/components/BbTag.tree.json +1 -1
- package/dist/ai/manifest/components/BbTextInput.json +6 -3
- package/dist/ai/manifest/components/BbTextarea.json +6 -3
- package/dist/ai/manifest/components/BbTimePicker.json +1 -1
- package/dist/ai/manifest/components/BbTimePickerInput.json +10 -7
- package/dist/ai/manifest/components/BbToast.json +7 -2
- package/dist/ai/manifest/components/BbToast.tree.json +4 -2
- package/dist/ai/manifest/components/BbTooltip.json +6 -5
- package/dist/ai/manifest/components/ChipsBox.tree.json +1 -1
- package/dist/ai/manifest/components/CommonField.json +1 -1
- package/dist/ai/manifest/components/OptionsContainer.json +3 -1
- package/dist/ai/manifest/components/OptionsContainer.tree.json +38 -0
- package/dist/ai/manifest/index.json +3 -3
- package/dist/ai/manifest/meta.json +5 -3
- package/dist/ai/manifest/types.advanced.json +5 -2
- package/dist/ai/manifest/types.api.json +9 -7
- package/dist/ai/recipes/inertia/layout-scaffold.md +19 -6
- package/dist/ai/recipes/inertia/records-workspace.md +49 -13
- package/dist/ai/recipes/nuxt/layout-scaffold.md +19 -6
- package/dist/ai/recipes/nuxt/records-workspace.md +42 -12
- package/dist/ai/recipes/vue/layout-scaffold.md +19 -6
- package/dist/ai/recipes/vue/records-workspace.md +42 -12
- package/dist/ai/source/BbAlert.md +94 -76
- package/dist/ai/source/BbBadge.md +174 -72
- package/dist/ai/source/BbBadgeButton.md +130 -65
- package/dist/ai/source/BbBaseButton.md +46 -124
- package/dist/ai/source/BbBaseCheckboxIcon.md +38 -0
- package/dist/ai/source/BbBaseRadioIcon.md +18 -0
- package/dist/ai/source/BbBaseSwitchIcon.md +51 -0
- package/dist/ai/source/BbButton.md +153 -36
- package/dist/ai/source/BbCheckboxGroup.md +142 -18
- package/dist/ai/source/BbColorInput.md +240 -204
- package/dist/ai/source/BbColorPalette.md +7 -4
- package/dist/ai/source/BbConfirm.md +34 -11
- package/dist/ai/source/BbConfirmPortal.md +24 -9
- package/dist/ai/source/BbDatePicker.md +11 -7
- package/dist/ai/source/BbDatePickerInput.md +306 -269
- package/dist/ai/source/BbDialog.md +49 -14
- package/dist/ai/source/BbDropdown.md +314 -197
- package/dist/ai/source/BbDropdownButton.md +197 -31
- package/dist/ai/source/BbDropdownGroup.md +274 -176
- package/dist/ai/source/BbForm.md +50 -6
- package/dist/ai/source/BbHoverCard.md +12 -5
- package/dist/ai/source/BbIcon.md +4 -3
- package/dist/ai/source/BbIndicator.md +73 -52
- package/dist/ai/source/BbNumberInput.md +293 -257
- package/dist/ai/source/BbOffCanvas.md +55 -29
- package/dist/ai/source/BbPopover.md +14 -10
- package/dist/ai/source/BbRadioGroup.md +413 -297
- package/dist/ai/source/BbSelect.md +549 -435
- package/dist/ai/source/BbSelectPopover.md +128 -33
- package/dist/ai/source/BbSwitchGroup.md +70 -10
- package/dist/ai/source/BbTable.md +369 -37
- package/dist/ai/source/BbTabs.md +115 -39
- package/dist/ai/source/BbTabsList.md +106 -38
- package/dist/ai/source/BbTabsPanels.md +96 -36
- package/dist/ai/source/BbTabsRoot.md +96 -36
- package/dist/ai/source/BbTag.md +267 -233
- package/dist/ai/source/BbTextInput.md +261 -225
- package/dist/ai/source/BbTextarea.md +251 -215
- package/dist/ai/source/BbTimePicker.md +11 -7
- package/dist/ai/source/BbTimePickerInput.md +257 -220
- package/dist/ai/source/BbToast.md +73 -32
- package/dist/ai/source/BbToastPortal.md +65 -30
- package/dist/ai/source/BbTooltip.md +148 -113
- package/dist/ai/source/CommonPopover.md +6 -1
- package/dist/ai/source/FlatListBox.md +19 -9
- package/dist/ai/source/GroupedListBox.md +19 -9
- package/dist/ai/source/OptionsContainer.md +25 -9
- package/dist/components/BbAlert/BbAlert.vue_vue_type_script_setup_true_lang.js +61 -36
- package/dist/components/BbAlert/types.d.ts +9 -5
- package/dist/components/BbAlert/types.js +8 -3
- package/dist/components/BbBadge/BadgeBodyContent.vue.d.ts +3 -3
- package/dist/components/BbBadge/BadgeBodyContent.vue_vue_type_script_setup_true_lang.js +26 -17
- package/dist/components/BbBadge/BbBadge.vue_vue_type_script_setup_true_lang.js +103 -50
- package/dist/components/BbBadge/BbBadgeButton.vue_vue_type_script_setup_true_lang.js +20 -15
- package/dist/components/BbBadge/badgeButtonContext.d.ts +12 -1
- package/dist/components/BbBadge/types.d.ts +45 -15
- package/dist/components/BbBadge/types.js +12 -3
- package/dist/components/BbBaseButton/BbBaseButton.vue_vue_type_script_setup_true_lang.js +89 -126
- package/dist/components/BbBaseButton/types.d.ts +23 -4
- package/dist/components/BbBaseButton/types.js +7 -1
- package/dist/components/BbBaseButton/useLinkState.d.ts +41 -0
- package/dist/components/BbBaseButton/useLinkState.js +70 -0
- package/dist/components/BbButton/BbButton.vue_vue_type_script_setup_true_lang.js +130 -74
- package/dist/components/BbButton/types.d.ts +50 -13
- package/dist/components/BbButton/types.js +10 -3
- package/dist/components/BbCheckboxGroup/BbCheckboxGroup.vue_vue_type_script_setup_true_lang.js +148 -95
- package/dist/components/BbCheckboxGroup/types.d.ts +34 -11
- package/dist/components/BbCheckboxGroup/types.js +9 -4
- package/dist/components/BbCollapsible/BbCollapsible.vue.d.ts +1 -1
- package/dist/components/BbColorInput/BbColorInput.vue_vue_type_script_setup_true_lang.js +134 -93
- package/dist/components/BbColorInput/types.d.ts +11 -4
- package/dist/components/BbColorInput/types.js +9 -3
- package/dist/components/BbConfirm/BbConfirm.vue_vue_type_script_setup_true_lang.js +82 -59
- package/dist/components/BbConfirm/types.d.ts +9 -4
- package/dist/components/BbConfirm/types.js +8 -3
- package/dist/components/BbDatePicker/BbDatePicker.vue.d.ts +1 -1
- package/dist/components/BbDatePicker/BbDatePicker.vue_vue_type_script_setup_true_lang.js +68 -67
- package/dist/components/BbDatePickerInput/BbDatePickerInput.vue.d.ts +1 -1
- package/dist/components/BbDatePickerInput/BbDatePickerInput.vue_vue_type_script_setup_true_lang.js +259 -215
- package/dist/components/BbDatePickerInput/types.d.ts +12 -5
- package/dist/components/BbDatePickerInput/types.js +9 -3
- package/dist/components/BbDialog/BbDialog.vue_vue_type_script_setup_true_lang.js +223 -219
- package/dist/components/BbDialog/useDialogStack.d.ts +1 -1
- package/dist/components/BbDropdown/AdaptiveDropdown.vue_vue_type_script_setup_true_lang.js +104 -89
- package/dist/components/BbDropdown/BbDropdown.vue.d.ts +1 -0
- package/dist/components/BbDropdown/BbDropdown.vue_vue_type_script_setup_true_lang.js +323 -285
- package/dist/components/BbDropdown/BbDropdownList.vue.d.ts +1 -0
- package/dist/components/BbDropdown/BbDropdownList.vue_vue_type_script_setup_true_lang.js +411 -319
- package/dist/components/BbDropdown/DropdownPipelineResolver.vue_vue_type_script_setup_true_lang.js +100 -98
- package/dist/components/BbDropdown/DropdownRow.vue.d.ts +4 -3
- package/dist/components/BbDropdown/DropdownRow.vue_vue_type_script_setup_true_lang.js +49 -28
- package/dist/components/BbDropdown/normalizeGroups.d.ts +6 -0
- package/dist/components/BbDropdown/normalizeGroups.js +21 -15
- package/dist/components/BbDropdown/types.d.ts +59 -12
- package/dist/components/BbDropdown/types.js +16 -3
- package/dist/components/BbDropdown/useDropdownContext.d.ts +6 -0
- package/dist/components/BbDropdownButton/BbDropdownButton.vue.d.ts +2 -1
- package/dist/components/BbDropdownButton/BbDropdownButton.vue_vue_type_script_setup_true_lang.js +179 -68
- package/dist/components/BbDropdownButton/types.d.ts +44 -16
- package/dist/components/BbDropdownButton/types.js +28 -3
- package/dist/components/BbForm/BbForm.vue_vue_type_script_setup_true_lang.js +111 -89
- package/dist/components/BbForm/formSchema.d.ts +13 -0
- package/dist/components/BbHoverCard/BbHoverCard.vue_vue_type_script_setup_true_lang.js +100 -100
- package/dist/components/BbIndicator/BbIndicator.vue_vue_type_script_setup_true_lang.js +40 -25
- package/dist/components/BbIndicator/types.d.ts +9 -5
- package/dist/components/BbIndicator/types.js +8 -3
- package/dist/components/BbNumberInput/BbNumberInput.vue_vue_type_script_setup_true_lang.js +243 -202
- package/dist/components/BbNumberInput/types.d.ts +12 -5
- package/dist/components/BbNumberInput/types.js +9 -3
- package/dist/components/BbOffCanvas/BbOffCanvas.vue.d.ts +1 -1
- package/dist/components/BbOffCanvas/BbOffCanvas.vue_vue_type_script_setup_true_lang.js +401 -399
- package/dist/components/BbOffCanvas/types.d.ts +6 -2
- package/dist/components/BbPopover/BbPopover.vue_vue_type_script_setup_true_lang.js +81 -80
- package/dist/components/BbRadioGroup/BbRadioGroup.vue_vue_type_script_setup_true_lang.js +158 -105
- package/dist/components/BbRadioGroup/types.d.ts +21 -7
- package/dist/components/BbRadioGroup/types.js +9 -4
- package/dist/components/BbSelect/BbSelect.vue.d.ts +4 -3
- package/dist/components/BbSelect/BbSelect.vue_vue_type_script_setup_true_lang.js +181 -137
- package/dist/components/BbSelect/types.d.ts +36 -22
- package/dist/components/BbSelect/types.js +22 -3
- package/dist/components/BbSelectPopover/BbSelectPopover.vue.d.ts +4 -4
- package/dist/components/BbSelectPopover/BbSelectPopover.vue_vue_type_script_setup_true_lang.js +543 -532
- package/dist/components/BbSelectPopover/knownItems.d.ts +5 -0
- package/dist/components/BbSelectPopover/types.d.ts +46 -12
- package/dist/components/BbSmoothHeight/BbSmoothHeight.vue.d.ts +1 -1
- package/dist/components/BbSwitchGroup/BbSwitchGroup.vue_vue_type_script_setup_true_lang.js +2 -2
- package/dist/components/BbSwitchGroup/types.d.ts +14 -4
- package/dist/components/BbSwitchGroup/types.js +8 -3
- package/dist/components/BbTable/BbTable.vue_vue_type_script_setup_true_lang.js +1102 -995
- package/dist/components/BbTable/estimatedFloors.golden.d.ts +25 -0
- package/dist/components/BbTable/measuredFloors.d.ts +46 -0
- package/dist/components/BbTable/measuredFloors.js +322 -0
- package/dist/components/BbTable/measuredFloorsTestKit.d.ts +27 -0
- package/dist/components/BbTable/textRuler.d.ts +71 -0
- package/dist/components/BbTable/textRuler.js +121 -0
- package/dist/components/BbTable/utils.d.ts +113 -6
- package/dist/components/BbTable/utils.js +118 -65
- package/dist/components/BbTabs/BbTabs.vue_vue_type_script_setup_true_lang.js +53 -35
- package/dist/components/BbTabs/BbTabsList.vue_vue_type_script_setup_true_lang.js +62 -45
- package/dist/components/BbTabs/types.d.ts +26 -11
- package/dist/components/BbTabs/types.js +23 -8
- package/dist/components/BbTag/BbTag.vue_vue_type_script_setup_true_lang.js +205 -164
- package/dist/components/BbTag/types.d.ts +11 -4
- package/dist/components/BbTag/types.js +9 -3
- package/dist/components/BbTextInput/BbTextInput.vue_vue_type_script_setup_true_lang.js +98 -57
- package/dist/components/BbTextInput/types.d.ts +12 -5
- package/dist/components/BbTextInput/types.js +9 -3
- package/dist/components/BbTextarea/BbTextarea.vue_vue_type_script_setup_true_lang.js +137 -96
- package/dist/components/BbTextarea/types.d.ts +12 -5
- package/dist/components/BbTextarea/types.js +9 -3
- package/dist/components/BbTimePicker/BbTimePicker.vue_vue_type_script_setup_true_lang.js +105 -104
- package/dist/components/BbTimePickerInput/BbTimePickerInput.vue_vue_type_script_setup_true_lang.js +241 -197
- package/dist/components/BbTimePickerInput/types.d.ts +12 -5
- package/dist/components/BbTimePickerInput/types.js +9 -3
- package/dist/components/BbToast/BbToast.vue_vue_type_script_setup_true_lang.js +74 -32
- package/dist/components/BbToast/BbToastMessage.vue_vue_type_script_setup_true_lang.js +47 -47
- package/dist/components/BbToast/types.d.ts +10 -5
- package/dist/components/BbToast/types.js +18 -3
- package/dist/components/BbTooltip/BbTooltip.vue_vue_type_script_setup_true_lang.js +85 -71
- package/dist/components/BbTooltip/types.d.ts +13 -8
- package/dist/components/BbTooltip/types.js +8 -3
- package/dist/components/CommonField/CommonField.vue.d.ts +1 -1
- package/dist/components/CommonPopover/CommonPopover.vue.d.ts +1 -1
- package/dist/components/CommonPopover/CommonPopover.vue_vue_type_script_setup_true_lang.js +69 -69
- package/dist/components/FlatListBox/FlatListBox.vue_vue_type_script_setup_true_lang.js +53 -50
- package/dist/components/GroupedListBox/GroupedListBox.vue_vue_type_script_setup_true_lang.js +146 -143
- package/dist/components/OptionsContainer/OptionsContainer.vue_vue_type_script_setup_true_lang.js +7 -2
- package/dist/components/OptionsContainer/types.d.ts +14 -3
- package/dist/composables/useBbFormContext.d.ts +4 -3
- package/dist/composables/useBbTabsContext.js +99 -85
- package/dist/composables/useChoiceIndicator.d.ts +58 -0
- package/dist/composables/useChoiceIndicator.js +197 -0
- package/dist/composables/useConfirm.d.ts +4 -4
- package/dist/composables/usePassthrough.d.ts +54 -1
- package/dist/composables/usePassthrough.js +100 -71
- package/dist/directives/bbTooltip.d.ts +12 -6
- package/dist/directives/createPopoverDirective.js +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/llms-full.txt +2300 -543
- package/dist/llms-medium.txt +71 -53
- package/dist/llms.txt +2 -1
- package/dist/passthrough-deduper.js +6 -3
- package/dist/project-dts.d.ts +24 -0
- package/dist/project-dts.js +43 -17
- package/dist/styles.css +2 -2
- package/dist/types/AlertVariant.d.ts +14 -0
- package/dist/types/AlertVariant.js +9 -0
- package/dist/types/BadgeVariant.d.ts +14 -0
- package/dist/types/BadgeVariant.js +9 -0
- package/dist/types/ButtonVariant.d.ts +16 -0
- package/dist/types/ButtonVariant.js +11 -0
- package/dist/types/CheckboxVariant.d.ts +38 -0
- package/dist/types/CheckboxVariant.js +4 -0
- package/dist/types/CommonProps.d.ts +4 -3
- package/dist/types/Config.d.ts +7 -0
- package/dist/types/ConfirmVariant.d.ts +12 -0
- package/dist/types/ConfirmVariant.js +4 -0
- package/dist/types/DropdownItemVariant.d.ts +12 -0
- package/dist/types/DropdownItemVariant.js +4 -0
- package/dist/types/IndicatorVariant.d.ts +15 -0
- package/dist/types/IndicatorVariant.js +10 -0
- package/dist/types/InputVariant.d.ts +13 -0
- package/dist/types/InputVariant.js +8 -0
- package/dist/types/RadioVariant.d.ts +38 -0
- package/dist/types/RadioVariant.js +4 -0
- package/dist/types/TabsVariant.d.ts +13 -0
- package/dist/types/TabsVariant.js +8 -0
- package/dist/types/ToastVariant.d.ts +15 -0
- package/dist/types/ToastVariant.js +10 -0
- package/dist/types/TooltipVariant.d.ts +12 -0
- package/dist/types/TooltipVariant.js +4 -0
- package/dist/types/passthrough.d.ts +83 -15
- package/dist/types/passthrough.js +2 -2
- package/dist/types/ptComponentMap.d.ts +35 -23
- package/dist/utilities/functions/extractDomContainer.d.ts +20 -1
- package/dist/utilities/functions/extractDomContainer.js +8 -3
- package/dist/utils/focusVisibility.d.ts +6 -0
- package/dist/utils/focusVisibility.js +4 -1
- package/dist/utils/passthroughDeduper.d.ts +14 -0
- package/dist/utils/versionCheck.js +1 -1
- package/dist/vite-plugin.d.ts +64 -7
- package/dist/vite.js +385 -259
- package/llms.txt +2 -1
- package/package.json +3 -3
- package/scripts/lib/adoption-checklist.json +312 -0
- package/scripts/lib/eslint-plugin.d.ts +13 -0
- package/scripts/lib/eslint-plugin.mjs +75 -11
- package/scripts/lib/idiom-scan.mjs +65 -0
- package/scripts/lib/mcp-config.mjs +203 -9
- package/scripts/lib/migrate-fix.mjs +42 -1
- package/scripts/lib/project-variant-dts.mjs +18 -0
- package/scripts/lib/validate-bb-markup.mjs +99 -2
package/dist/ai/BbDropdown.md
CHANGED
|
@@ -52,7 +52,10 @@ An `items` entry is one of three shapes, and you can mix them freely:
|
|
|
52
52
|
- a **separator section** — a nested `[ … ]` array, rendered as its own
|
|
53
53
|
divider-separated anonymous group;
|
|
54
54
|
- a **group object** — `{ id, label?, items, selectable?, … }`, a titled and/or
|
|
55
|
-
selectable section (next sections). A group
|
|
55
|
+
selectable section (next sections). A group with plain rows and no
|
|
56
|
+
`selectable` needs `group: true` to be a group rather than a submenu row;
|
|
57
|
+
[Titled sections](#titled-sections-group-true-or-groupby) compares it with
|
|
58
|
+
`groupBy`, which titles the rows of one group. A group's heading is its `label` too;
|
|
56
59
|
add `hideLabel` to keep the `label` for the adaptive sheet title / chips /
|
|
57
60
|
`useBbDropdownContext` while rendering no heading in the menu.
|
|
58
61
|
|
|
@@ -89,6 +92,10 @@ check` flags both (`missing-value`, `duplicate-row-label`) when the items are
|
|
|
89
92
|
rendering a `bb-dropdown__item--variant-<name>` class hook you style yourself.
|
|
90
93
|
- `disabled` — non-interactive row, skipped by keyboard navigation.
|
|
91
94
|
|
|
95
|
+
Nothing else on an item reaches the row. An attribute for it (a `data-*` test
|
|
96
|
+
hook, an `aria-*`) goes through `pt:item`, per row with the function form:
|
|
97
|
+
`:pt:item="({ item }) => ({ attrs: { 'data-test': item.value } })"`.
|
|
98
|
+
|
|
92
99
|
Note how the destructive item below follows the design rule end to end: its
|
|
93
100
|
`onClick` awaits [useConfirm](./composables/useConfirm.md) and acts only on a
|
|
94
101
|
yes (`<BbHost />` mounts once per app, at the root).
|
|
@@ -212,9 +219,9 @@ trigger (unless the action moved focus elsewhere, e.g. opened a dialog). When
|
|
|
212
219
|
the `onClick` returns a promise, the dropdown keeps tracking it after the menu
|
|
213
220
|
has closed: the `activator` slot's `loading` flag stays `true` until it
|
|
214
221
|
settles, and re-clicks on that item are ignored while it's in flight. Reflect
|
|
215
|
-
`loading` on your trigger and you get a busy state for free.
|
|
216
|
-
|
|
217
|
-
`aria-busy` while its handler runs.
|
|
222
|
+
`loading` on your trigger and you get a busy state for free. A selectable
|
|
223
|
+
row closes the menu only as `closeOnSelect` says (see _Selectable groups_),
|
|
224
|
+
and the row itself carries `aria-busy` while its handler runs.
|
|
218
225
|
|
|
219
226
|
**Background sync with a busy trigger**
|
|
220
227
|
|
|
@@ -285,8 +292,11 @@ Give an item its own `items` array and it opens a submenu — recursively, to an
|
|
|
285
292
|
depth. A chevron is shown automatically (it replaces any `append:icon`). On
|
|
286
293
|
desktop, submenus are hover-intent flyouts (opening waits for the parent
|
|
287
294
|
panel's transition; leaving tolerates a short diagonal move); clicking a parent
|
|
288
|
-
row opens its submenu
|
|
289
|
-
|
|
295
|
+
row opens its submenu with focus inside (its search box, when it has one) and
|
|
296
|
+
never closes the menu, and `Escape` closes one level at a time (see
|
|
297
|
+
[Accessibility](#accessibility) for every key). On the mobile sheet the same
|
|
298
|
+
items **drill down** one level at a time with a back control instead
|
|
299
|
+
(`Escape` is the same back step). Use
|
|
290
300
|
submenus to group rarely-used options without crowding the top level; keep the
|
|
291
301
|
nesting shallow (two levels is plenty).
|
|
292
302
|
|
|
@@ -388,10 +398,16 @@ Behavior you can rely on:
|
|
|
388
398
|
|
|
389
399
|
- a **single** group is a radio group: re-clicking the selected row keeps it
|
|
390
400
|
(the row's `onClick` still runs, no `item:selected` / `item:unselected`
|
|
391
|
-
fires). Add `clearable: true` to the group to make that re-click clear it
|
|
392
|
-
|
|
393
|
-
(the same
|
|
401
|
+
fires). Add `clearable: true` to the group to make that re-click clear it;
|
|
402
|
+
- a change in a **single** group closes the menu and puts focus back on the
|
|
403
|
+
trigger: a pick (the same value included) or a `clearable` group's clear,
|
|
404
|
+
wherever the group sits (inside a submenu too) and whatever else the menu
|
|
405
|
+
holds — a filter menu with a "Role" list and a "Deleted" on/off entry
|
|
406
|
+
closes after either;
|
|
394
407
|
- a **multiple** group keeps the menu open while you toggle;
|
|
408
|
+
- `close-on-select` overrides both: `true` closes after every selection
|
|
409
|
+
change (a multiple pick included), `false` never closes on a selection.
|
|
410
|
+
Plain actions close the menu either way;
|
|
395
411
|
- the dropdown emits `item:selected` / `item:unselected` with the item's
|
|
396
412
|
**value** (its `itemValue` for pipeline groups, else its own `value`) when the user
|
|
397
413
|
picks or unpicks a row, never for your own changes to a group's value — the
|
|
@@ -410,8 +426,7 @@ const statusGroup = {
|
|
|
410
426
|
```
|
|
411
427
|
|
|
412
428
|
- The group is still a selectable group (a function counts as `true`): checks,
|
|
413
|
-
`menuitemcheckbox` / `menuitemradio` roles, the
|
|
414
|
-
toggling.
|
|
429
|
+
`menuitemcheckbox` / `menuitemradio` roles, and the same closing rules.
|
|
415
430
|
- A row the function rejects renders **disabled**: clicks do nothing and
|
|
416
431
|
keyboard navigation skips it.
|
|
417
432
|
- The lock holds on a row that is **already selected** — it cannot be
|
|
@@ -598,6 +613,54 @@ rows distinct values when it matters:
|
|
|
598
613
|
- **Submenu parents.** A row that opens a submenu needs a value unique in the
|
|
599
614
|
whole menu; the flyout is addressed by it.
|
|
600
615
|
|
|
616
|
+
### Titled sections: `group: true` or `groupBy`
|
|
617
|
+
|
|
618
|
+
Two ways to put headings in a menu, for two different needs:
|
|
619
|
+
|
|
620
|
+
- **Independent sections, each its own group: `group: true`.** A group object
|
|
621
|
+
with `group: true` is a titled section (its `label` is the heading) without
|
|
622
|
+
being selectable; give it `selectable` and it becomes its own chooser. Each
|
|
623
|
+
group keeps **its own** value (its own companion and `v-model`) and, when
|
|
624
|
+
`searchable`, its own search field. Use it for sections that answer
|
|
625
|
+
different questions ("Sort by" / "Show").
|
|
626
|
+
- **One choice, sorted under headings: `groupBy` on one group.** The rows of a
|
|
627
|
+
single group are listed under section headings, and it stays one group:
|
|
628
|
+
**one** `v-model`, **one** search field. Use it when the headings only
|
|
629
|
+
organise the options of one question (categories under their sector).
|
|
630
|
+
|
|
631
|
+
```vue
|
|
632
|
+
<BbDropdown
|
|
633
|
+
:items="[
|
|
634
|
+
{
|
|
635
|
+
id: 'category',
|
|
636
|
+
label: 'Category',
|
|
637
|
+
selectable: true,
|
|
638
|
+
searchable: true,
|
|
639
|
+
groupBy: 'sector',
|
|
640
|
+
items: [
|
|
641
|
+
{ value: 1, label: 'Bakery', sector: 'Food' },
|
|
642
|
+
{ value: 2, label: 'Clothing', sector: 'No food' },
|
|
643
|
+
{ value: 3, label: 'Discount' },
|
|
644
|
+
],
|
|
645
|
+
},
|
|
646
|
+
]"
|
|
647
|
+
>
|
|
648
|
+
<BbDropdownGroup id="category" v-model="category" />
|
|
649
|
+
</BbDropdown>
|
|
650
|
+
```
|
|
651
|
+
|
|
652
|
+
- `groupBy` is a field path (`'sector'`, `'owner.team'`) read off each row,
|
|
653
|
+
or a function `(row) => string | null | undefined`. On a fetched group it
|
|
654
|
+
reads the **raw item**, so `items: ({ query }) => …` groups the same way.
|
|
655
|
+
- Sections keep the order of their first row. Rows whose `groupBy` gives
|
|
656
|
+
`null`, `undefined` or `''` have no section: they are listed **first**,
|
|
657
|
+
before every heading — the same rule as `BbSelect`'s `group-by`.
|
|
658
|
+
- A heading is not a row: the arrows and typeahead skip it, and it is never
|
|
659
|
+
selected. A search hides a section left without a matching row, heading
|
|
660
|
+
included.
|
|
661
|
+
- Each titled section is a `role="group"` labelled by its heading, with the
|
|
662
|
+
look of a group heading. The adaptive sheet shows the same sections.
|
|
663
|
+
|
|
601
664
|
### Loading options on demand
|
|
602
665
|
|
|
603
666
|
For options that come from an API, make the group a **pipeline group**: pass an
|
|
@@ -633,8 +696,9 @@ The full grammar:
|
|
|
633
696
|
- `loadingText` / `emptyText` / `failedText` — placeholder row text per
|
|
634
697
|
group; the dropdown-level `loading-text` / `empty-text` / `failed-text` props
|
|
635
698
|
set the default for all groups, and the `#loading` / `#empty` slots (payload:
|
|
636
|
-
`{ text, groupId }`, `#empty` also `error`) replace the placeholder
|
|
637
|
-
entirely.
|
|
699
|
+
`{ text, groupId, query }`, `#empty` also `error`) replace the placeholder
|
|
700
|
+
rows entirely. `query` is the group's search text (`''` without one), like
|
|
701
|
+
`BbSelect`'s `#empty="{ query }"`.
|
|
638
702
|
- `dependencies: [...]` + `depsDebounceTime` — re-run the getter (debounced)
|
|
639
703
|
when any dependency changes, e.g. a search field feeding the fetch.
|
|
640
704
|
- `enforceCoherence` — after a re-fetch, drop selected values that no longer
|
|
@@ -1112,6 +1176,30 @@ What each knob does:
|
|
|
1112
1176
|
`searchable`, which is the one place the three-state `prefill` differs from a
|
|
1113
1177
|
plain menu group (`'interaction'`, the default, fetches when the group is
|
|
1114
1178
|
first reached; `true` fetches on mount).
|
|
1179
|
+
- **A minimum query length** is the getter's call and the `#empty` slot's
|
|
1180
|
+
copy: return `[]` below it, and read `query` in the slot. The slot also
|
|
1181
|
+
replaces the search-first hint, so one condition covers both:
|
|
1182
|
+
|
|
1183
|
+
```vue
|
|
1184
|
+
<BbDropdown
|
|
1185
|
+
:items="[
|
|
1186
|
+
{
|
|
1187
|
+
id: 'zone',
|
|
1188
|
+
label: 'Zone',
|
|
1189
|
+
searchable: true,
|
|
1190
|
+
selectable: true,
|
|
1191
|
+
prefill: false,
|
|
1192
|
+
filterBy: false,
|
|
1193
|
+
items: ({ query }) => (query.length < 2 ? [] : api.zones({ q: query })),
|
|
1194
|
+
},
|
|
1195
|
+
]"
|
|
1196
|
+
>
|
|
1197
|
+
<template #empty="{ query, text }">
|
|
1198
|
+
{{ query.length < 2 ? 'Type at least 2 characters' : text }}
|
|
1199
|
+
</template>
|
|
1200
|
+
</BbDropdown>
|
|
1201
|
+
```
|
|
1202
|
+
|
|
1115
1203
|
- **`stash`** accumulates the items behind _selected_ keys so they stay
|
|
1116
1204
|
resolvable after the query changes. Without it, selecting in one search and
|
|
1117
1205
|
then searching for something else leaves the earlier selection unresolvable
|
|
@@ -1597,7 +1685,8 @@ const items: BbDropdownItem[] = [
|
|
|
1597
1685
|
- `placement` (default `'bottom'`) accepts every floating-UI placement
|
|
1598
1686
|
(`top`, `bottom-start`, `right-end`, …) plus `'cursor'`; the panel flips
|
|
1599
1687
|
automatically when there's no room, and the item list caps its height to the
|
|
1600
|
-
available space (scrolling inside).
|
|
1688
|
+
available space (scrolling inside). It is read at open: a change while open
|
|
1689
|
+
applies at the next open.
|
|
1601
1690
|
- `width` — `'auto'` (default) sizes to content with a 128px floor; a number
|
|
1602
1691
|
is pixels; a percentage is relative to the **anchor's width**, so
|
|
1603
1692
|
`width="100%"` makes the menu match its trigger.
|
|
@@ -1767,7 +1856,11 @@ the same floor the select's own sheet holds.
|
|
|
1767
1856
|
On viewports below the config's `mobileMaxWidth`, the menu renders as a
|
|
1768
1857
|
bottom-anchored, draggable, auto-sized off-canvas sheet instead of a flyout.
|
|
1769
1858
|
Nested submenus become drill-down levels with a back control (the parent
|
|
1770
|
-
item's text becomes the level title
|
|
1859
|
+
item's text becomes the level title, and the control points toward the
|
|
1860
|
+
inline start, mirrored under `dir="rtl"`). `Escape` on a drilled-in level, from
|
|
1861
|
+
a row or the level's search box, does what the back control does: back to the
|
|
1862
|
+
parent level, focus on the row that opened it. At the top level it closes the
|
|
1863
|
+
sheet. Selection, slots and events behave
|
|
1771
1864
|
exactly as on desktop. The surface is **latched per open**: resizing
|
|
1772
1865
|
mid-session never swaps a live menu between flyout and sheet.
|
|
1773
1866
|
|
|
@@ -1893,13 +1986,21 @@ const tags = ref<string[]>(['overdue']);
|
|
|
1893
1986
|
</script>
|
|
1894
1987
|
```
|
|
1895
1988
|
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1989
|
+
An entry's `variant` is a state of the entry parts: `pt:item:destructive`
|
|
1990
|
+
(or `'item:destructive'` in the object form and the global map) styles the
|
|
1991
|
+
destructive entries only, after the base `item` entry and before `selected` /
|
|
1992
|
+
`disabled`. So a base look never hides the red: a global
|
|
1993
|
+
`item: 'text-ink hover:bg-tint'` plus `'item:destructive': 'text-red-700'`
|
|
1994
|
+
keeps it, on the flyout and the phone sheet alike. An entry with no `variant`
|
|
1995
|
+
is `default`; a name of your own (`dropdownItemVariants: ['warning']`) works in
|
|
1996
|
+
every form, `pt:item:warning` included.
|
|
1997
|
+
|
|
1998
|
+
A look that depends on the ENTRY'S DATA — an entry flagged by the row it came
|
|
1999
|
+
from — is a **per-item function** on an entry part:
|
|
2000
|
+
`:pt:item="({ item, variant, selected, disabled }) => …"`, called with the menu
|
|
2001
|
+
entry, every state as a boolean for it and its `variant` as a string, its
|
|
2002
|
+
result merged after the state entries. Entry parts only (`item`, `itemText`,
|
|
2003
|
+
`itemIcon`, `itemDescription`), on the instance only.
|
|
1903
2004
|
|
|
1904
2005
|
**pt:item as a function — a destructive entry by its data**
|
|
1905
2006
|
|
|
@@ -2077,6 +2178,22 @@ A `pt` value written in `<script>` (a constant, a preset, a wrapper's
|
|
|
2077
2178
|
`pt` prop) is typed as `BbDropdownProps['pt']`, never an imported `PtValue`: see
|
|
2078
2179
|
[passthrough § Typing `pt` in `<script>`](./guides/passthrough.md#typing-pt-in-script).
|
|
2079
2180
|
|
|
2181
|
+
#### Item text and icon size
|
|
2182
|
+
|
|
2183
|
+
Two knobs on the menu set the rows' size, with BbButton's names: `--fs` the
|
|
2184
|
+
label (default `var(--bb-fs)`, the same as BbSelect's options) and
|
|
2185
|
+
`--icon-size` the prepend / append icons (default `1rem`). Submenus follow
|
|
2186
|
+
them. A denser desktop menu with 13px text and 14px icons:
|
|
2187
|
+
|
|
2188
|
+
```vue
|
|
2189
|
+
<BbDropdown class="[--fs:13px] [--icon-size:14px]" :items="items" />
|
|
2190
|
+
```
|
|
2191
|
+
|
|
2192
|
+
They size the desktop menu only. The phone sheet keeps its touch sizes (larger
|
|
2193
|
+
text and icons in 44px rows) and never reads them, so there is no desktop-only
|
|
2194
|
+
switch to add. A component inside a row (a `BbBadge` in an item slot) keeps its
|
|
2195
|
+
own sizes.
|
|
2196
|
+
|
|
2080
2197
|
### Works well with
|
|
2081
2198
|
|
|
2082
2199
|
- `BbDropdownButton` — the same `items` model behind a split button when one
|
|
@@ -2120,6 +2237,10 @@ A `pt` value written in `<script>` (a constant, a preset, a wrapper's
|
|
|
2120
2237
|
a check in `item:append`). Make the group `selectable` and bind its
|
|
2121
2238
|
`v-model` to the current id — the check, `aria-checked` and the radio role
|
|
2122
2239
|
come with it.
|
|
2240
|
+
- **A server-searched group needs `filterBy: false`.** The default local
|
|
2241
|
+
match runs on the getter's answer too, so a row the server matched on a field
|
|
2242
|
+
the menu doesn't show (an email, a fiscal code) is fetched and then hidden.
|
|
2243
|
+
See [Searchable groups](#searchable-groups).
|
|
2123
2244
|
- `width` defaults to `'auto'` (content-sized, ≥128px) — not a fixed pixel
|
|
2124
2245
|
width; pass a number when menus must align across rows.
|
|
2125
2246
|
- Item `variant`s other than `destructive` render only a class hook — register
|
|
@@ -2160,29 +2281,55 @@ A `pt` value written in `<script>` (a constant, a preset, a wrapper's
|
|
|
2160
2281
|
after the row that opened it; and the adaptive sheet, already a `<dialog>`,
|
|
2161
2282
|
just steps its menu container aside rather than nesting a second dialog.
|
|
2162
2283
|
Surfaces with no search field are unchanged.
|
|
2163
|
-
- Keyboard is fully handled
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
(
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2284
|
+
- Keyboard is fully handled, following the WAI-ARIA APG menu pattern — don't
|
|
2285
|
+
add your own handlers (table below). The menu is a single tab stop (rows are
|
|
2286
|
+
`tabindex="-1"` per the ARIA menu pattern): `Tab` leaves the menu and closes
|
|
2287
|
+
it. Focus returns to the activator after an action unless the action moved
|
|
2288
|
+
it (e.g. opened a dialog).
|
|
2289
|
+
- A submenu opener carries `aria-haspopup="menu"`, or `"dialog"` when the
|
|
2290
|
+
submenu has a search field, `aria-expanded`, and `aria-controls` naming the
|
|
2291
|
+
submenu while it is open; the submenu is named after its opener. Under `dir="rtl"` submenus open to the left, their
|
|
2292
|
+
chevron points left, and the two inline arrows swap.
|
|
2172
2293
|
- The focused row's highlight is keyboard-only (`:focus-visible`). The mobile
|
|
2173
2294
|
sheet always places real focus on the level's first row when it opens — a
|
|
2174
2295
|
modal dialog would otherwise skip the `tabindex="-1"` rows — but a menu
|
|
2175
2296
|
opened by tap or click paints nothing, so it never looks pre-selected.
|
|
2176
2297
|
|
|
2298
|
+
#### Keyboard
|
|
2299
|
+
|
|
2300
|
+
| Key | Where | What happens |
|
|
2301
|
+
| ------------------------------ | --------------------------------------- | ----------------------------------------------------------------------------- |
|
|
2302
|
+
| `ArrowDown` / `ArrowUp` | trigger | open the menu, focus on the first / last row |
|
|
2303
|
+
| `ArrowDown` / `ArrowUp` | row | next / previous enabled row of the same level, wrapping |
|
|
2304
|
+
| `ArrowDown` / `ArrowUp` | search box | first / last row of its level |
|
|
2305
|
+
| `Home` / `End` | row | first / last of the level (`Home` lands on its search box, when it has one) |
|
|
2306
|
+
| a letter | row | the level's next enabled row whose label starts with what was typed |
|
|
2307
|
+
| `ArrowRight`, `Enter`, `Space` | submenu opener | open the submenu, focus on its search box or first row |
|
|
2308
|
+
| click | submenu opener | the same: open it with focus inside |
|
|
2309
|
+
| hover | submenu opener | open it; focus never moves into it |
|
|
2310
|
+
| `ArrowLeft` | row in a submenu | close that level, focus on its opener (the search box keeps it for the caret) |
|
|
2311
|
+
| `Escape` | anywhere in a submenu (row, search box) | close that level only, focus on its opener: one level per press |
|
|
2312
|
+
| `Escape` | top level | close the menu, focus on the trigger |
|
|
2313
|
+
| pointer leaves the menu | focus inside a submenu | the submenu closes, focus lands on its opener |
|
|
2314
|
+
| `Tab` | inside | leave the menu, which closes |
|
|
2315
|
+
|
|
2316
|
+
`ArrowLeft` / `ArrowRight` read in the row's direction: swapped under
|
|
2317
|
+
`dir="rtl"`. A popover or dialog opened from an item takes `Escape` first;
|
|
2318
|
+
the menu gets it back once that closes. On the mobile sheet the drill-down
|
|
2319
|
+
uses `ArrowRight` / `ArrowLeft` and its back control; `Escape` on a drilled-in
|
|
2320
|
+
level (row or search box) goes back one level, focus on the row that opened
|
|
2321
|
+
it, and at the top level closes the sheet.
|
|
2322
|
+
|
|
2177
2323
|
## Props
|
|
2178
2324
|
|
|
2179
2325
|
| Prop | Type | Default | Required | Description |
|
|
2180
2326
|
| --- | --- | --- | --- | --- |
|
|
2181
|
-
| `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: `footer`, `header`, `input`, `item`, `itemDescription`, `itemIcon`, `itemText`, `list`, `panel`, `root`, `sheet`. States: `disabled`, `open`, `selected`. 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 `BbDropdownProps['pt']` (`PtValue` is not exported): § Typing `pt` in `<script>`. |
|
|
2327
|
+
| `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: `footer`, `header`, `input`, `item`, `itemDescription`, `itemIcon`, `itemText`, `list`, `panel`, `root`, `sheet`. States: `activeLink`, `disabled`, `exactActiveLink`, `open`, `selected`, `default`, `destructive`. 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 `BbDropdownProps['pt']` (`PtValue` is not exported): § Typing `pt` in `<script>`. |
|
|
2182
2328
|
| `activator` | `Record<string, any> \| HTMLElement \| null \| undefined` | | | An external activator element or component ref: the activator slot is not rendered, and the listeners and ARIA (`aria-haspopup` / `aria-expanded` / `aria-controls`) are attached to it; don't add your own. |
|
|
2183
2329
|
| `adaptive` | `boolean \| undefined` | ``config.adaptive` (`true`)` | | On mobile (below `config.mobileMaxWidth`), renders the menu as a bottom sheet that drills into submenus one level at a time instead of hover flyouts; slots and selection are unchanged. Unset: the global `config.adaptive`. |
|
|
2184
2330
|
| `anchor` | `Record<string, any> \| HTMLElement \| null \| undefined` | `the activator element` | | The element the panel positions against when it should differ from the activator (a wrapper the activator is part of); an HTMLElement or component ref. It also drives a percentage `width`. Ignored with `placement="cursor"`. |
|
|
2185
2331
|
| `boundary` | `string \| Record<string, any> \| HTMLElement \| null \| undefined` | | | Keeps the panel inside this element alongside its trigger (sideways for a menu above or below); away from the trigger it may pass the edge, and only the viewport flips it. An HTMLElement, a component ref or a CSS selector: a `useTemplateRef`, never `$refs.x` (not reactive). |
|
|
2332
|
+
| `closeOnSelect` | `boolean \| undefined` | `unset (close after a single-choice change)` | | Whether a selection closes the menu. Unset: a change in a single-choice group closes it (an untick too, at any depth); a `multiple` group stays open. `true`: every selection change closes it. `false`: none does. |
|
|
2186
2333
|
| `compact` | `boolean \| undefined` | `false` | | Compact density, the `BbSelect` ladder: flyout rows 28px → 24px, sheet rows 44px → 36px (a sheet row stays a touch target). The label size does not change. |
|
|
2187
2334
|
| `disabled` | `boolean \| undefined` | `false` | | Disables the component |
|
|
2188
2335
|
| `eager` | `boolean \| undefined` | `false` | | Renders the menu panel at mount instead of on the first open (the phone sheet's too), and keeps its rows after a close. Without it the rows mount on each open and go once the menu has closed. |
|
|
@@ -2223,9 +2370,13 @@ States are listed in precedence order: when two are on at once and their entries
|
|
|
2223
2370
|
|
|
2224
2371
|
| State | When it is on |
|
|
2225
2372
|
| --- | --- |
|
|
2373
|
+
| `activeLink` | Per node, on the entry parts: an entry whose link (`to` / `href`) points at the current page or one of its ancestors — exactly when its `activeClass` is on. The weakest state. |
|
|
2374
|
+
| `exactActiveLink` | Per node, on the entry parts: an entry whose link points at the current page itself — its `exactActiveClass` is on. |
|
|
2226
2375
|
| `selected` | Per node, on the entry parts: a selectable group's checked entry. |
|
|
2227
2376
|
| `disabled` | Per node, on the entry parts: an entry that is disabled. |
|
|
2228
2377
|
| `open` | Component-wide: the menu is open. |
|
|
2378
|
+
| `default` | Per entry, on the entry parts: an entry with `variant: 'default'` or none. Merged after the part's base entry and before its states, so the real states still win. |
|
|
2379
|
+
| `destructive` | Per entry, on the entry parts: `variant: 'destructive'`. Below the real states, like every variant. |
|
|
2229
2380
|
|
|
2230
2381
|
## Events
|
|
2231
2382
|
|
|
@@ -2240,12 +2391,12 @@ States are listed in precedence order: when two are on at once and their entries
|
|
|
2240
2391
|
|
|
2241
2392
|
- `activator` — scope: `BbDropdownActivatorSlotProps` `{ disabled?: boolean; loading: boolean; open: boolean; placement: Placement \| "cursor"; props: BbDropdownActivatorProps }` — The element that triggers the dropdown to open. Spread `props` onto your trigger element.
|
|
2242
2393
|
- `default` — scope: `any` — Hosts `<BbDropdownGroup>` companions. They register their group with the dropdown and render nothing themselves.
|
|
2243
|
-
- `empty` — scope: `BbDropdownPlaceholderSlotProps` `{ groupId?: string; text: string; error?: unknown }` — Replaces the default "no data" placeholder row shown in a pipeline group that resolved to no items. Rendered once per empty group.
|
|
2394
|
+
- `empty` — scope: `BbDropdownPlaceholderSlotProps` `{ groupId?: string; query: string; text: string; error?: unknown }` — Replaces the default "no data" placeholder row shown in a pipeline group that resolved to no items. Rendered once per empty group.
|
|
2244
2395
|
- `footer` — scope: `BbDropdownEdgeSlotProps` `{ disabled?: boolean; open: boolean; placement: Placement \| "cursor" }` — Content pinned to the bottom of the dropdown panel, outside the scroll area. Stays visible while the items scroll and is separated from them by a divider — for action buttons.
|
|
2245
2396
|
- `header` — scope: `BbDropdownEdgeSlotProps` `{ disabled?: boolean; open: boolean; placement: Placement \| "cursor" }` — Content pinned to the top of the dropdown panel, outside the scroll area. Stays visible while the items scroll and is separated from them by a divider — for a title or a filter field.
|
|
2246
|
-
- `item:append` — scope: `BbDropdownItemSlotProps` `{ description?: string; disabled?: boolean; group: BbDropdownSlotGroup; groupTitle: boolean; level: number; index: number; item: InternalItem; loading: boolean; open: boolean; placement: Placement \| "cursor"; selected: boolean; label: string }` — The trailing region of every row (and group title line), replacing its `append:icon`. A named slot wins over it; the submenu chevron and the check on a selected row take its place.
|
|
2247
|
-
- `item:prepend` — scope: `BbDropdownItemSlotProps` `{ description?: string; disabled?: boolean; group: BbDropdownSlotGroup; groupTitle: boolean; level: number; index: number; item: InternalItem; loading: boolean; open: boolean; placement: Placement \| "cursor"; selected: boolean; label: string }` — The leading region of every row (and group title line), replacing its `prepend:icon`. A row's own or its group's named slot wins over it.
|
|
2248
|
-
- `loading` — scope: `BbDropdownPlaceholderSlotProps` `{ groupId?: string; text: string; error?: unknown }` — Replaces the default loading placeholder row shown in a pipeline group while its async items load. Rendered once per loading group.
|
|
2397
|
+
- `item:append` — scope: `BbDropdownItemSlotProps` `{ description?: string; disabled?: boolean; group: BbDropdownSlotGroup; groupTitle: boolean; level: number; index: number; item: InternalItem; loading: boolean; open: boolean; placement: Placement \| "cursor"; selected: boolean; label: string; activeLink?: boolean; exactActiveLink?: boolean }` — The trailing region of every row (and group title line), replacing its `append:icon`. A named slot wins over it; the submenu chevron and the check on a selected row take its place.
|
|
2398
|
+
- `item:prepend` — scope: `BbDropdownItemSlotProps` `{ description?: string; disabled?: boolean; group: BbDropdownSlotGroup; groupTitle: boolean; level: number; index: number; item: InternalItem; loading: boolean; open: boolean; placement: Placement \| "cursor"; selected: boolean; label: string; activeLink?: boolean; exactActiveLink?: boolean }` — The leading region of every row (and group title line), replacing its `prepend:icon`. A row's own or its group's named slot wins over it.
|
|
2399
|
+
- `loading` — scope: `BbDropdownPlaceholderSlotProps` `{ groupId?: string; query: string; text: string; error?: unknown }` — Replaces the default loading placeholder row shown in a pipeline group while its async items load. Rendered once per loading group.
|
|
2249
2400
|
- `#<value>` (named from data) — scope: `BbDropdownItemSlotProps` — One row's content (label and description), by its value; in a fetched group, by its resolved `itemValue`. Reserved names (their slot is one of this component's own, so an item value or column key spelled like them is an error): `activator`, `default`, `empty`, `footer`, `header`, `item`, `loading`.
|
|
2250
2401
|
- `#<value>:prepend` (named from data) — scope: `BbDropdownItemSlotProps` — One row's leading region; replaces its `prepend:icon`.
|
|
2251
2402
|
- `#<value>:append` (named from data) — scope: `BbDropdownItemSlotProps` — One row's trailing region; replaces its `append:icon` and its submenu chevron. The check takes its place on the selected row.
|
|
@@ -2276,11 +2427,11 @@ Set these on the element, or on a class you put on it, to retune this component
|
|
|
2276
2427
|
|
|
2277
2428
|
- `BbDropdown` _(this component)_ — its own template binds: `panel` → `CommonPopover`, `root` → `CommonPopover`, `header` → `div.bb-dropdown__header`, `list` → `span.bb-dropdown__list`, `footer` → `div.bb-dropdown__footer`
|
|
2278
2429
|
- `BbDropdownList` _(internal — not importable, reach it through `BbDropdown`)_ — also mounts `BbIcon`, `ErrorIcon`, `CommonPopover`, `BbDropdownList`
|
|
2279
|
-
- `BbBadge` _(public — [contract](./BbBadge.md))_ — its own pt parts (`BbBadge`): `spinner` → `BbSpinner`, `icon` → `BbIcon`, `clear` → `button.bb-badge__clear`; documented CSS variables: `--bg`, `--fg`, `--bw`, `--ring-color`, `--ring-size`, `--min-size-md`, `--min-size`, `--elev`, `--r`, `--fs`, `--icon-size`, `--gap`, `--px`, `--clear-size`, `--bg-disabled`, `--fg-disabled`, `--border-disabled`, `--pad-left`; also mounts `BbIcon`, `BbSpinner`, `BadgeBodyContent`
|
|
2430
|
+
- `BbBadge` _(public — [contract](./BbBadge.md))_ — its own pt parts (`BbBadge`): `spinner` → `BbSpinner`, `icon` → `span.bb-badge__append-icon`, `icon` → `BbIcon`, `clear` → `button.bb-badge__clear`; documented CSS variables: `--bg`, `--fg`, `--bw`, `--ring-color`, `--ring-size`, `--min-size-md`, `--min-size`, `--elev`, `--r`, `--fs`, `--icon-size`, `--gap`, `--px`, `--clear-size`, `--bg-disabled`, `--fg-disabled`, `--border-disabled`, `--pad-left`; also mounts `BbIcon`, `BbSpinner`, `BadgeBodyContent`
|
|
2280
2431
|
- `AdaptiveDropdown` _(internal — not importable, reach it through `BbDropdown`)_ — hands `BbOffCanvas` the pt map `{ header: 'header', footer: 'footer', panel: 'root', sheet: 'root' }` (ours → theirs); also mounts `BbSmoothHeight`, `BbDropdownList`
|
|
2281
2432
|
- `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__content`, `footer` → `div.bb-offcanvas__footer`; documented CSS variables: `--stack-x`, `--snap-y`, `--stack-fill`, `--stack-transition-duration`, `--px`, `--handle-w`, `--handle-h`, `--handle-bg`, `--safe-top`, `--close-size`
|
|
2282
2433
|
- `CloseButton` _(internal — not importable, reach it through `BbOffCanvas`)_ — documented CSS variables: `--size`, `--p`
|
|
2283
|
-
- `BbButton` _(public — [contract](./BbButton.md))_ — its own pt parts (`BbButton`): `root` → `BbBaseButton`, `spinner` → `BbSpinner`, `icon` → `BbIcon`, `text` → `span.bb-button__text`; documented CSS variables: `--h-xs`, `--h`, `--icon-size`, `--px`, `--fs`, `--r`, `--gap`, `--bg`, `--bg-hover`, `--bg-pressed`, `--fg`, `--border-color`, `--ring-color`, `--ring-size`, `--bw`, `--fg-hover`, `--border-hover`, `--fg-pressed`, `--border-pressed`, `--bg-disabled`, `--fg-disabled`, `--border-disabled`, `--opacity-disabled`, `--elev-tier`, `--elev`; also mounts `BbIcon`, `BbSpinner`
|
|
2434
|
+
- `BbButton` _(public — [contract](./BbButton.md))_ — its own pt parts (`BbButton`): `root` → `BbBaseButton`, `spinner` → `BbSpinner`, `icon` → `span.bb-button__icon`, `icon` → `BbIcon`, `icon` → `span.bb-button__prepend-icon`, `text` → `span.bb-button__text`, `icon` → `span.bb-button__append-icon`; documented CSS variables: `--h-xs`, `--h`, `--icon-size`, `--px`, `--fs`, `--r`, `--gap`, `--bg`, `--bg-hover`, `--bg-pressed`, `--fg`, `--border-color`, `--ring-color`, `--ring-size`, `--bw`, `--fg-hover`, `--border-hover`, `--fg-pressed`, `--border-pressed`, `--bg-disabled`, `--fg-disabled`, `--border-disabled`, `--opacity-disabled`, `--elev-tier`, `--elev`; also mounts `BbIcon`, `BbSpinner`
|
|
2284
2435
|
- `BbBaseButton` _(public — [contract](./BbBaseButton.md))_ — its own pt parts (`BbBaseButton`): `root` → `RouterComponent`, `root` → `a`, `root` → `component`; also mounts `RouterComponent`
|
|
2285
2436
|
- Also mounts `CommonPopover`, `DropdownPipelineResolver`
|
|
2286
2437
|
|
|
@@ -379,6 +379,13 @@ activator slot: the toggle button is part of the component's contract.
|
|
|
379
379
|
</BbDropdownButton>
|
|
380
380
|
```
|
|
381
381
|
|
|
382
|
+
### Icons on the main button
|
|
383
|
+
|
|
384
|
+
`icon`, `prepend:icon` and `append:icon` belong to the main button, as on
|
|
385
|
+
`BbButton`, and so do the slots of the same names: `#prepend:icon="{ loading,
|
|
386
|
+
activeLink }"` swaps its glyph with its states, inside its `icon` part. The
|
|
387
|
+
toggle keeps its chevron (`toggle:icon` above).
|
|
388
|
+
|
|
382
389
|
### Selectable groups in a split button
|
|
383
390
|
|
|
384
391
|
Because it shares `BbDropdown`'s items, a split button can also host a
|
|
@@ -637,7 +644,7 @@ A `pt` value written in `<script>` (a constant, a preset, a wrapper's
|
|
|
637
644
|
|
|
638
645
|
| Prop | Type | Default | Required | Description |
|
|
639
646
|
| --- | --- | --- | --- | --- |
|
|
640
|
-
| `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: `footer`, `header`, `icon`, `input`, `item`, `itemDescription`, `itemIcon`, `itemText`, `main`, `panel`, `root`, `sheet`, `spinner`, `text`, `toggle`. States: `disabled`, `loading`, `open`, `selected`. 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 `BbDropdownButtonProps['pt']` (`PtValue` is not exported): § Typing `pt` in `<script>`. |
|
|
647
|
+
| `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: `footer`, `header`, `icon`, `input`, `item`, `itemDescription`, `itemIcon`, `itemText`, `main`, `panel`, `root`, `sheet`, `spinner`, `text`, `toggle`. States: `activeLink`, `disabled`, `exactActiveLink`, `loading`, `open`, `destructive`, `ghost`, `link`, `outline`, `primary`, `secondary`, `default`, `selected`. 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 `BbDropdownButtonProps['pt']` (`PtValue` is not exported): § Typing `pt` in `<script>`. |
|
|
641
648
|
| `activeClass` | `string \| undefined` | | | Class to apply when the link is active. |
|
|
642
649
|
| `adaptive` | `boolean \| undefined` | ``config.adaptive` (`true`)` | | On mobile (below `config.mobileMaxWidth`), renders the menu as a bottom sheet that drills into submenus one level at a time instead of hover flyouts; slots and selection are unchanged. Unset: the global `config.adaptive`. |
|
|
643
650
|
| `append:icon` | `string \| undefined` | | | Icon to be added on the right of the text. |
|
|
@@ -646,6 +653,7 @@ A `pt` value written in `<script>` (a constant, a preset, a wrapper's
|
|
|
646
653
|
| `block` | `boolean \| undefined` | `false` | | Displays the component as full width. |
|
|
647
654
|
| `cacheFor` | `string \| number \| (string \| number)[] \| undefined` | | | Inertia: how long a prefetched response stays fresh before it is re-fetched. A single duration, or `[staleAfter, expiresAfter]`. Typed platform-agnostically (matching BbButton) so the library's types never require `@inertiajs/vue3` to be installed. |
|
|
648
655
|
| `cacheTags` | `string \| string[] \| undefined` | | | Inertia: tags to file this visit's prefetch cache under, so a later request can invalidate the whole tagged group. |
|
|
656
|
+
| `closeOnSelect` | `boolean \| undefined` | `unset (close after a single-choice change)` | | Whether a selection closes the menu. Unset: a change in a single-choice group closes it (an untick too, at any depth); a `multiple` group stays open. `true`: every selection change closes it. `false`: none does. |
|
|
649
657
|
| `compact` | `boolean \| undefined` | `false` | | Compact density, the `BbSelect` ladder: flyout rows 28px → 24px, sheet rows 44px → 36px (a sheet row stays a touch target). The label size does not change. |
|
|
650
658
|
| `component` | `string \| undefined` | | | Inertia: the page component this visit resolves to. Rarely set by hand — the server normally decides it. |
|
|
651
659
|
| `data` | `object \| undefined` | | | Request payload forwarded to Inertia when navigating via `href` in an Inertia-enabled app. Ignored when not using Inertia. |
|
|
@@ -727,10 +735,19 @@ States are listed in precedence order: when two are on at once and their entries
|
|
|
727
735
|
|
|
728
736
|
| State | When it is on |
|
|
729
737
|
| --- | --- |
|
|
738
|
+
| `activeLink` | Component-wide while the main button is a link to the current page or one of its ancestors (its `activeClass` is on); also per node, on the entry parts: a menu entry whose link is. The weakest state. |
|
|
739
|
+
| `exactActiveLink` | Component-wide while the main button is a link to the current page itself (its `exactActiveClass` is on); also per node, on the entry parts. |
|
|
730
740
|
| `selected` | Per node, on the entry parts only (`item`, `itemText`, `itemIcon`, `itemDescription`): a selectable group's checked entry. `pt:root:selected` is a type error, not a silent no-op. |
|
|
731
741
|
| `disabled` | Component-wide while the control is `disabled`; also per node, on the entry parts: a menu entry that is disabled. |
|
|
732
742
|
| `open` | Component-wide: the menu is open. |
|
|
733
743
|
| `loading` | Component-wide: `loading` is on — the main button shows its spinner. |
|
|
744
|
+
| `destructive` | Per entry, on the entry parts: `variant: 'destructive'`. Below the real states, like every variant. |
|
|
745
|
+
| `ghost` | Component-wide: `variant="ghost"`. Below the real states, like every variant. |
|
|
746
|
+
| `link` | Component-wide: `variant="link"`. Below the real states, like every variant. |
|
|
747
|
+
| `outline` | Component-wide: `variant="outline"`. Below the real states, like every variant. |
|
|
748
|
+
| `primary` | Component-wide: `variant="primary"`. Merged after the part's base entry and before its states, so `disabled` / `loading` still win. |
|
|
749
|
+
| `secondary` | Component-wide: `variant="secondary"`. Below the real states, like every variant. |
|
|
750
|
+
| `default` | Per entry, on the entry parts: an entry with `variant: 'default'` or none. Merged after the part's base entry and before its states, so the real states still win. |
|
|
734
751
|
|
|
735
752
|
## Events
|
|
736
753
|
|
|
@@ -743,21 +760,24 @@ States are listed in precedence order: when two are on at once and their entries
|
|
|
743
760
|
|
|
744
761
|
## Slots
|
|
745
762
|
|
|
763
|
+
- `append:icon` — scope: `BbButtonIconSlotProps` `{ activeLink: boolean; exactActiveLink: boolean; pressed: boolean; loading: boolean; disabled: boolean }` — The main button's trailing icon, replacing `append:icon`.
|
|
746
764
|
- `default` — scope: `any` — The main button's label (falls back to `text`).
|
|
747
765
|
- `dropdown` — scope: `any` — Menu companions, forwarded into the dropdown: a `<BbDropdownGroup>` binding a group of `items` by id. A `#dropdown` slot keeps the toggle even with no `items`.
|
|
748
|
-
- `empty` — scope: `BbDropdownPlaceholderSlotProps` `{ groupId?: string; text: string; error?: unknown }` — Replaces the default "no data" placeholder row shown in a pipeline group that resolved to no items. Rendered once per empty group. Forwarded to the underlying `BbDropdown`.
|
|
766
|
+
- `empty` — scope: `BbDropdownPlaceholderSlotProps` `{ groupId?: string; query: string; text: string; error?: unknown }` — Replaces the default "no data" placeholder row shown in a pipeline group that resolved to no items. Rendered once per empty group. Forwarded to the underlying `BbDropdown`.
|
|
749
767
|
- `footer` — scope: `BbDropdownButtonEdgeSlotProps` `{ disabled?: boolean; open: boolean; placement: Placement \| "cursor" }` — Content pinned to the bottom of the dropdown panel, outside the scroll area.
|
|
750
768
|
- `header` — scope: `BbDropdownButtonEdgeSlotProps` `{ disabled?: boolean; open: boolean; placement: Placement \| "cursor" }` — Content pinned to the top of the dropdown panel, outside the scroll area.
|
|
769
|
+
- `icon` — scope: `BbButtonIconSlotProps` `{ activeLink: boolean; exactActiveLink: boolean; pressed: boolean; loading: boolean; disabled: boolean }` — The main button's icon, replacing the `icon` prop; inside its `icon` part (`pt:icon`, `--icon-size`, the loading spinner), with its states.
|
|
751
770
|
- `item:append` — scope: `BbDropdownButtonItemSlotProps` `{ disabled?: boolean; index: number; item: InternalItem; open: boolean; placement: Placement \| "cursor"; label: string }` — The trailing region of every menu row, replacing its `append:icon`; the submenu chevron and the check on a selected row take its place (BbDropdown's rules).
|
|
752
771
|
- `item:prepend` — scope: `BbDropdownButtonItemSlotProps` `{ disabled?: boolean; index: number; item: InternalItem; open: boolean; placement: Placement \| "cursor"; label: string }` — The leading region of every menu row, replacing its `prepend:icon` (BbDropdown's rules).
|
|
753
|
-
- `loading` — scope: `BbDropdownPlaceholderSlotProps` `{ groupId?: string; text: string; error?: unknown }` — Replaces the default loading placeholder row shown in a pipeline group while its async items load. Rendered once per loading group. Forwarded to the underlying `BbDropdown`.
|
|
754
|
-
-
|
|
772
|
+
- `loading` — scope: `BbDropdownPlaceholderSlotProps` `{ groupId?: string; query: string; text: string; error?: unknown }` — Replaces the default loading placeholder row shown in a pipeline group while its async items load. Rendered once per loading group. Forwarded to the underlying `BbDropdown`.
|
|
773
|
+
- `prepend:icon` — scope: `BbButtonIconSlotProps` `{ activeLink: boolean; exactActiveLink: boolean; pressed: boolean; loading: boolean; disabled: boolean }` — The main button's leading icon, replacing `prepend:icon`.
|
|
774
|
+
- `#<value>` (named from data) — scope: `BbDropdownItemSlotProps` — One row's content (label and description), by its value; in a fetched group, by its resolved `itemValue`. Reserved names (their slot is one of this component's own, so an item value or column key spelled like them is an error): `default`, `dropdown`, `empty`, `footer`, `header`, `icon`, `item`, `loading`.
|
|
755
775
|
- `#<value>:prepend` (named from data) — scope: `BbDropdownItemSlotProps` — One row's leading region; replaces its `prepend:icon`.
|
|
756
776
|
- `#<value>:append` (named from data) — scope: `BbDropdownItemSlotProps` — One row's trailing region; replaces its `append:icon` and its submenu chevron. The check takes its place on the selected row.
|
|
757
777
|
- `#<groupId>:item` (named from data) — scope: `BbDropdownItemSlotProps` — The content of every row of that group, and no other; a row's own `#<value>` still wins.
|
|
758
778
|
- `#<groupId>:item:prepend` (named from data) — scope: `BbDropdownItemSlotProps` — The leading region of every row of that group — e.g. an avatar per record, drawn from `item.meta`, while other rows keep their `prepend:icon`.
|
|
759
779
|
- `#<groupId>:item:append` (named from data) — scope: `BbDropdownItemSlotProps` — The trailing region of every row of that group; replaces their `append:icon`. The check takes its place on the selected row.
|
|
760
|
-
- `#<groupId>` (named from data) — scope: `BbDropdownItemSlotProps` — That group's title line (the group is passed as `item`, `groupTitle` is `true`). Reserved names (their slot is one of this component's own, so an item value or column key spelled like them is an error): `default`, `dropdown`, `empty`, `footer`, `header`, `item`, `loading`.
|
|
780
|
+
- `#<groupId>` (named from data) — scope: `BbDropdownItemSlotProps` — That group's title line (the group is passed as `item`, `groupTitle` is `true`). Reserved names (their slot is one of this component's own, so an item value or column key spelled like them is an error): `default`, `dropdown`, `empty`, `footer`, `header`, `icon`, `item`, `loading`.
|
|
761
781
|
- `#<groupId>:prepend` (named from data) — scope: `BbDropdownItemSlotProps` — The leading region of that group's title line.
|
|
762
782
|
- `#<groupId>:append` (named from data) — scope: `BbDropdownItemSlotProps` — The trailing region of that group's title line.
|
|
763
783
|
|
|
@@ -771,11 +791,11 @@ States are listed in precedence order: when two are on at once and their entries
|
|
|
771
791
|
- Listed nodes are the ones `BbDropdownButton`'s API reaches or that declare a documented CSS variable; the rest fold into "also mounts". The complete tree, repeats and undocumented locals included, is `manifest/components/BbDropdownButton.tree.json`.
|
|
772
792
|
|
|
773
793
|
- `BbDropdownButton` _(this component)_ — hands `BbButton` the pt map `{ main: 'root', icon: 'icon', spinner: 'spinner', text: 'text' }` (ours → theirs); hands `BbDropdown` the pt map `{ panel: 'panel', sheet: 'sheet', header: 'header', footer: 'footer', input: 'input', item: 'item', itemText: 'itemText', itemIcon: 'itemIcon', itemDescription: 'itemDescription' }` (ours → theirs); hands `BbButton` the pt map `{ toggle: 'root' }` (ours → theirs)
|
|
774
|
-
- `BbButton` _(public — [contract](./BbButton.md))_ — its own pt parts (`BbButton`): `root` → `BbBaseButton`, `spinner` → `BbSpinner`, `icon` → `BbIcon`, `text` → `span.bb-button__text`; documented CSS variables: `--h-xs`, `--h`, `--icon-size`, `--px`, `--fs`, `--r`, `--gap`, `--bg`, `--bg-hover`, `--bg-pressed`, `--fg`, `--border-color`, `--ring-color`, `--ring-size`, `--bw`, `--fg-hover`, `--border-hover`, `--fg-pressed`, `--border-pressed`, `--bg-disabled`, `--fg-disabled`, `--border-disabled`, `--opacity-disabled`, `--elev-tier`, `--elev`; also mounts `BbIcon`, `BbSpinner`
|
|
794
|
+
- `BbButton` _(public — [contract](./BbButton.md))_ — its own pt parts (`BbButton`): `root` → `BbBaseButton`, `spinner` → `BbSpinner`, `icon` → `span.bb-button__icon`, `icon` → `BbIcon`, `icon` → `span.bb-button__prepend-icon`, `text` → `span.bb-button__text`, `icon` → `span.bb-button__append-icon`; documented CSS variables: `--h-xs`, `--h`, `--icon-size`, `--px`, `--fs`, `--r`, `--gap`, `--bg`, `--bg-hover`, `--bg-pressed`, `--fg`, `--border-color`, `--ring-color`, `--ring-size`, `--bw`, `--fg-hover`, `--border-hover`, `--fg-pressed`, `--border-pressed`, `--bg-disabled`, `--fg-disabled`, `--border-disabled`, `--opacity-disabled`, `--elev-tier`, `--elev`; also mounts `BbIcon`, `BbSpinner`
|
|
775
795
|
- `BbBaseButton` _(public — [contract](./BbBaseButton.md))_ — its own pt parts (`BbBaseButton`): `root` → `RouterComponent`, `root` → `a`, `root` → `component`; also mounts `RouterComponent`
|
|
776
796
|
- `BbDropdown` _(public — [contract](./BbDropdown.md))_ — its own pt parts (`BbDropdown`): `panel` → `CommonPopover`, `root` → `CommonPopover`, `header` → `div.bb-dropdown__header`, `list` → `span.bb-dropdown__list`, `footer` → `div.bb-dropdown__footer`; documented CSS variables: `--menu-inset`; also mounts `CommonPopover`, `DropdownPipelineResolver`
|
|
777
797
|
- `BbDropdownList` _(internal — not importable, reach it through `BbDropdown`)_ — also mounts `BbIcon`, `ErrorIcon`, `CommonPopover`, `BbDropdownList`
|
|
778
|
-
- `BbBadge` _(public — [contract](./BbBadge.md))_ — its own pt parts (`BbBadge`): `spinner` → `BbSpinner`, `icon` → `BbIcon`, `clear` → `button.bb-badge__clear`; documented CSS variables: `--bg`, `--fg`, `--bw`, `--ring-color`, `--ring-size`, `--min-size-md`, `--min-size`, `--elev`, `--r`, `--fs`, `--icon-size`, `--gap`, `--px`, `--clear-size`, `--bg-disabled`, `--fg-disabled`, `--border-disabled`, `--pad-left`; also mounts `BbIcon`, `BbSpinner`, `BadgeBodyContent`
|
|
798
|
+
- `BbBadge` _(public — [contract](./BbBadge.md))_ — its own pt parts (`BbBadge`): `spinner` → `BbSpinner`, `icon` → `span.bb-badge__append-icon`, `icon` → `BbIcon`, `clear` → `button.bb-badge__clear`; documented CSS variables: `--bg`, `--fg`, `--bw`, `--ring-color`, `--ring-size`, `--min-size-md`, `--min-size`, `--elev`, `--r`, `--fs`, `--icon-size`, `--gap`, `--px`, `--clear-size`, `--bg-disabled`, `--fg-disabled`, `--border-disabled`, `--pad-left`; also mounts `BbIcon`, `BbSpinner`, `BadgeBodyContent`
|
|
779
799
|
- `AdaptiveDropdown` _(internal — not importable, reach it through `BbDropdown`)_ — hands `BbOffCanvas` the pt map `{ header: 'header', footer: 'footer', panel: 'root', sheet: 'root' }` (ours → theirs); also mounts `BbSmoothHeight`, `BbButton`, `BbDropdownList`
|
|
780
800
|
- `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__content`, `footer` → `div.bb-offcanvas__footer`; documented CSS variables: `--stack-x`, `--snap-y`, `--stack-fill`, `--stack-transition-duration`, `--px`, `--handle-w`, `--handle-h`, `--handle-bg`, `--safe-top`, `--close-size`
|
|
781
801
|
- `CloseButton` _(internal — not importable, reach it through `BbOffCanvas`)_ — documented CSS variables: `--size`, `--p`
|
package/dist/ai/BbForm.md
CHANGED
|
@@ -507,14 +507,16 @@ on the problem instead of hunting for it. A field inside a `v-show`-hidden
|
|
|
507
507
|
section, an `inert` subtree or `hidden` content is skipped; a failing path with
|
|
508
508
|
no field mounted has nothing to focus.
|
|
509
509
|
|
|
510
|
-
It also emits **`invalid`** with `{ errors, values }`:
|
|
511
|
-
failing path to all its messages, `{ [path]: string[] }` —
|
|
512
|
-
keys as the form's `errors` (`address.city`, `lines.0.qty`)
|
|
513
|
-
paths that are not on screen. That is what a wizard needs to
|
|
514
|
-
step holding the error; focus runs after your handler, so the
|
|
515
|
-
came back on screen is the one that gets it. A handler that
|
|
516
|
-
(to an [error summary](#a-summary-of-the-problems-at-the-top-of-a-long-form),
|
|
517
|
-
say) keeps it: the form leaves focus alone then.
|
|
510
|
+
It also emits **`invalid`** with `{ errors, values, unmatched, source }`:
|
|
511
|
+
`errors` maps every failing path to all its messages, `{ [path]: string[] }` —
|
|
512
|
+
the same shape and keys as the form's `errors` (`address.city`, `lines.0.qty`)
|
|
513
|
+
— including the paths that are not on screen. That is what a wizard needs to
|
|
514
|
+
jump to the step holding the error; focus runs after your handler, so the
|
|
515
|
+
field that just came back on screen is the one that gets it. A handler that
|
|
516
|
+
moves focus itself (to an [error summary](#a-summary-of-the-problems-at-the-top-of-a-long-form),
|
|
517
|
+
say) keeps it: the form leaves focus alone then. `unmatched` holds the paths
|
|
518
|
+
no field claims (the same shape as `unmatchedErrors`), `{}` when every error
|
|
519
|
+
has its field.
|
|
518
520
|
|
|
519
521
|
```vue
|
|
520
522
|
<BbForm
|
|
@@ -529,13 +531,38 @@ say) keeps it: the form leaves focus alone then.
|
|
|
529
531
|
> Behaviour change in 3.0.0-beta.41: a failed submit used to leave focus where
|
|
530
532
|
> it was (usually on the submit button).
|
|
531
533
|
|
|
532
|
-
**Server errors move focus the same way
|
|
533
|
-
field that got an error and is on screen,
|
|
534
|
-
the map). It holds back when focus is no
|
|
535
|
-
moved on to something outside the form
|
|
536
|
-
has submitted the form yet and focus is
|
|
537
|
-
errors in its props). Keys that match no
|
|
538
|
-
nothing; `setErrors(map, { focus: false })`
|
|
534
|
+
**Server errors move focus the same way, and emit the same event.**
|
|
535
|
+
`setErrors(map)` focuses the first field that got an error and is on screen,
|
|
536
|
+
in page order (not the first key of the map). It holds back when focus is no
|
|
537
|
+
longer the form's: if the user has moved on to something outside the form
|
|
538
|
+
while the request ran, or if nobody has submitted the form yet and focus is
|
|
539
|
+
on the page (a page that opens with errors in its props). Keys that match no
|
|
540
|
+
field, and an empty map, move nothing; `setErrors(map, { focus: false })`
|
|
541
|
+
never moves it. Either way a non-empty map emits `invalid` first, with
|
|
542
|
+
`source: 'server'`, and so does a [`field-errors`](#the-pages-errors-object-field-errors)
|
|
543
|
+
value that brings messages. Errors a page loads with emit nothing: nobody
|
|
544
|
+
submitted. One `@invalid` handler then covers both answers (`source:
|
|
545
|
+
'submit'` for a failed submit).
|
|
546
|
+
|
|
547
|
+
Errors no field shows (a 422 keyed on `assignments.0.id`, drawn by hand in
|
|
548
|
+
its row) get no focus from the form: bring their row on screen in the
|
|
549
|
+
handler, and the form leaves focus where you put it.
|
|
550
|
+
|
|
551
|
+
```ts
|
|
552
|
+
import type { BbFormInvalidPayload } from 'bitboss-ui';
|
|
553
|
+
|
|
554
|
+
const onInvalid = ({ unmatched }: BbFormInvalidPayload) => {
|
|
555
|
+
const key = Object.keys(unmatched).find((path) =>
|
|
556
|
+
path.startsWith('assignments.')
|
|
557
|
+
);
|
|
558
|
+
if (!key) return;
|
|
559
|
+
const row = document.querySelector<HTMLElement>(
|
|
560
|
+
`[data-row="${key.split('.')[1]}"]`
|
|
561
|
+
);
|
|
562
|
+
row?.scrollIntoView({ block: 'center' });
|
|
563
|
+
row?.focus({ preventScroll: true }); // a row with tabindex="-1"
|
|
564
|
+
};
|
|
565
|
+
```
|
|
539
566
|
|
|
540
567
|
### A summary of the problems at the top of a long form
|
|
541
568
|
|
|
@@ -752,10 +779,10 @@ How it works:
|
|
|
752
779
|
empties on a successful one, never while the user types: fixing one field
|
|
753
780
|
does not reshuffle the box above them. The messages under the fields
|
|
754
781
|
update as usual.
|
|
755
|
-
- **Server errors
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
782
|
+
- **Server errors list the same way.** A 422 through `setErrors` or
|
|
783
|
+
`field-errors` emits `invalid` too (`source: 'server'`), so the same handler
|
|
784
|
+
builds the box from the server's answer. A path no field has (in
|
|
785
|
+
`unmatched`) is an item with no field to focus.
|
|
759
786
|
|
|
760
787
|
**When not to use it: a short form**, where every field is on screen. A
|
|
761
788
|
failed submit already focuses the first invalid field and every message sits
|
|
@@ -1357,6 +1384,11 @@ async function save(values: Record<string, unknown>) {
|
|
|
1357
1384
|
}
|
|
1358
1385
|
```
|
|
1359
1386
|
|
|
1387
|
+
A value that brings a message the object did not have (or comes back after a
|
|
1388
|
+
new submit) is an answer: it emits `invalid` with `source: 'server'` and
|
|
1389
|
+
moves focus like `setErrors`. The same content passed again, a message
|
|
1390
|
+
leaving, and the object the page loads with do neither.
|
|
1391
|
+
|
|
1360
1392
|
##### A message of your own that comes and goes
|
|
1361
1393
|
|
|
1362
1394
|
The object does not have to come from a server. A check that spans fields is
|
|
@@ -1514,8 +1546,9 @@ const save = async (values: Record<string, unknown>) => {
|
|
|
1514
1546
|
instead: it shows while its key holds a message and goes the moment it
|
|
1515
1547
|
does not. Calling `validate()` to wipe a `setErrors` message runs every
|
|
1516
1548
|
rule on every field, so it puts messages on fields the user never touched.
|
|
1517
|
-
- `setErrors`
|
|
1518
|
-
field on screen, like a failed submit
|
|
1549
|
+
- `setErrors` emits `invalid` (`source: 'server'`) for a non-empty map, then
|
|
1550
|
+
moves focus to the first failing field on screen, like a failed submit
|
|
1551
|
+
(`{ focus: false }` opts out of the focus, not the event; see
|
|
1519
1552
|
[A failed submit focuses the first invalid field](#a-failed-submit-focuses-the-first-invalid-field)).
|
|
1520
1553
|
|
|
1521
1554
|
#### Fields on a step you left, and the step badge
|
|
@@ -1833,7 +1866,7 @@ marker stays consistent with the rules.
|
|
|
1833
1866
|
|
|
1834
1867
|
## Events
|
|
1835
1868
|
|
|
1836
|
-
- `invalid` — `(payload: BbFormInvalidPayload): void` — Fired when a submit fails validation
|
|
1869
|
+
- `invalid` — `(payload: BbFormInvalidPayload): void` — Fired when a submit fails validation (`source: 'submit'`) or server errors land (`'server'`: `setErrors()`, a new `field-errors` message), before the form's own focus; a handler that moves focus keeps it. `unmatched`: the paths no field claims.
|
|
1837
1870
|
- `submit` — `(values: BbFormSubmitValues<S>, meta: BbFormSubmitMeta): void` — Fired only when every field passes. Carries the values — with a schema, its parsed OUTPUT (transforms and coercions applied), typed from it.
|
|
1838
1871
|
|
|
1839
1872
|
## Slots
|