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