bitboss-ui 3.0.0-beta.21 → 3.0.0-beta.22
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 +55 -3
- package/bin/bitboss-ui-mcp.mjs +419 -9
- package/bin/bitboss-ui.mjs +293 -22
- package/dist/ai/BbAccordion.md +21 -23
- package/dist/ai/BbAlert.md +6 -12
- package/dist/ai/BbAvatar.md +60 -24
- package/dist/ai/BbBadge.md +12 -20
- package/dist/ai/BbBaseButton.md +14 -16
- package/dist/ai/BbBaseCheckboxIcon.md +6 -10
- package/dist/ai/BbBaseRadioIcon.md +6 -10
- package/dist/ai/BbBaseSwitchIcon.md +5 -9
- package/dist/ai/BbBreadcrumbs.md +23 -34
- package/dist/ai/BbButton.md +35 -47
- package/dist/ai/BbCheckbox.md +21 -37
- package/dist/ai/BbCheckboxGroup.md +13 -13
- package/dist/ai/BbCollapsible.md +14 -26
- package/dist/ai/BbColorInput.md +13 -23
- package/dist/ai/BbColorPalette.md +23 -35
- package/dist/ai/BbConfirm.md +17 -32
- package/dist/ai/BbDatePickerInput.md +15 -21
- package/dist/ai/BbDialog.md +159 -62
- package/dist/ai/BbDropdown.md +21 -25
- package/dist/ai/BbDropdownButton.md +13 -30
- package/dist/ai/BbDropzone.md +9 -11
- package/dist/ai/BbIcon.md +44 -33
- package/dist/ai/BbIndicator.md +2 -2
- package/dist/ai/BbNumberInput.md +18 -20
- package/dist/ai/BbOffCanvas.md +42 -42
- package/dist/ai/BbPagination.md +21 -23
- package/dist/ai/BbPopover.md +15 -17
- package/dist/ai/BbProgress.md +40 -51
- package/dist/ai/BbRadio.md +9 -9
- package/dist/ai/BbRadioGroup.md +7 -11
- package/dist/ai/BbRating.md +8 -12
- package/dist/ai/BbSelect.md +32 -36
- package/dist/ai/BbSelectPopover.md +19 -31
- package/dist/ai/BbSlider.md +15 -19
- package/dist/ai/BbSmoothHeight.md +16 -31
- package/dist/ai/BbSpinner.md +118 -74
- package/dist/ai/BbSwitch.md +25 -18
- package/dist/ai/BbSwitchGroup.md +9 -14
- package/dist/ai/BbTable.md +102 -55
- package/dist/ai/BbTabs.md +59 -82
- package/dist/ai/BbTag.md +12 -23
- package/dist/ai/BbTextInput.md +20 -26
- package/dist/ai/BbTextarea.md +28 -34
- package/dist/ai/BbToast.md +14 -34
- package/dist/ai/BbTooltip.md +22 -20
- package/dist/ai/BbTree.md +46 -72
- package/dist/ai/changelog.json +169 -62
- package/dist/ai/components.json +1467 -9
- package/dist/ai/composables/useConfirm.md +5 -2
- package/dist/ai/composables/useToast.md +4 -2
- package/dist/ai/guides/agent-contract.md +7 -4
- package/dist/ai/guides/ai-router.md +37 -22
- package/dist/ai/guides/component-picker.md +23 -18
- package/dist/ai/guides/design-language.md +141 -13
- package/dist/ai/guides/design-tokens.md +29 -4
- package/dist/ai/guides/icons-policy.md +46 -21
- package/dist/ai/guides/installation-and-plugin-setup.md +253 -17
- package/dist/ai/guides/migration/components/bb-rating.md +26 -1
- package/dist/ai/guides/migration/components/bb-tooltip.md +18 -0
- package/dist/ai/guides/migration/v2-to-v3.md +50 -23
- package/dist/ai/index.md +1 -1
- package/dist/ai/recipes/inertia/approvals-inbox.md +3 -3
- package/dist/ai/recipes/inertia/inline-edit-workspace.md +2 -2
- package/dist/ai/recipes/inertia/onboarding.md +2 -2
- package/dist/ai/recipes/inertia/ownership-atlas.md +6 -6
- package/dist/ai/recipes/inertia/record-form.md +5 -5
- package/dist/ai/recipes/inertia/records-workspace.md +4 -4
- package/dist/ai/recipes/inertia/upload-center.md +6 -6
- package/dist/ai/recipes/inertia/wizard-form.md +5 -5
- package/dist/ai/recipes/nuxt/approvals-inbox.md +3 -3
- package/dist/ai/recipes/nuxt/inline-edit-workspace.md +2 -2
- package/dist/ai/recipes/nuxt/onboarding.md +2 -2
- package/dist/ai/recipes/nuxt/record-form.md +5 -5
- package/dist/ai/recipes/nuxt/records-workspace.md +4 -4
- package/dist/ai/recipes/nuxt/upload-center.md +6 -6
- package/dist/ai/recipes/nuxt/wizard-form.md +5 -5
- package/dist/ai/recipes/vue/approvals-inbox.md +3 -3
- package/dist/ai/recipes/vue/inline-edit-workspace.md +2 -2
- package/dist/ai/recipes/vue/onboarding.md +2 -2
- package/dist/ai/recipes/vue/record-form.md +10 -10
- package/dist/ai/recipes/vue/records-workspace.md +4 -4
- package/dist/ai/recipes/vue/upload-center.md +6 -6
- package/dist/ai/recipes/vue/wizard-form.md +5 -5
- package/dist/ai/source/BbBadge.md +1 -1
- package/dist/ai/source/BbBaseCheckbox.md +1 -1
- package/dist/ai/source/BbBaseDatePicker.md +5 -5
- package/dist/ai/source/BbBaseDatePickerInput.md +2 -2
- package/dist/ai/source/BbBaseRadio.md +1 -1
- package/dist/ai/source/BbBaseRating.md +5 -5
- package/dist/ai/source/BbBaseSelect.md +1 -1
- package/dist/ai/source/BbBaseSlider.md +5 -5
- package/dist/ai/source/BbBaseSwitch.md +1 -1
- package/dist/ai/source/BbBaseTimePickerInput.md +1 -1
- package/dist/ai/source/BbBreadcrumbs.md +20 -1
- package/dist/ai/source/BbButton.md +2 -2
- package/dist/ai/source/BbDialog.md +39 -8
- package/dist/ai/source/BbDropdown.md +1 -1
- package/dist/ai/source/BbDropzone.md +5 -5
- package/dist/ai/source/BbIcon.md +23 -10
- package/dist/ai/source/BbOffCanvas.md +50 -28
- package/dist/ai/source/BbPagination.md +2 -2
- package/dist/ai/source/BbPopover.md +12 -1
- package/dist/ai/source/BbSelectPopover.md +45 -7
- package/dist/ai/source/BbSpinner.md +2 -2
- package/dist/ai/source/BbTable.md +11 -11
- package/dist/ai/source/BbTooltip.md +57 -10
- package/dist/ai/source/ChipsBox.md +1 -1
- package/dist/ai/source/CommaBox.md +1 -1
- package/dist/ai/source/GuidesComponent.md +14 -7
- package/dist/ai/source/OptionsContainer.md +1 -1
- package/dist/components/BbBadge/BadgeBodyContent.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/components/BbBadge/BbBadge.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/components/BbBaseCheckbox/BbBaseCheckbox.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/components/BbBaseDatePicker/BbBaseDatePicker.vue_vue_type_script_setup_true_lang.js +4 -4
- package/dist/components/BbBaseDatePicker/BbBaseDatePickerInputDaySelector.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/components/BbBaseDatePickerInput/BbBaseDatePickerInput.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/components/BbBaseInputContainer/BbBaseInputContainer.vue.d.ts +1 -1
- package/dist/components/BbBaseRadio/BbBaseRadio.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/components/BbBaseRating/BbBaseRating.vue_vue_type_script_setup_true_lang.js +3 -3
- package/dist/components/BbBaseSelect/BbBaseSelect.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/components/BbBaseSlider/BbBaseSlider.vue_vue_type_script_setup_true_lang.js +3 -3
- package/dist/components/BbBaseSwitch/BbBaseSwitch.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/components/BbBaseTimePickerInput/BbBaseTimePickerInput.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/components/BbBreadcrumbs/BbBreadcrumbs.vue_vue_type_script_setup_true_lang.js +71 -71
- package/dist/components/BbButton/BbButton.vue_vue_type_script_setup_true_lang.js +2 -2
- package/dist/components/BbDialog/BbDialog.vue_vue_type_script_setup_true_lang.js +102 -97
- package/dist/components/BbDropdown/AdaptiveDropdown.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/components/BbDropdown/BbDropdown.vue_vue_type_script_setup_true_lang.js +58 -58
- package/dist/components/BbDropzone/BbDropzone.vue_vue_type_script_setup_true_lang.js +2 -2
- package/dist/components/BbIcon/BbIcon.vue_vue_type_script_setup_true_lang.js +33 -35
- package/dist/components/BbIcon/iconCache.d.ts +30 -0
- package/dist/components/BbIcon/iconCache.js +21 -3
- package/dist/components/BbOffCanvas/BbOffCanvas.vue_vue_type_script_setup_true_lang.js +57 -56
- package/dist/components/BbPagination/BbPagination.vue_vue_type_script_setup_true_lang.js +2 -2
- package/dist/components/BbPopover/BbPopover.vue_vue_type_script_setup_true_lang.js +138 -138
- package/dist/components/BbSelectPopover/BbSelectPopover.vue_vue_type_script_setup_true_lang.js +43 -43
- package/dist/components/BbSpinner/BbSpinner.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/components/BbSpinner/types.d.ts +1 -1
- package/dist/components/BbTable/BbTable.vue_vue_type_script_setup_true_lang.js +8 -8
- package/dist/components/BbTable/BbTableDataRow.js +2 -2
- package/dist/components/BbToast/BbToastRegion.vue_vue_type_script_setup_true_lang.js +62 -62
- package/dist/components/BbTooltip/BbTooltip.vue_vue_type_script_setup_true_lang.js +81 -78
- package/dist/components/BbTooltip/types.d.ts +8 -1
- package/dist/components/ChipsBox/ChipsBox.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/components/CommaBox/CommaBox.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/components/OptionsContainer/OptionsContainer.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/composables/useConfirm.d.ts +22 -0
- package/dist/composables/useConfirm.js +43 -40
- package/dist/composables/useSafeAreaInternal.js +1 -1
- package/dist/composables/useToast.d.ts +16 -0
- package/dist/composables/useToast.js +20 -16
- package/dist/composables/useViewportWidth.d.ts +20 -6
- package/dist/composables/useViewportWidth.js +8 -7
- package/dist/icon-scan.d.ts +276 -0
- package/dist/icon-scan.js +485 -0
- package/dist/icons-whitelist.d.ts +5 -4
- package/dist/llms-full.txt +1979 -1527
- package/dist/llms-medium.txt +461 -74
- package/dist/llms.txt +1 -1
- package/dist/nuxt.js +10 -7
- package/dist/plugin.js +1 -0
- package/dist/runtime/nuxt-plugin.js +2 -1
- package/dist/styles.css +1 -1
- package/dist/types/Config.d.ts +18 -0
- package/dist/utils/cssLayers.d.ts +91 -0
- package/dist/utils/cssLayers.js +43 -0
- package/dist/utils/injectLibraryStyles.d.ts +3 -1
- package/dist/utils/injectLibraryStyles.js +24 -23
- package/dist/vite-plugin.d.ts +74 -11
- package/dist/vite.js +292 -253
- package/llms.txt +1 -1
- package/package.json +7 -5
- package/scripts/lib/ensure-manifest.mjs +28 -5
- package/scripts/lib/eslint-plugin.d.ts +35 -0
- package/scripts/lib/eslint-plugin.mjs +299 -3
- package/scripts/lib/hand-roll-hints.mjs +50 -6
- package/scripts/lib/html-attributes.mjs +42 -0
- package/scripts/lib/mcp-config.mjs +38 -34
- package/scripts/lib/public-type-exports.mjs +246 -0
- package/scripts/lib/validate-bb-markup.mjs +205 -12
package/dist/ai/BbSpinner.md
CHANGED
|
@@ -21,7 +21,7 @@ spinner, or vice-versa — `BbProgress` has no indeterminate mode (`null` render
|
|
|
21
21
|
an empty bar), so this component **is** the library's indeterminate state.
|
|
22
22
|
|
|
23
23
|
Two props, no slots, no events: `size` (icon scale) and optional `label` (an
|
|
24
|
-
|
|
24
|
+
visually-hidden status announcement). Show the spinner with `v-if` while loading, remove
|
|
25
25
|
it when done.
|
|
26
26
|
|
|
27
27
|
**An indeterminate wait**
|
|
@@ -47,14 +47,27 @@ earlier:
|
|
|
47
47
|
<span class="import-card__title">Import contacts</span>
|
|
48
48
|
<span class="import-card__meta">contacts.csv · 1,284 rows</span>
|
|
49
49
|
</div>
|
|
50
|
-
<
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
50
|
+
<div class="import-card__actions">
|
|
51
|
+
<BbButton
|
|
52
|
+
:disabled="phase !== 'idle' && phase !== 'done'"
|
|
53
|
+
prepend:icon="lucide:upload"
|
|
54
|
+
variant="outline"
|
|
55
|
+
@click="onImport"
|
|
56
|
+
>
|
|
57
|
+
Import
|
|
58
|
+
</BbButton>
|
|
59
|
+
<!-- Demo control: advances the job one step per click. In an app
|
|
60
|
+
the parser and the upload drive these transitions; nothing
|
|
61
|
+
here ticks on its own. -->
|
|
62
|
+
<BbButton
|
|
63
|
+
v-if="phase === 'validating' || phase === 'uploading'"
|
|
64
|
+
prepend:icon="lucide:step-forward"
|
|
65
|
+
variant="ghost"
|
|
66
|
+
@click="onAdvance"
|
|
67
|
+
>
|
|
68
|
+
{{ phase === 'validating' ? 'Validation done' : 'Next chunk' }}
|
|
69
|
+
</BbButton>
|
|
70
|
+
</div>
|
|
58
71
|
</div>
|
|
59
72
|
|
|
60
73
|
<div
|
|
@@ -89,20 +102,19 @@ const phase = ref<Phase>('idle');
|
|
|
89
102
|
const progress = ref(0);
|
|
90
103
|
|
|
91
104
|
const onImport = () => {
|
|
105
|
+
// Parsing + validating the file: duration unknown → spinner.
|
|
92
106
|
phase.value = 'validating';
|
|
93
107
|
progress.value = 0;
|
|
94
|
-
|
|
95
|
-
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
const onAdvance = () => {
|
|
111
|
+
if (phase.value === 'validating') {
|
|
112
|
+
// Rows counted from here on → the bar takes over.
|
|
96
113
|
phase.value = 'uploading';
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
clearInterval(timer);
|
|
102
|
-
phase.value = 'done';
|
|
103
|
-
}
|
|
104
|
-
}, 90);
|
|
105
|
-
}, 350);
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
progress.value = Math.min(progress.value + 25, 100);
|
|
117
|
+
if (progress.value === 100) phase.value = 'done';
|
|
106
118
|
};
|
|
107
119
|
</script>
|
|
108
120
|
|
|
@@ -125,6 +137,13 @@ const onImport = () => {
|
|
|
125
137
|
justify-content: space-between;
|
|
126
138
|
}
|
|
127
139
|
|
|
140
|
+
.import-card__actions {
|
|
141
|
+
align-items: center;
|
|
142
|
+
display: flex;
|
|
143
|
+
flex-shrink: 0;
|
|
144
|
+
gap: 6px;
|
|
145
|
+
}
|
|
146
|
+
|
|
128
147
|
.import-card__titles {
|
|
129
148
|
display: flex;
|
|
130
149
|
flex-direction: column;
|
|
@@ -185,13 +204,13 @@ internals.
|
|
|
185
204
|
|
|
186
205
|
```vue
|
|
187
206
|
<div class="flex items-center gap-4">
|
|
188
|
-
<span class="inline-flex items-center gap-2 text-
|
|
207
|
+
<span class="inline-flex items-center gap-2 text-(--bb-text-muted)">
|
|
189
208
|
<BbSpinner size="sm" /> Muted
|
|
190
209
|
</span>
|
|
191
|
-
<span class="inline-flex items-center gap-2 text-
|
|
210
|
+
<span class="inline-flex items-center gap-2 text-(--bb-primary)">
|
|
192
211
|
<BbSpinner size="sm" /> Brand
|
|
193
212
|
</span>
|
|
194
|
-
<span class="inline-flex items-center gap-2 text-
|
|
213
|
+
<span class="inline-flex items-center gap-2 text-(--bb-danger)">
|
|
195
214
|
<BbSpinner size="sm" /> Retrying…
|
|
196
215
|
</span>
|
|
197
216
|
</div>
|
|
@@ -225,15 +244,28 @@ panel body (and let the trigger button use its own `loading` prop):
|
|
|
225
244
|
<div class="results-panel">
|
|
226
245
|
<div class="results-panel__head">
|
|
227
246
|
<span class="results-panel__title">Invoices</span>
|
|
228
|
-
<
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
247
|
+
<div class="results-panel__actions">
|
|
248
|
+
<BbButton
|
|
249
|
+
:loading="loading"
|
|
250
|
+
prepend:icon="lucide:refresh-cw"
|
|
251
|
+
size="sm"
|
|
252
|
+
variant="outline"
|
|
253
|
+
@click="onRefresh"
|
|
254
|
+
>
|
|
255
|
+
Refresh
|
|
256
|
+
</BbButton>
|
|
257
|
+
<!-- Demo control: plays the response arriving. In an app the
|
|
258
|
+
fetch's own completion does this; nothing here ticks on its own. -->
|
|
259
|
+
<BbButton
|
|
260
|
+
v-if="loading"
|
|
261
|
+
prepend:icon="lucide:check"
|
|
262
|
+
size="sm"
|
|
263
|
+
variant="ghost"
|
|
264
|
+
@click="onResponse"
|
|
265
|
+
>
|
|
266
|
+
Deliver results
|
|
267
|
+
</BbButton>
|
|
268
|
+
</div>
|
|
237
269
|
</div>
|
|
238
270
|
|
|
239
271
|
<div v-if="loading" class="results-panel__status" role="status">
|
|
@@ -276,14 +308,15 @@ const loading = ref(false);
|
|
|
276
308
|
|
|
277
309
|
const onRefresh = () => {
|
|
278
310
|
loading.value = true;
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
311
|
+
};
|
|
312
|
+
|
|
313
|
+
const onResponse = () => {
|
|
314
|
+
invoices.value = [
|
|
315
|
+
{ id: 'INV-1045', customer: 'Umbrella', amount: '€5,120.00' },
|
|
316
|
+
{ id: 'INV-1044', customer: 'Hooli', amount: '€2,340.00' },
|
|
317
|
+
{ id: 'INV-1043', customer: 'Stark Industries', amount: '€8,900.00' },
|
|
318
|
+
];
|
|
319
|
+
loading.value = false;
|
|
287
320
|
};
|
|
288
321
|
</script>
|
|
289
322
|
|
|
@@ -306,6 +339,12 @@ const onRefresh = () => {
|
|
|
306
339
|
justify-content: space-between;
|
|
307
340
|
}
|
|
308
341
|
|
|
342
|
+
.results-panel__actions {
|
|
343
|
+
align-items: center;
|
|
344
|
+
display: flex;
|
|
345
|
+
gap: 6px;
|
|
346
|
+
}
|
|
347
|
+
|
|
309
348
|
.results-panel__title {
|
|
310
349
|
font-size: 14px;
|
|
311
350
|
font-weight: 500;
|
|
@@ -385,14 +424,21 @@ on the container makes the state audible to assistive tech, per the
|
|
|
385
424
|
|
|
386
425
|
<div class="pending-list__trail">
|
|
387
426
|
<span class="pending-list__role">{{ member.role }}</span>
|
|
388
|
-
<
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
427
|
+
<template v-if="pendingId === member.email">
|
|
428
|
+
<span class="pending-list__status" role="status">
|
|
429
|
+
<BbSpinner size="xs" />
|
|
430
|
+
Saving…
|
|
431
|
+
</span>
|
|
432
|
+
<!-- Demo control: plays the save response. In an app the
|
|
433
|
+
request's completion clears `pendingId`; nothing ticks. -->
|
|
434
|
+
<BbButton
|
|
435
|
+
aria-label="Mark as saved"
|
|
436
|
+
icon="lucide:check"
|
|
437
|
+
size="sm"
|
|
438
|
+
variant="ghost"
|
|
439
|
+
@click="onSaved"
|
|
440
|
+
/>
|
|
441
|
+
</template>
|
|
396
442
|
<BbButton
|
|
397
443
|
v-else
|
|
398
444
|
size="sm"
|
|
@@ -442,9 +488,10 @@ const pendingId = ref<string | null>(null);
|
|
|
442
488
|
|
|
443
489
|
const onSave = (email: string) => {
|
|
444
490
|
pendingId.value = email;
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
491
|
+
};
|
|
492
|
+
|
|
493
|
+
const onSaved = () => {
|
|
494
|
+
pendingId.value = null;
|
|
448
495
|
};
|
|
449
496
|
</script>
|
|
450
497
|
|
|
@@ -535,14 +582,15 @@ const onSave = (email: string) => {
|
|
|
535
582
|
<span class="section-shell__title">Revenue overview</span>
|
|
536
583
|
<span class="section-shell__meta">Last 30 days · Northwind</span>
|
|
537
584
|
</div>
|
|
585
|
+
<!-- Demo control: stands in for the request settling / being re-run.
|
|
586
|
+
In an app the fetch flips `loading`; nothing here ticks on its own. -->
|
|
538
587
|
<BbButton
|
|
539
|
-
:
|
|
540
|
-
prepend:icon="lucide:refresh-cw"
|
|
588
|
+
:prepend:icon="loading ? 'lucide:check' : 'lucide:refresh-cw'"
|
|
541
589
|
size="sm"
|
|
542
590
|
variant="outline"
|
|
543
|
-
@click="
|
|
591
|
+
@click="loading ? deliver() : reload()"
|
|
544
592
|
>
|
|
545
|
-
Reload
|
|
593
|
+
{{ loading ? 'Deliver data' : 'Reload' }}
|
|
546
594
|
</BbButton>
|
|
547
595
|
</div>
|
|
548
596
|
|
|
@@ -560,34 +608,30 @@ const onSave = (email: string) => {
|
|
|
560
608
|
</template>
|
|
561
609
|
|
|
562
610
|
<script setup lang="ts">
|
|
563
|
-
import {
|
|
611
|
+
import { ref } from 'vue';
|
|
564
612
|
import { BbButton, BbSpinner } from 'bitboss-ui';
|
|
565
613
|
|
|
566
614
|
type Stat = { label: string; value: string };
|
|
567
615
|
|
|
568
616
|
// First paint of an empty section: center a spinner with a line naming what is
|
|
569
|
-
// coming. A bare spinner in a blank region tells users nothing.
|
|
617
|
+
// coming. A bare spinner in a blank region tells users nothing. The example
|
|
618
|
+
// mounts IN that state — no timer resolves it; the button plays the response.
|
|
570
619
|
const stats = ref<Stat[]>([]);
|
|
571
620
|
const loading = ref(true);
|
|
572
621
|
|
|
573
|
-
const
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
{ label: 'Overdue', value: '€3,180' },
|
|
581
|
-
];
|
|
582
|
-
loading.value = false;
|
|
583
|
-
}, 800);
|
|
622
|
+
const deliver = () => {
|
|
623
|
+
stats.value = [
|
|
624
|
+
{ label: 'Collected', value: '€48,210' },
|
|
625
|
+
{ label: 'Outstanding', value: '€12,940' },
|
|
626
|
+
{ label: 'Overdue', value: '€3,180' },
|
|
627
|
+
];
|
|
628
|
+
loading.value = false;
|
|
584
629
|
};
|
|
585
630
|
|
|
586
|
-
const
|
|
587
|
-
|
|
631
|
+
const reload = () => {
|
|
632
|
+
stats.value = [];
|
|
633
|
+
loading.value = true;
|
|
588
634
|
};
|
|
589
|
-
|
|
590
|
-
onMounted(load);
|
|
591
635
|
</script>
|
|
592
636
|
|
|
593
637
|
<style scoped>
|
|
@@ -717,14 +761,14 @@ By default the spinner is decorative — no live region and no ARIA role. Pair i
|
|
|
717
761
|
with adjacent visible text (`Loading results…`) and put `role="status"` /
|
|
718
762
|
`aria-live="polite"` on the text container you control. When the spinner stands
|
|
719
763
|
alone (icon-only pending affordance), set `label` so the component wraps itself
|
|
720
|
-
in `role="status"` with that text rendered `sr-only
|
|
764
|
+
in `role="status"` with that text rendered visually hidden (`bb-sr-only`). Prefer `BbButton`'s
|
|
721
765
|
`loading` for action feedback since it wires up ARIA for you.
|
|
722
766
|
|
|
723
767
|
## Props
|
|
724
768
|
|
|
725
769
|
| Prop | Type | Default | Required | Description |
|
|
726
770
|
| --- | --- | --- | --- | --- |
|
|
727
|
-
| `label` | `string \| undefined` | | | Accessible loading announcement. When set, the spinner is wrapped in a `role="status"` element containing this text rendered `sr-only`, so screen readers announce the loading state. When omitted the markup is unchanged and the spinner is
|
|
771
|
+
| `label` | `string \| undefined` | | | Accessible loading announcement. When set, the spinner is wrapped in a `role="status"` element containing this text rendered `bb-sr-only`, so screen readers announce the loading state. When omitted the markup is unchanged and the spinner is… |
|
|
728
772
|
| `size` | `number \| ({ size?: any; } & string) \| keyof Sizes \| undefined` | `"md"` | | Defines the component size. Accepted values: - A key from the provided size map (`keyof T`), e.g. `'sm' \| 'md' \| 'lg'` - A custom CSS size string (e.g. `'20px'`, `'1.5rem'`, `'2em'`) - A number, typically interpreted as pixels by size par… |
|
|
729
773
|
|
|
730
774
|
## Events
|
package/dist/ai/BbSwitch.md
CHANGED
|
@@ -39,10 +39,10 @@ the switch has focus — pin it open with `persistent-hint`.
|
|
|
39
39
|
|
|
40
40
|
```vue
|
|
41
41
|
<template>
|
|
42
|
-
<div class="grid max-w-sm gap-3 rounded-
|
|
42
|
+
<div class="grid max-w-sm gap-3 rounded-(--bb-radius) border p-4">
|
|
43
43
|
<div class="flex flex-col gap-0.5">
|
|
44
44
|
<p class="text-sm font-medium">Account security</p>
|
|
45
|
-
<p class="text-xs text-
|
|
45
|
+
<p class="text-xs text-(--bb-text-muted)">
|
|
46
46
|
Preferences take effect as soon as you flip them.
|
|
47
47
|
</p>
|
|
48
48
|
</div>
|
|
@@ -88,10 +88,10 @@ state maps to. Handy when the switch drives an enum-like setting.
|
|
|
88
88
|
|
|
89
89
|
```vue
|
|
90
90
|
<template>
|
|
91
|
-
<div class="grid max-w-sm gap-2 rounded-
|
|
91
|
+
<div class="grid max-w-sm gap-2 rounded-(--bb-radius) border p-4">
|
|
92
92
|
<div class="flex flex-col gap-0.5">
|
|
93
93
|
<p class="text-sm font-medium">Profile visibility</p>
|
|
94
|
-
<p class="text-xs text-
|
|
94
|
+
<p class="text-xs text-(--bb-text-muted)">
|
|
95
95
|
Stores an enum string instead of a boolean.
|
|
96
96
|
</p>
|
|
97
97
|
</div>
|
|
@@ -102,7 +102,7 @@ state maps to. Handy when the switch drives an enum-like setting.
|
|
|
102
102
|
name="visibility"
|
|
103
103
|
true-value="public"
|
|
104
104
|
/>
|
|
105
|
-
<p class="text-xs text-
|
|
105
|
+
<p class="text-xs text-(--bb-text-muted)">
|
|
106
106
|
Stored value: <code>{{ visibility }}</code>
|
|
107
107
|
</p>
|
|
108
108
|
</div>
|
|
@@ -133,10 +133,10 @@ the user cannot queue conflicting toggles.
|
|
|
133
133
|
|
|
134
134
|
```vue
|
|
135
135
|
<template>
|
|
136
|
-
<div class="grid max-w-sm gap-2 rounded-
|
|
136
|
+
<div class="grid max-w-sm gap-2 rounded-(--bb-radius) border p-4">
|
|
137
137
|
<div class="flex flex-col gap-0.5">
|
|
138
138
|
<p class="text-sm font-medium">Workspace</p>
|
|
139
|
-
<p class="text-xs text-
|
|
139
|
+
<p class="text-xs text-(--bb-text-muted)">
|
|
140
140
|
Northwind Billing — flips save immediately and revert on failure.
|
|
141
141
|
</p>
|
|
142
142
|
</div>
|
|
@@ -151,7 +151,7 @@ the user cannot queue conflicting toggles.
|
|
|
151
151
|
<p v-if="error" class="text-xs text-red-600" data-testid="error">
|
|
152
152
|
{{ error }}
|
|
153
153
|
</p>
|
|
154
|
-
<p class="text-xs text-
|
|
154
|
+
<p class="text-xs text-(--bb-text-muted)" data-testid="status">
|
|
155
155
|
{{ saving ? 'Saving…' : maintenance ? 'Enabled' : 'Disabled' }}
|
|
156
156
|
</p>
|
|
157
157
|
</div>
|
|
@@ -233,10 +233,10 @@ its focus ring (style against `focusVisible`).
|
|
|
233
233
|
|
|
234
234
|
```vue
|
|
235
235
|
<template>
|
|
236
|
-
<div class="grid max-w-sm gap-2 rounded-
|
|
236
|
+
<div class="grid max-w-sm gap-2 rounded-(--bb-radius) border p-4">
|
|
237
237
|
<div class="flex flex-col gap-0.5">
|
|
238
238
|
<p class="text-sm font-medium">Appearance</p>
|
|
239
|
-
<p class="text-xs text-
|
|
239
|
+
<p class="text-xs text-(--bb-text-muted)">
|
|
240
240
|
The icon slot replaces the whole track — style checked state yourself.
|
|
241
241
|
</p>
|
|
242
242
|
</div>
|
|
@@ -291,10 +291,10 @@ a stage pill next to the flag name:
|
|
|
291
291
|
|
|
292
292
|
```vue
|
|
293
293
|
<template>
|
|
294
|
-
<div class="grid max-w-sm gap-3 rounded-
|
|
294
|
+
<div class="grid max-w-sm gap-3 rounded-(--bb-radius) border p-4">
|
|
295
295
|
<div class="flex flex-col gap-0.5">
|
|
296
296
|
<p class="text-sm font-medium">Feature flags</p>
|
|
297
|
-
<p class="text-xs text-
|
|
297
|
+
<p class="text-xs text-(--bb-text-muted)">
|
|
298
298
|
Workspace experiments for Northwind Billing.
|
|
299
299
|
</p>
|
|
300
300
|
</div>
|
|
@@ -365,16 +365,22 @@ const usageAnalytics = ref(true);
|
|
|
365
365
|
|
|
366
366
|
```vue
|
|
367
367
|
<template>
|
|
368
|
-
<div class="grid max-w-md gap-2 rounded-
|
|
368
|
+
<div class="grid max-w-md gap-2 rounded-(--bb-radius) border p-3">
|
|
369
369
|
<div class="flex flex-col gap-0.5 pb-1">
|
|
370
370
|
<p class="text-sm font-medium">Playback</p>
|
|
371
|
-
<p class="text-xs text-
|
|
371
|
+
<p class="text-xs text-(--bb-text-muted)">
|
|
372
372
|
Label-heavy rows with the control pinned to the trailing edge.
|
|
373
373
|
</p>
|
|
374
374
|
</div>
|
|
375
|
+
<!-- `reverse` puts the label first; the ratio pattern then reads in that
|
|
376
|
+
VISUAL order (label 6 : control 2 → 75% / 25%). The ratio alone
|
|
377
|
+
leaves the switch at the START of its track, a quarter-width in
|
|
378
|
+
from the edge — `input-position="right"` is what pins it to the
|
|
379
|
+
trailing edge. -->
|
|
375
380
|
<BbSwitch
|
|
376
381
|
v-model="autoplay"
|
|
377
382
|
direction="xxxxxx xx"
|
|
383
|
+
input-position="right"
|
|
378
384
|
label="Autoplay videos"
|
|
379
385
|
name="autoplay"
|
|
380
386
|
reverse
|
|
@@ -382,12 +388,13 @@ const usageAnalytics = ref(true);
|
|
|
382
388
|
<BbSwitch
|
|
383
389
|
v-model="captions"
|
|
384
390
|
direction="xxxxxx xx"
|
|
391
|
+
input-position="right"
|
|
385
392
|
label="Always show captions"
|
|
386
393
|
name="captions"
|
|
387
394
|
reverse
|
|
388
395
|
/>
|
|
389
396
|
<!-- A described row keeps the same trailing edge: `input-position`
|
|
390
|
-
applies on the description path too, and the switch
|
|
397
|
+
applies on the description path too, and the switch aligns with the
|
|
391
398
|
label's FIRST line rather than the centre of the two-line block. -->
|
|
392
399
|
<BbSwitch
|
|
393
400
|
v-model="downloads"
|
|
@@ -422,10 +429,10 @@ What a panel must not do is both.
|
|
|
422
429
|
|
|
423
430
|
```vue
|
|
424
431
|
<template>
|
|
425
|
-
<div class="grid max-w-md gap-3 rounded-
|
|
432
|
+
<div class="grid max-w-md gap-3 rounded-(--bb-radius) border p-4">
|
|
426
433
|
<div class="flex flex-col gap-0.5">
|
|
427
434
|
<p class="text-sm font-medium">Email notifications</p>
|
|
428
|
-
<p class="text-xs text-
|
|
435
|
+
<p class="text-xs text-(--bb-text-muted)">
|
|
429
436
|
Sent to alex@northwind.io — changes apply immediately.
|
|
430
437
|
</p>
|
|
431
438
|
</div>
|
|
@@ -439,7 +446,7 @@ What a panel must not do is both.
|
|
|
439
446
|
:name="pref.key"
|
|
440
447
|
/>
|
|
441
448
|
</div>
|
|
442
|
-
<p class="text-xs text-
|
|
449
|
+
<p class="text-xs text-(--bb-text-muted)" data-testid="summary">
|
|
443
450
|
{{ enabledCount }} of {{ preferences.length }} notifications on
|
|
444
451
|
</p>
|
|
445
452
|
</div>
|
package/dist/ai/BbSwitchGroup.md
CHANGED
|
@@ -44,7 +44,7 @@ stored value with `item-text` / `item-value` — never pre-map into
|
|
|
44
44
|
|
|
45
45
|
```vue
|
|
46
46
|
<template>
|
|
47
|
-
<div class="grid max-w-sm gap-2 rounded-
|
|
47
|
+
<div class="grid max-w-sm gap-2 rounded-(--bb-radius) border p-3">
|
|
48
48
|
<BbSwitchGroup
|
|
49
49
|
v-model="channels"
|
|
50
50
|
compact
|
|
@@ -55,7 +55,7 @@ stored value with `item-text` / `item-value` — never pre-map into
|
|
|
55
55
|
legend="Where should we reach you?"
|
|
56
56
|
name="workspace-notifications"
|
|
57
57
|
/>
|
|
58
|
-
<p class="text-xs text-
|
|
58
|
+
<p class="text-xs text-(--bb-text-muted)" data-testid="summary">
|
|
59
59
|
{{ channels.length }} channel{{ channels.length === 1 ? '' : 's' }} active
|
|
60
60
|
</p>
|
|
61
61
|
</div>
|
|
@@ -115,7 +115,7 @@ explains the limit.
|
|
|
115
115
|
|
|
116
116
|
```vue
|
|
117
117
|
<template>
|
|
118
|
-
<div class="max-w-sm rounded-
|
|
118
|
+
<div class="max-w-sm rounded-(--bb-radius) border p-3">
|
|
119
119
|
<BbSwitchGroup
|
|
120
120
|
v-model="channels"
|
|
121
121
|
compact
|
|
@@ -163,7 +163,7 @@ prop; when a dead row adds nothing, filter the item out of `items`.
|
|
|
163
163
|
|
|
164
164
|
```vue
|
|
165
165
|
<template>
|
|
166
|
-
<div class="max-w-sm rounded-
|
|
166
|
+
<div class="max-w-sm rounded-(--bb-radius) border p-3">
|
|
167
167
|
<BbSwitchGroup
|
|
168
168
|
v-model="enabled"
|
|
169
169
|
compact
|
|
@@ -213,7 +213,7 @@ explains why:
|
|
|
213
213
|
|
|
214
214
|
```vue
|
|
215
215
|
<template>
|
|
216
|
-
<div class="grid max-w-sm gap-2 rounded-
|
|
216
|
+
<div class="grid max-w-sm gap-2 rounded-(--bb-radius) border p-3">
|
|
217
217
|
<BbSwitchGroup
|
|
218
218
|
compact
|
|
219
219
|
item-text="label"
|
|
@@ -227,15 +227,12 @@ explains why:
|
|
|
227
227
|
/>
|
|
228
228
|
<p
|
|
229
229
|
v-if="error"
|
|
230
|
-
class="text-xs text-
|
|
230
|
+
class="text-xs text-(--bb-danger)"
|
|
231
231
|
data-testid="flags-error"
|
|
232
232
|
>
|
|
233
233
|
{{ error }}
|
|
234
234
|
</p>
|
|
235
|
-
<p
|
|
236
|
-
class="text-xs text-[color:var(--bb-text-muted)]"
|
|
237
|
-
data-testid="flags-status"
|
|
238
|
-
>
|
|
235
|
+
<p class="text-xs text-(--bb-text-muted)" data-testid="flags-status">
|
|
239
236
|
{{ saving ? 'Saving…' : `${enabled.length} of ${flags.length} flags on` }}
|
|
240
237
|
</p>
|
|
241
238
|
</div>
|
|
@@ -310,9 +307,7 @@ involved. See the [fetch-items](../../ai/guides/fetch-items-playbook.md) and
|
|
|
310
307
|
|
|
311
308
|
```vue
|
|
312
309
|
<template>
|
|
313
|
-
<div
|
|
314
|
-
class="flex max-w-sm flex-col gap-3 rounded-[var(--bb-radius)] border p-3"
|
|
315
|
-
>
|
|
310
|
+
<div class="flex max-w-sm flex-col gap-3 rounded-(--bb-radius) border p-3">
|
|
316
311
|
<BbRadioGroup
|
|
317
312
|
v-model="plan"
|
|
318
313
|
compact
|
|
@@ -338,7 +333,7 @@ involved. See the [fetch-items](../../ai/guides/fetch-items-playbook.md) and
|
|
|
338
333
|
name="alert-channels-by-plan"
|
|
339
334
|
persistent-hint
|
|
340
335
|
/>
|
|
341
|
-
<p class="channel-summary text-xs text-
|
|
336
|
+
<p class="channel-summary text-xs text-(--bb-text-muted)">
|
|
342
337
|
{{ enabled.length }} channel{{ enabled.length === 1 ? '' : 's' }} on
|
|
343
338
|
</p>
|
|
344
339
|
</div>
|