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/BbDialog.md
CHANGED
|
@@ -42,11 +42,11 @@ for buttons inside the body. Footer buttons simply set the model back to
|
|
|
42
42
|
```vue
|
|
43
43
|
<template>
|
|
44
44
|
<div
|
|
45
|
-
class="flex w-full max-w-sm flex-col gap-3 rounded-
|
|
45
|
+
class="flex w-full max-w-sm flex-col gap-3 rounded-(--bb-radius) border p-4"
|
|
46
46
|
>
|
|
47
47
|
<div>
|
|
48
48
|
<p class="m-0 text-sm font-medium">Issue labels</p>
|
|
49
|
-
<p class="m-0 text-xs text-
|
|
49
|
+
<p class="m-0 text-xs text-(--bb-text-muted)">
|
|
50
50
|
12 labels · used across Northwind issues
|
|
51
51
|
</p>
|
|
52
52
|
</div>
|
|
@@ -68,7 +68,7 @@ for buttons inside the body. Footer buttons simply set the model back to
|
|
|
68
68
|
label="Label name"
|
|
69
69
|
placeholder="e.g. Priority"
|
|
70
70
|
/>
|
|
71
|
-
<p class="m-0 text-xs text-
|
|
71
|
+
<p class="m-0 text-xs text-(--bb-text-muted)">
|
|
72
72
|
Names are unique per workspace and show up in filters.
|
|
73
73
|
</p>
|
|
74
74
|
</div>
|
|
@@ -108,35 +108,56 @@ A `title` prop renders the standard header (title text + close button) and wires
|
|
|
108
108
|
`aria-labelledby` for you. Put form fields in the `default` slot and actions in
|
|
109
109
|
the `footer` slot — keep exactly one primary action there and align the group to
|
|
110
110
|
the end. The body area scrolls internally when content overflows; header and
|
|
111
|
-
footer stay pinned. This edit-record dialog
|
|
112
|
-
record on `@show
|
|
113
|
-
|
|
111
|
+
footer stay pinned. This edit-record dialog builds a fresh draft from the
|
|
112
|
+
selected record on `@show`, drops it on `@hidden`, and copies it back on save —
|
|
113
|
+
so a canceled edit never leaks into the next session, and neither does a field
|
|
114
|
+
the next record happens not to have.
|
|
114
115
|
|
|
115
116
|
**Edit-record dialog with a footer action**
|
|
116
117
|
|
|
117
118
|
```vue
|
|
118
119
|
<template>
|
|
119
|
-
<
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
<p class="m-0 truncate text-xs text-[color:var(--bb-text-muted)]">
|
|
125
|
-
{{ contact.email }}
|
|
126
|
-
</p>
|
|
127
|
-
</div>
|
|
128
|
-
<BbButton
|
|
129
|
-
prepend:icon="lucide:pencil"
|
|
130
|
-
variant="outline"
|
|
131
|
-
@click="open = true"
|
|
120
|
+
<ul class="m-0 flex w-full max-w-sm list-none flex-col gap-2 p-0">
|
|
121
|
+
<li
|
|
122
|
+
v-for="contact in contacts"
|
|
123
|
+
:key="contact.id"
|
|
124
|
+
class="flex items-center justify-between gap-3 rounded-(--bb-radius) border p-3"
|
|
132
125
|
>
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
126
|
+
<div class="min-w-0">
|
|
127
|
+
<p class="m-0 truncate text-sm font-medium">{{ contact.name }}</p>
|
|
128
|
+
<p class="m-0 truncate text-xs text-(--bb-text-muted)">
|
|
129
|
+
{{ contact.email
|
|
130
|
+
}}<template v-if="contact.phone"> · {{ contact.phone }}</template>
|
|
131
|
+
</p>
|
|
132
|
+
</div>
|
|
133
|
+
<BbButton
|
|
134
|
+
:aria-label="`Edit ${contact.name}`"
|
|
135
|
+
prepend:icon="lucide:pencil"
|
|
136
|
+
size="sm"
|
|
137
|
+
variant="outline"
|
|
138
|
+
@click="edit(contact)"
|
|
139
|
+
>
|
|
140
|
+
Edit
|
|
141
|
+
</BbButton>
|
|
142
|
+
</li>
|
|
143
|
+
</ul>
|
|
144
|
+
<BbDialog
|
|
145
|
+
v-model="open"
|
|
146
|
+
size="md"
|
|
147
|
+
title="Edit contact"
|
|
148
|
+
@hidden="clear"
|
|
149
|
+
@show="seed"
|
|
150
|
+
>
|
|
151
|
+
<div v-if="draft" class="grid gap-3">
|
|
138
152
|
<BbTextInput v-model="draft.name" compact label="Full name" />
|
|
139
153
|
<BbTextInput v-model="draft.email" compact label="Email" type="email" />
|
|
154
|
+
<BbTextInput
|
|
155
|
+
v-model="draft.phone"
|
|
156
|
+
compact
|
|
157
|
+
label="Phone"
|
|
158
|
+
placeholder="Optional"
|
|
159
|
+
type="tel"
|
|
160
|
+
/>
|
|
140
161
|
<BbSwitch v-model="draft.subscribed" label="Subscribed to updates" />
|
|
141
162
|
</div>
|
|
142
163
|
<template #footer>
|
|
@@ -149,33 +170,100 @@ copies it back on save.
|
|
|
149
170
|
</template>
|
|
150
171
|
|
|
151
172
|
<script setup lang="ts">
|
|
152
|
-
import {
|
|
173
|
+
import { ref } from 'vue';
|
|
153
174
|
import { BbButton, BbDialog, BbSwitch, BbTextInput } from 'bitboss-ui';
|
|
154
175
|
|
|
176
|
+
// `phone` is optional on the record: some contacts simply do not have one.
|
|
155
177
|
type Contact = {
|
|
178
|
+
id: number;
|
|
156
179
|
name: string;
|
|
157
180
|
email: string;
|
|
181
|
+
phone?: string;
|
|
158
182
|
subscribed: boolean;
|
|
159
183
|
};
|
|
160
184
|
|
|
161
|
-
// The
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
185
|
+
// The records being edited — in a real app these come from your store/API.
|
|
186
|
+
// Two of them on purpose, one WITHOUT the optional field: that is the case a
|
|
187
|
+
// single-record demo can never show going wrong.
|
|
188
|
+
const contacts = ref<Contact[]>([
|
|
189
|
+
{
|
|
190
|
+
id: 1,
|
|
191
|
+
name: 'Ada Lovelace',
|
|
192
|
+
email: 'ada@analytical.co',
|
|
193
|
+
phone: '+44 20 7946 0958',
|
|
194
|
+
subscribed: true,
|
|
195
|
+
},
|
|
196
|
+
{
|
|
197
|
+
id: 2,
|
|
198
|
+
name: 'Grace Hopper',
|
|
199
|
+
email: 'grace@navy.mil',
|
|
200
|
+
subscribed: false,
|
|
201
|
+
},
|
|
202
|
+
]);
|
|
203
|
+
|
|
204
|
+
// The form binds every field, so the draft must always carry every field.
|
|
205
|
+
// A blank factory guarantees that; the record only overrides what it has.
|
|
206
|
+
type Draft = {
|
|
207
|
+
name: string;
|
|
208
|
+
email: string;
|
|
209
|
+
phone: string;
|
|
210
|
+
subscribed: boolean;
|
|
211
|
+
};
|
|
212
|
+
const blank = (): Draft => ({
|
|
213
|
+
name: '',
|
|
214
|
+
email: '',
|
|
215
|
+
phone: '',
|
|
216
|
+
subscribed: false,
|
|
166
217
|
});
|
|
167
218
|
|
|
168
219
|
const open = ref(false);
|
|
169
|
-
const
|
|
220
|
+
const editing = ref<Contact | null>(null);
|
|
221
|
+
const draft = ref<Draft | null>(null);
|
|
170
222
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
223
|
+
const edit = (contact: Contact) => {
|
|
224
|
+
editing.value = contact;
|
|
225
|
+
open.value = true;
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
// Seed on `@show`, and REPLACE the draft rather than merging into it.
|
|
229
|
+
// `Object.assign(draft, record)` copies only the keys the record has: open Grace
|
|
230
|
+
// (no phone) right after Ada (phone set) and Ada's phone is still in the input.
|
|
231
|
+
const seed = () => {
|
|
232
|
+
const record = editing.value;
|
|
233
|
+
if (!record) return;
|
|
234
|
+
draft.value = {
|
|
235
|
+
...blank(),
|
|
236
|
+
name: record.name,
|
|
237
|
+
email: record.email,
|
|
238
|
+
phone: record.phone ?? '',
|
|
239
|
+
subscribed: record.subscribed,
|
|
240
|
+
};
|
|
241
|
+
};
|
|
242
|
+
|
|
243
|
+
// Drop the draft once the close transition ends, so nothing waits around for
|
|
244
|
+
// the next record — `@hidden` is the teardown hook, not `@hide`.
|
|
245
|
+
const clear = () => {
|
|
246
|
+
draft.value = null;
|
|
247
|
+
editing.value = null;
|
|
174
248
|
};
|
|
175
249
|
|
|
176
250
|
const save = () => {
|
|
177
|
-
|
|
178
|
-
|
|
251
|
+
const record = editing.value;
|
|
252
|
+
const next = draft.value;
|
|
253
|
+
if (!record || !next) return;
|
|
254
|
+
// Persist here, then dismiss. The optional field goes back to "absent"
|
|
255
|
+
// when it was cleared, so the record never grows an empty string.
|
|
256
|
+
contacts.value = contacts.value.map((contact) =>
|
|
257
|
+
contact.id === record.id
|
|
258
|
+
? {
|
|
259
|
+
...contact,
|
|
260
|
+
name: next.name,
|
|
261
|
+
email: next.email,
|
|
262
|
+
phone: next.phone.trim() || undefined,
|
|
263
|
+
subscribed: next.subscribed,
|
|
264
|
+
}
|
|
265
|
+
: contact
|
|
266
|
+
);
|
|
179
267
|
open.value = false;
|
|
180
268
|
};
|
|
181
269
|
</script>
|
|
@@ -194,11 +282,11 @@ and the only thing `aria-describedby` points at:
|
|
|
194
282
|
```vue
|
|
195
283
|
<template>
|
|
196
284
|
<div
|
|
197
|
-
class="flex w-full max-w-sm flex-col gap-3 rounded-
|
|
285
|
+
class="flex w-full max-w-sm flex-col gap-3 rounded-(--bb-radius) border p-4"
|
|
198
286
|
>
|
|
199
287
|
<div>
|
|
200
288
|
<p class="m-0 text-sm font-medium">INV-2044</p>
|
|
201
|
-
<p class="m-0 text-xs text-
|
|
289
|
+
<p class="m-0 text-xs text-(--bb-text-muted)">
|
|
202
290
|
Northwind Traders · €1,280.00 · paid
|
|
203
291
|
</p>
|
|
204
292
|
</div>
|
|
@@ -263,11 +351,11 @@ dismissed invite doesn't resurface half-typed:
|
|
|
263
351
|
```vue
|
|
264
352
|
<template>
|
|
265
353
|
<div
|
|
266
|
-
class="flex w-full max-w-sm flex-col gap-3 rounded-
|
|
354
|
+
class="flex w-full max-w-sm flex-col gap-3 rounded-(--bb-radius) border p-4"
|
|
267
355
|
>
|
|
268
356
|
<div>
|
|
269
357
|
<p class="m-0 text-sm font-medium">Team · Northwind Labs</p>
|
|
270
|
-
<p class="m-0 text-xs text-
|
|
358
|
+
<p class="m-0 text-xs text-(--bb-text-muted)">
|
|
271
359
|
4 members · 1 pending invite
|
|
272
360
|
</p>
|
|
273
361
|
</div>
|
|
@@ -298,7 +386,7 @@ dismissed invite doesn't resurface half-typed:
|
|
|
298
386
|
:items="roles"
|
|
299
387
|
label="Role"
|
|
300
388
|
/>
|
|
301
|
-
<p class="m-0 text-xs text-
|
|
389
|
+
<p class="m-0 text-xs text-(--bb-text-muted)">
|
|
302
390
|
They'll get an email with a link that expires in 7 days.
|
|
303
391
|
</p>
|
|
304
392
|
</div>
|
|
@@ -349,10 +437,18 @@ const send = () => {
|
|
|
349
437
|
</script>
|
|
350
438
|
```
|
|
351
439
|
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
-
|
|
355
|
-
|
|
440
|
+
Three rules keep dialog forms honest:
|
|
441
|
+
|
|
442
|
+
- Seed the draft when the dialog opens (`@show` is the hook), and **replace
|
|
443
|
+
it, never merge into it**. `Object.assign(draft, record)` copies only the
|
|
444
|
+
keys the record has, so opening a record whose optional field is absent
|
|
445
|
+
right after one where it was set leaves the previous value in the input —
|
|
446
|
+
nothing warns. Build the draft from a blank factory so every field the form
|
|
447
|
+
binds is always present, then overlay the record
|
|
448
|
+
(`{ ...blank(), phone: record.phone ?? '' }`).
|
|
449
|
+
- Clear the draft on `@hidden` as well. A close must leave nothing behind for
|
|
450
|
+
the next caller; `@hidden` fires after the close transition, so the form
|
|
451
|
+
does not blank mid-fade.
|
|
356
452
|
- On success, do the work first, then set the model to `false`; the close
|
|
357
453
|
transition runs while your toast/refresh happens.
|
|
358
454
|
|
|
@@ -361,7 +457,8 @@ Two rules keep dialog forms honest:
|
|
|
361
457
|
Four events bracket the transitions — `show` fires as the model turns `true`,
|
|
362
458
|
`shown` after the native `showModal()` call and initial focus, `hide` as the
|
|
363
459
|
model turns `false`, and `hidden` after the close transition completes. Use
|
|
364
|
-
`@show` to (re)seed form state, `@hidden` to tear down
|
|
460
|
+
`@show` to (re)seed form state, `@hidden` to drop a draft and tear down
|
|
461
|
+
expensive content.
|
|
365
462
|
|
|
366
463
|
Body content is **lazy**: nothing inside the dialog renders until the first
|
|
367
464
|
open. Set `eager` to render it immediately (e.g. so a chart can pre-measure, or
|
|
@@ -435,11 +532,11 @@ element.
|
|
|
435
532
|
```vue
|
|
436
533
|
<template>
|
|
437
534
|
<div
|
|
438
|
-
class="flex w-full max-w-sm flex-col gap-3 rounded-
|
|
535
|
+
class="flex w-full max-w-sm flex-col gap-3 rounded-(--bb-radius) border p-4"
|
|
439
536
|
>
|
|
440
537
|
<div>
|
|
441
538
|
<p class="m-0 text-sm font-medium">Finish setting up</p>
|
|
442
|
-
<p class="m-0 text-xs text-
|
|
539
|
+
<p class="m-0 text-xs text-(--bb-text-muted)">
|
|
443
540
|
Add your company so invoices and invites look right.
|
|
444
541
|
</p>
|
|
445
542
|
</div>
|
|
@@ -513,13 +610,11 @@ automatically; close only once the work resolves:
|
|
|
513
610
|
```vue
|
|
514
611
|
<template>
|
|
515
612
|
<div
|
|
516
|
-
class="flex w-full max-w-sm items-center justify-between gap-3 rounded-
|
|
613
|
+
class="flex w-full max-w-sm items-center justify-between gap-3 rounded-(--bb-radius) border p-4"
|
|
517
614
|
>
|
|
518
615
|
<div class="min-w-0">
|
|
519
616
|
<p class="m-0 truncate text-sm font-medium">{{ projectName }}</p>
|
|
520
|
-
<p class="m-0 text-xs text-
|
|
521
|
-
Project · private
|
|
522
|
-
</p>
|
|
617
|
+
<p class="m-0 text-xs text-(--bb-text-muted)">Project · private</p>
|
|
523
618
|
</div>
|
|
524
619
|
<BbButton
|
|
525
620
|
prepend:icon="lucide:pencil"
|
|
@@ -595,8 +690,10 @@ const save = async () => {
|
|
|
595
690
|
|
|
596
691
|
Dialogs sharing a `stack` name **replace** one another: only the most recently
|
|
597
692
|
opened member is visible, the ones beneath are hidden until it closes — the
|
|
598
|
-
stack reads as a single surface whose content swaps as you drill in.
|
|
599
|
-
|
|
693
|
+
stack reads as a single surface whose content swaps as you drill in. When a
|
|
694
|
+
member closes, the one beneath crossfades in as it fades out, on the stack's
|
|
695
|
+
single backdrop — the page behind never blinks between them. Dialogs with
|
|
696
|
+
different names (or none) are independent and simply layer by open order.
|
|
600
697
|
Use a stack for a two-step flow that should not read as two boxes piling up.
|
|
601
698
|
|
|
602
699
|
**Drill into advanced options**
|
|
@@ -604,11 +701,11 @@ Use a stack for a two-step flow that should not read as two boxes piling up.
|
|
|
604
701
|
```vue
|
|
605
702
|
<template>
|
|
606
703
|
<div
|
|
607
|
-
class="flex w-full max-w-sm flex-col gap-3 rounded-
|
|
704
|
+
class="flex w-full max-w-sm flex-col gap-3 rounded-(--bb-radius) border p-4"
|
|
608
705
|
>
|
|
609
706
|
<div>
|
|
610
707
|
<p class="m-0 text-sm font-medium">Workspace settings</p>
|
|
611
|
-
<p class="m-0 text-xs text-
|
|
708
|
+
<p class="m-0 text-xs text-(--bb-text-muted)">
|
|
612
709
|
Storage, backups, retention
|
|
613
710
|
</p>
|
|
614
711
|
</div>
|
|
@@ -621,7 +718,7 @@ Use a stack for a two-step flow that should not read as two boxes piling up.
|
|
|
621
718
|
<BbDialog v-model="first" stack="settings" title="Storage">
|
|
622
719
|
<div class="grid gap-3">
|
|
623
720
|
<BbSwitch v-model="autoBackup" label="Automatic backups" />
|
|
624
|
-
<p class="m-0 text-xs text-
|
|
721
|
+
<p class="m-0 text-xs text-(--bb-text-muted)">
|
|
625
722
|
Nightly snapshots keep the last 30 days of changes.
|
|
626
723
|
</p>
|
|
627
724
|
<BbButton
|
|
@@ -636,7 +733,7 @@ Use a stack for a two-step flow that should not read as two boxes piling up.
|
|
|
636
733
|
<BbDialog v-model="second" stack="settings" title="Advanced retention">
|
|
637
734
|
<div class="grid gap-3">
|
|
638
735
|
<BbSwitch v-model="keepForever" label="Keep monthly snapshots" />
|
|
639
|
-
<p class="m-0 text-xs text-
|
|
736
|
+
<p class="m-0 text-xs text-(--bb-text-muted)">
|
|
640
737
|
Monthly snapshots stay available for 12 months after creation.
|
|
641
738
|
</p>
|
|
642
739
|
</div>
|
|
@@ -694,11 +791,11 @@ link.
|
|
|
694
791
|
```vue
|
|
695
792
|
<template>
|
|
696
793
|
<div
|
|
697
|
-
class="flex w-full max-w-sm flex-col gap-3 rounded-
|
|
794
|
+
class="flex w-full max-w-sm flex-col gap-3 rounded-(--bb-radius) border p-4"
|
|
698
795
|
>
|
|
699
796
|
<div>
|
|
700
797
|
<p class="m-0 text-sm font-medium">Projects</p>
|
|
701
|
-
<p class="m-0 text-xs text-
|
|
798
|
+
<p class="m-0 text-xs text-(--bb-text-muted)">
|
|
702
799
|
Free plan · {{ used }} of {{ limit }} used
|
|
703
800
|
</p>
|
|
704
801
|
</div>
|
|
@@ -719,7 +816,7 @@ link.
|
|
|
719
816
|
using all of them. Upgrade to <strong>Pro</strong> for unlimited
|
|
720
817
|
projects and priority support.
|
|
721
818
|
</p>
|
|
722
|
-
<p class="m-0 text-xs text-
|
|
819
|
+
<p class="m-0 text-xs text-(--bb-text-muted)">
|
|
723
820
|
Billing starts when you confirm — you can cancel anytime.
|
|
724
821
|
</p>
|
|
725
822
|
</div>
|
|
@@ -846,7 +943,7 @@ default falls back to `config.adaptive`.
|
|
|
846
943
|
| `modelValue` | `boolean \| undefined` | `false` | | Used by v-model to open / close the dialog. A dialog with no `v-model` starts closed. |
|
|
847
944
|
| `offCanvasProps` | `Partial<BbOffCanvasProps> \| undefined` | | | Overrides merged over the offcanvas (mobile) surface's props. The drawer defaults to a bottom, draggable, content-sized sheet (`side: 'bottom'`, `draggable: true`, `size: 'auto'`); use this to override those, set other drawer-only options (… |
|
|
848
945
|
| `persistent` | `boolean \| undefined` | `false` | | Prevent closing via outside clicks or Escape key. The header close (×) button STILL closes a persistent dialog — that is the documented escape hatch; combine with `hideClose` to remove it, or use `disabled` to block every dismissal. Program… |
|
|
849
|
-
| `size` | `Responsive<NonNullable<number \| ({ size?: any; } & string) \| keyof
|
|
946
|
+
| `size` | `Responsive<NonNullable<number \| ({ size?: any; } & string) \| keyof BbDialogSizes \| undefined>> \| undefined` | `"sm"` | | Controls the maximum width of the dialog. Accepts named presets from `'xs'` to `'2xl'`, a custom CSS width string, or a numeric pixel value — or a per-breakpoint map (e.g. `{ default: 'sm', lg: 'lg' }`) to switch width responsively. |
|
|
850
947
|
| `stack` | `string \| undefined` | | | Name of the stack this dialog belongs to. Dialogs sharing the same `stack` value replace one another: only the most recently opened stays visible while the others in the stack are hidden beneath it. Dialogs in different stacks — or with no … |
|
|
851
948
|
| `title` | `string \| undefined` | | | Title text announced to assistive technologies. If omitted, no header is rendered (unless a `header` slot is supplied) and accessibility must be handled manually. |
|
|
852
949
|
| `transitionDuration` | `number \| undefined` | `250` | | Controls the duration of the open and close animations. |
|
package/dist/ai/BbDropdown.md
CHANGED
|
@@ -71,17 +71,17 @@ yes (the `<BbConfirm>` host mounts once per app, e.g. in the root layout).
|
|
|
71
71
|
```vue
|
|
72
72
|
<template>
|
|
73
73
|
<div
|
|
74
|
-
class="flex max-w-sm items-center gap-2 rounded-
|
|
74
|
+
class="flex max-w-sm items-center gap-2 rounded-(--bb-radius) border p-2"
|
|
75
75
|
>
|
|
76
76
|
<div
|
|
77
77
|
aria-hidden="true"
|
|
78
|
-
class="flex size-8 shrink-0 items-center justify-center rounded-
|
|
78
|
+
class="flex size-8 shrink-0 items-center justify-center rounded-(--bb-radius-sm) bg-(--bb-muted) text-(--bb-text-muted)"
|
|
79
79
|
>
|
|
80
80
|
<span class="text-xs font-medium">PDF</span>
|
|
81
81
|
</div>
|
|
82
82
|
<div class="min-w-0 flex-1">
|
|
83
83
|
<p class="truncate text-sm font-medium">Q3-report.pdf</p>
|
|
84
|
-
<p class="text-xs text-
|
|
84
|
+
<p class="text-xs text-(--bb-text-muted)">
|
|
85
85
|
248 KB · <span data-last>{{ last }}</span>
|
|
86
86
|
</p>
|
|
87
87
|
</div>
|
|
@@ -194,11 +194,11 @@ selectable group the menu stays open instead, and the row itself carries
|
|
|
194
194
|
```vue
|
|
195
195
|
<template>
|
|
196
196
|
<div
|
|
197
|
-
class="flex max-w-sm items-center gap-2 rounded-
|
|
197
|
+
class="flex max-w-sm items-center gap-2 rounded-(--bb-radius) border p-2"
|
|
198
198
|
>
|
|
199
199
|
<div class="min-w-0 flex-1">
|
|
200
200
|
<p class="truncate text-sm font-medium">bitboss/storefront</p>
|
|
201
|
-
<p class="text-xs text-
|
|
201
|
+
<p class="text-xs text-(--bb-text-muted)" data-sync>
|
|
202
202
|
{{ status }}
|
|
203
203
|
</p>
|
|
204
204
|
</div>
|
|
@@ -268,7 +268,7 @@ nesting shallow (two levels is plenty).
|
|
|
268
268
|
```vue
|
|
269
269
|
<template>
|
|
270
270
|
<div
|
|
271
|
-
class="flex max-w-xs items-center justify-between gap-2 rounded-
|
|
271
|
+
class="flex max-w-xs items-center justify-between gap-2 rounded-(--bb-radius) border p-2"
|
|
272
272
|
>
|
|
273
273
|
<span class="text-sm font-medium">Acme Studio</span>
|
|
274
274
|
<BbDropdown :items="items" placement="bottom-end">
|
|
@@ -357,9 +357,9 @@ must point at a _group_ (not a plain item, not a missing key).
|
|
|
357
357
|
```vue
|
|
358
358
|
<template>
|
|
359
359
|
<div
|
|
360
|
-
class="flex max-w-md flex-wrap items-center gap-2 rounded-
|
|
360
|
+
class="flex max-w-md flex-wrap items-center gap-2 rounded-(--bb-radius) border p-2"
|
|
361
361
|
>
|
|
362
|
-
<span class="pr-1 text-xs font-medium text-
|
|
362
|
+
<span class="pr-1 text-xs font-medium text-(--bb-text-muted)"
|
|
363
363
|
>Invoices</span
|
|
364
364
|
>
|
|
365
365
|
<BbDropdown :adaptive="false" :items="items" :width="200">
|
|
@@ -378,7 +378,7 @@ must point at a _group_ (not a plain item, not a missing key).
|
|
|
378
378
|
<BbDropdownGroup id="sort" v-model="sortBy" />
|
|
379
379
|
<BbDropdownGroup id="tags" v-model="tags" />
|
|
380
380
|
</BbDropdown>
|
|
381
|
-
<span class="text-xs text-
|
|
381
|
+
<span class="text-xs text-(--bb-text-muted)">
|
|
382
382
|
Sort: <span data-sort>{{ sortBy }}</span> · Tags:
|
|
383
383
|
<span data-tags>{{ tags.join(', ') || 'none' }}</span>
|
|
384
384
|
</span>
|
|
@@ -456,11 +456,11 @@ The full grammar:
|
|
|
456
456
|
```vue
|
|
457
457
|
<template>
|
|
458
458
|
<div
|
|
459
|
-
class="flex max-w-sm flex-wrap items-center gap-2 rounded-
|
|
459
|
+
class="flex max-w-sm flex-wrap items-center gap-2 rounded-(--bb-radius) border p-2"
|
|
460
460
|
>
|
|
461
461
|
<div class="min-w-0 flex-1">
|
|
462
462
|
<p class="truncate text-sm font-medium">INV-2048 · Northwind</p>
|
|
463
|
-
<p class="text-xs text-
|
|
463
|
+
<p class="text-xs text-(--bb-text-muted)">
|
|
464
464
|
Assignees ·
|
|
465
465
|
<span data-count>{{ assignees.length }} selected</span>
|
|
466
466
|
</p>
|
|
@@ -535,11 +535,9 @@ a valid selection.
|
|
|
535
535
|
```vue
|
|
536
536
|
<template>
|
|
537
537
|
<div
|
|
538
|
-
class="flex max-w-md flex-wrap items-center gap-2 rounded-
|
|
538
|
+
class="flex max-w-md flex-wrap items-center gap-2 rounded-(--bb-radius) border p-2"
|
|
539
539
|
>
|
|
540
|
-
<span class="pr-1 text-xs font-medium text-
|
|
541
|
-
>Board</span
|
|
542
|
-
>
|
|
540
|
+
<span class="pr-1 text-xs font-medium text-(--bb-text-muted)">Board</span>
|
|
543
541
|
<BbDropdown
|
|
544
542
|
:adaptive="false"
|
|
545
543
|
:items="menu"
|
|
@@ -560,7 +558,7 @@ a valid selection.
|
|
|
560
558
|
<BbDropdownGroup id="board" v-model="board" />
|
|
561
559
|
<BbDropdownGroup id="assignees" v-model="assignees" />
|
|
562
560
|
</BbDropdown>
|
|
563
|
-
<span class="text-xs text-
|
|
561
|
+
<span class="text-xs text-(--bb-text-muted)">
|
|
564
562
|
<span data-board>{{ board ?? 'all boards' }}</span> ·
|
|
565
563
|
<span data-assignees>{{ assigneeNames || 'anyone' }}</span>
|
|
566
564
|
</span>
|
|
@@ -771,11 +769,9 @@ the edge slots, to replace one row's content use its key.
|
|
|
771
769
|
```vue
|
|
772
770
|
<template>
|
|
773
771
|
<div
|
|
774
|
-
class="flex max-w-xs items-center gap-2 rounded-
|
|
772
|
+
class="flex max-w-xs items-center gap-2 rounded-(--bb-radius) border p-2"
|
|
775
773
|
>
|
|
776
|
-
<span class="text-xs font-medium text-
|
|
777
|
-
>Workspace</span
|
|
778
|
-
>
|
|
774
|
+
<span class="text-xs font-medium text-(--bb-text-muted)">Workspace</span>
|
|
779
775
|
<!-- `adaptive` is pinned off so the demo behaves identically on any
|
|
780
776
|
viewport; leave it at the project default in real apps. -->
|
|
781
777
|
<BbDropdown :adaptive="false" :items="items">
|
|
@@ -794,7 +790,7 @@ the edge slots, to replace one row's content use its key.
|
|
|
794
790
|
(and inside group headers). Payload is read-only. -->
|
|
795
791
|
<template #item:prepend="{ item }">
|
|
796
792
|
<BbIcon
|
|
797
|
-
class="text-
|
|
793
|
+
class="text-(--bb-text-muted)"
|
|
798
794
|
data-env-dot
|
|
799
795
|
:icon="envIcon(item.key)"
|
|
800
796
|
size="xs"
|
|
@@ -874,7 +870,7 @@ the sheet's pinned header and footer.
|
|
|
874
870
|
</BbButton>
|
|
875
871
|
</template>
|
|
876
872
|
<template #header>
|
|
877
|
-
<div class="px-3 py-2 text-xs font-semibold text-
|
|
873
|
+
<div class="px-3 py-2 text-xs font-semibold text-(--bb-text-muted)">
|
|
878
874
|
Jump to month
|
|
879
875
|
</div>
|
|
880
876
|
</template>
|
|
@@ -903,11 +899,11 @@ behaves exactly as with a click menu.
|
|
|
903
899
|
```vue
|
|
904
900
|
<template>
|
|
905
901
|
<div
|
|
906
|
-
class="flex max-w-sm items-center gap-2 rounded-
|
|
902
|
+
class="flex max-w-sm items-center gap-2 rounded-(--bb-radius) border p-2"
|
|
907
903
|
>
|
|
908
904
|
<div class="min-w-0 flex-1">
|
|
909
905
|
<p class="truncate text-sm font-medium">INV-2048</p>
|
|
910
|
-
<p class="text-xs text-
|
|
906
|
+
<p class="text-xs text-(--bb-text-muted)">
|
|
911
907
|
Northwind · €1,240.00 ·
|
|
912
908
|
<span data-last>{{ last }}</span>
|
|
913
909
|
</p>
|
|
@@ -1221,7 +1217,7 @@ mid-session never swaps a live menu between flyout and sheet.
|
|
|
1221
1217
|
| `eager` | `boolean \| undefined` | `false` | | Prevents rendering content before it's made visible. |
|
|
1222
1218
|
| `enforceCoherence` | `boolean \| undefined` | `false` | | Default for pipeline groups: drop selections that are no longer present in a group's current items (e.g. after a `dependencies` re-fetch) from the selection and `v-model`. A group's own `enforceCoherence` overrides this. |
|
|
1223
1219
|
| `id` | `string \| undefined` | | | The identifier of the component. |
|
|
1224
|
-
| `items` | `
|
|
1220
|
+
| `items` | `BbDropdownItem[]` | `[]` | yes | Array used to render each dropdown button. They can act as `button`, as `a`, or as `router-link` as they are based on the functionality provided by `BbBaseButton`. Pass a flat array for a single group, nest arrays for divider-separated grou… |
|
|
1225
1221
|
| `loadingText` | `string \| undefined` | | | Default placeholder text shown while a pipeline group's async items load. A group's own `loadingText` overrides this; both fall back to the localized `common.loadingText` (`'Loading...'`). |
|
|
1226
1222
|
| `noDataText` | `string \| undefined` | | | Default placeholder text shown when a pipeline group resolves to no items. A group's own `noDataText` overrides this; both fall back to the localized `common.noDataText` (`'No data to display'`). |
|
|
1227
1223
|
| `offCanvasProps` | `Partial<BbOffCanvasProps> \| undefined` | | | Overrides forwarded to the underlying `BbOffCanvas` when `adaptive` renders the sheet on mobile. Merged over the adaptive defaults (`direction: 'bottom'`, `size: 'auto'`, `draggable: true`). Ignored when `adaptive` is `false`. |
|
|
@@ -47,20 +47,16 @@ entry's remaining rows are dropped from the menu.
|
|
|
47
47
|
|
|
48
48
|
```vue
|
|
49
49
|
<template>
|
|
50
|
-
<div
|
|
51
|
-
class="flex max-w-sm flex-col gap-3 rounded-[var(--bb-radius)] border p-3"
|
|
52
|
-
>
|
|
50
|
+
<div class="flex max-w-sm flex-col gap-3 rounded-(--bb-radius) border p-3">
|
|
53
51
|
<div class="flex flex-col gap-0.5">
|
|
54
52
|
<span class="text-sm font-medium">Invoice INV-2048</span>
|
|
55
|
-
<span class="text-xs text-
|
|
53
|
+
<span class="text-xs text-(--bb-text-muted)">
|
|
56
54
|
Acme Studio · due Jul 31, 2026
|
|
57
55
|
</span>
|
|
58
56
|
</div>
|
|
59
57
|
<div class="flex items-center gap-2">
|
|
60
58
|
<BbDropdownButton :items="items" prepend:icon="lucide:check" />
|
|
61
|
-
<span class="text-xs text-
|
|
62
|
-
last
|
|
63
|
-
}}</span>
|
|
59
|
+
<span class="text-xs text-(--bb-text-muted)" data-last>{{ last }}</span>
|
|
64
60
|
</div>
|
|
65
61
|
</div>
|
|
66
62
|
</template>
|
|
@@ -100,12 +96,10 @@ so each export is a real navigation, not an `@click` that fakes a download.
|
|
|
100
96
|
|
|
101
97
|
```vue
|
|
102
98
|
<template>
|
|
103
|
-
<div
|
|
104
|
-
class="flex max-w-sm flex-col gap-3 rounded-[var(--bb-radius)] border p-3"
|
|
105
|
-
>
|
|
99
|
+
<div class="flex max-w-sm flex-col gap-3 rounded-(--bb-radius) border p-3">
|
|
106
100
|
<div class="flex flex-col gap-0.5">
|
|
107
101
|
<span class="text-sm font-medium">Q2 revenue report</span>
|
|
108
|
-
<span class="text-xs text-
|
|
102
|
+
<span class="text-xs text-(--bb-text-muted)">
|
|
109
103
|
Acme Studio · Jul 1 – Sep 30, 2026
|
|
110
104
|
</span>
|
|
111
105
|
</div>
|
|
@@ -115,9 +109,7 @@ so each export is a real navigation, not an `@click` that fakes a download.
|
|
|
115
109
|
prepend:icon="lucide:download"
|
|
116
110
|
variant="outline"
|
|
117
111
|
/>
|
|
118
|
-
<span class="text-xs text-
|
|
119
|
-
last
|
|
120
|
-
}}</span>
|
|
112
|
+
<span class="text-xs text-(--bb-text-muted)" data-export>{{ last }}</span>
|
|
121
113
|
</div>
|
|
122
114
|
</div>
|
|
123
115
|
</template>
|
|
@@ -205,18 +197,16 @@ manually.
|
|
|
205
197
|
|
|
206
198
|
```vue
|
|
207
199
|
<template>
|
|
208
|
-
<div
|
|
209
|
-
class="flex max-w-sm flex-col gap-3 rounded-[var(--bb-radius)] border p-3"
|
|
210
|
-
>
|
|
200
|
+
<div class="flex max-w-sm flex-col gap-3 rounded-(--bb-radius) border p-3">
|
|
211
201
|
<div class="flex flex-col gap-0.5">
|
|
212
202
|
<span class="text-sm font-medium">July product changelog</span>
|
|
213
|
-
<span class="text-xs text-
|
|
203
|
+
<span class="text-xs text-(--bb-text-muted)">
|
|
214
204
|
bitboss-ui · ready to publish
|
|
215
205
|
</span>
|
|
216
206
|
</div>
|
|
217
207
|
<div class="flex items-center gap-2">
|
|
218
208
|
<BbDropdownButton :items="items" prepend:icon="lucide:rocket" />
|
|
219
|
-
<span class="text-xs text-
|
|
209
|
+
<span class="text-xs text-(--bb-text-muted)" data-status>{{
|
|
220
210
|
status
|
|
221
211
|
}}</span>
|
|
222
212
|
</div>
|
|
@@ -272,16 +262,11 @@ not the one that needs a second thought.
|
|
|
272
262
|
|
|
273
263
|
```vue
|
|
274
264
|
<template>
|
|
275
|
-
<div
|
|
276
|
-
class="flex max-w-md flex-col gap-3 rounded-[var(--bb-radius)] border p-3"
|
|
277
|
-
>
|
|
265
|
+
<div class="flex max-w-md flex-col gap-3 rounded-(--bb-radius) border p-3">
|
|
278
266
|
<div class="flex items-center justify-between gap-3">
|
|
279
267
|
<div class="flex min-w-0 flex-col gap-0.5">
|
|
280
268
|
<span class="text-sm font-medium">acme-web · production</span>
|
|
281
|
-
<span
|
|
282
|
-
class="text-xs text-[color:var(--bb-text-muted)]"
|
|
283
|
-
data-deploy-status
|
|
284
|
-
>
|
|
269
|
+
<span class="text-xs text-(--bb-text-muted)" data-deploy-status>
|
|
285
270
|
{{ status }}
|
|
286
271
|
</span>
|
|
287
272
|
</div>
|
|
@@ -376,12 +361,10 @@ main button itself — so the control always announces exactly what it will do.
|
|
|
376
361
|
|
|
377
362
|
```vue
|
|
378
363
|
<template>
|
|
379
|
-
<div
|
|
380
|
-
class="flex max-w-md flex-col gap-3 rounded-[var(--bb-radius)] border p-3"
|
|
381
|
-
>
|
|
364
|
+
<div class="flex max-w-md flex-col gap-3 rounded-(--bb-radius) border p-3">
|
|
382
365
|
<div class="flex flex-col gap-0.5">
|
|
383
366
|
<span class="text-sm font-medium">Add usage-based billing #482</span>
|
|
384
|
-
<span class="text-xs text-
|
|
367
|
+
<span class="text-xs text-(--bb-text-muted)" data-merge-status>
|
|
385
368
|
{{ status }}
|
|
386
369
|
</span>
|
|
387
370
|
</div>
|