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.
Files changed (183) hide show
  1. package/README.md +55 -3
  2. package/bin/bitboss-ui-mcp.mjs +419 -9
  3. package/bin/bitboss-ui.mjs +293 -22
  4. package/dist/ai/BbAccordion.md +21 -23
  5. package/dist/ai/BbAlert.md +6 -12
  6. package/dist/ai/BbAvatar.md +60 -24
  7. package/dist/ai/BbBadge.md +12 -20
  8. package/dist/ai/BbBaseButton.md +14 -16
  9. package/dist/ai/BbBaseCheckboxIcon.md +6 -10
  10. package/dist/ai/BbBaseRadioIcon.md +6 -10
  11. package/dist/ai/BbBaseSwitchIcon.md +5 -9
  12. package/dist/ai/BbBreadcrumbs.md +23 -34
  13. package/dist/ai/BbButton.md +35 -47
  14. package/dist/ai/BbCheckbox.md +21 -37
  15. package/dist/ai/BbCheckboxGroup.md +13 -13
  16. package/dist/ai/BbCollapsible.md +14 -26
  17. package/dist/ai/BbColorInput.md +13 -23
  18. package/dist/ai/BbColorPalette.md +23 -35
  19. package/dist/ai/BbConfirm.md +17 -32
  20. package/dist/ai/BbDatePickerInput.md +15 -21
  21. package/dist/ai/BbDialog.md +159 -62
  22. package/dist/ai/BbDropdown.md +21 -25
  23. package/dist/ai/BbDropdownButton.md +13 -30
  24. package/dist/ai/BbDropzone.md +9 -11
  25. package/dist/ai/BbIcon.md +44 -33
  26. package/dist/ai/BbIndicator.md +2 -2
  27. package/dist/ai/BbNumberInput.md +18 -20
  28. package/dist/ai/BbOffCanvas.md +42 -42
  29. package/dist/ai/BbPagination.md +21 -23
  30. package/dist/ai/BbPopover.md +15 -17
  31. package/dist/ai/BbProgress.md +40 -51
  32. package/dist/ai/BbRadio.md +9 -9
  33. package/dist/ai/BbRadioGroup.md +7 -11
  34. package/dist/ai/BbRating.md +8 -12
  35. package/dist/ai/BbSelect.md +32 -36
  36. package/dist/ai/BbSelectPopover.md +19 -31
  37. package/dist/ai/BbSlider.md +15 -19
  38. package/dist/ai/BbSmoothHeight.md +16 -31
  39. package/dist/ai/BbSpinner.md +118 -74
  40. package/dist/ai/BbSwitch.md +25 -18
  41. package/dist/ai/BbSwitchGroup.md +9 -14
  42. package/dist/ai/BbTable.md +102 -55
  43. package/dist/ai/BbTabs.md +59 -82
  44. package/dist/ai/BbTag.md +12 -23
  45. package/dist/ai/BbTextInput.md +20 -26
  46. package/dist/ai/BbTextarea.md +28 -34
  47. package/dist/ai/BbToast.md +14 -34
  48. package/dist/ai/BbTooltip.md +22 -20
  49. package/dist/ai/BbTree.md +46 -72
  50. package/dist/ai/changelog.json +169 -62
  51. package/dist/ai/components.json +1467 -9
  52. package/dist/ai/composables/useConfirm.md +5 -2
  53. package/dist/ai/composables/useToast.md +4 -2
  54. package/dist/ai/guides/agent-contract.md +7 -4
  55. package/dist/ai/guides/ai-router.md +37 -22
  56. package/dist/ai/guides/component-picker.md +23 -18
  57. package/dist/ai/guides/design-language.md +141 -13
  58. package/dist/ai/guides/design-tokens.md +29 -4
  59. package/dist/ai/guides/icons-policy.md +46 -21
  60. package/dist/ai/guides/installation-and-plugin-setup.md +253 -17
  61. package/dist/ai/guides/migration/components/bb-rating.md +26 -1
  62. package/dist/ai/guides/migration/components/bb-tooltip.md +18 -0
  63. package/dist/ai/guides/migration/v2-to-v3.md +50 -23
  64. package/dist/ai/index.md +1 -1
  65. package/dist/ai/recipes/inertia/approvals-inbox.md +3 -3
  66. package/dist/ai/recipes/inertia/inline-edit-workspace.md +2 -2
  67. package/dist/ai/recipes/inertia/onboarding.md +2 -2
  68. package/dist/ai/recipes/inertia/ownership-atlas.md +6 -6
  69. package/dist/ai/recipes/inertia/record-form.md +5 -5
  70. package/dist/ai/recipes/inertia/records-workspace.md +4 -4
  71. package/dist/ai/recipes/inertia/upload-center.md +6 -6
  72. package/dist/ai/recipes/inertia/wizard-form.md +5 -5
  73. package/dist/ai/recipes/nuxt/approvals-inbox.md +3 -3
  74. package/dist/ai/recipes/nuxt/inline-edit-workspace.md +2 -2
  75. package/dist/ai/recipes/nuxt/onboarding.md +2 -2
  76. package/dist/ai/recipes/nuxt/record-form.md +5 -5
  77. package/dist/ai/recipes/nuxt/records-workspace.md +4 -4
  78. package/dist/ai/recipes/nuxt/upload-center.md +6 -6
  79. package/dist/ai/recipes/nuxt/wizard-form.md +5 -5
  80. package/dist/ai/recipes/vue/approvals-inbox.md +3 -3
  81. package/dist/ai/recipes/vue/inline-edit-workspace.md +2 -2
  82. package/dist/ai/recipes/vue/onboarding.md +2 -2
  83. package/dist/ai/recipes/vue/record-form.md +10 -10
  84. package/dist/ai/recipes/vue/records-workspace.md +4 -4
  85. package/dist/ai/recipes/vue/upload-center.md +6 -6
  86. package/dist/ai/recipes/vue/wizard-form.md +5 -5
  87. package/dist/ai/source/BbBadge.md +1 -1
  88. package/dist/ai/source/BbBaseCheckbox.md +1 -1
  89. package/dist/ai/source/BbBaseDatePicker.md +5 -5
  90. package/dist/ai/source/BbBaseDatePickerInput.md +2 -2
  91. package/dist/ai/source/BbBaseRadio.md +1 -1
  92. package/dist/ai/source/BbBaseRating.md +5 -5
  93. package/dist/ai/source/BbBaseSelect.md +1 -1
  94. package/dist/ai/source/BbBaseSlider.md +5 -5
  95. package/dist/ai/source/BbBaseSwitch.md +1 -1
  96. package/dist/ai/source/BbBaseTimePickerInput.md +1 -1
  97. package/dist/ai/source/BbBreadcrumbs.md +20 -1
  98. package/dist/ai/source/BbButton.md +2 -2
  99. package/dist/ai/source/BbDialog.md +39 -8
  100. package/dist/ai/source/BbDropdown.md +1 -1
  101. package/dist/ai/source/BbDropzone.md +5 -5
  102. package/dist/ai/source/BbIcon.md +23 -10
  103. package/dist/ai/source/BbOffCanvas.md +50 -28
  104. package/dist/ai/source/BbPagination.md +2 -2
  105. package/dist/ai/source/BbPopover.md +12 -1
  106. package/dist/ai/source/BbSelectPopover.md +45 -7
  107. package/dist/ai/source/BbSpinner.md +2 -2
  108. package/dist/ai/source/BbTable.md +11 -11
  109. package/dist/ai/source/BbTooltip.md +57 -10
  110. package/dist/ai/source/ChipsBox.md +1 -1
  111. package/dist/ai/source/CommaBox.md +1 -1
  112. package/dist/ai/source/GuidesComponent.md +14 -7
  113. package/dist/ai/source/OptionsContainer.md +1 -1
  114. package/dist/components/BbBadge/BadgeBodyContent.vue_vue_type_script_setup_true_lang.js +1 -1
  115. package/dist/components/BbBadge/BbBadge.vue_vue_type_script_setup_true_lang.js +1 -1
  116. package/dist/components/BbBaseCheckbox/BbBaseCheckbox.vue_vue_type_script_setup_true_lang.js +1 -1
  117. package/dist/components/BbBaseDatePicker/BbBaseDatePicker.vue_vue_type_script_setup_true_lang.js +4 -4
  118. package/dist/components/BbBaseDatePicker/BbBaseDatePickerInputDaySelector.vue_vue_type_script_setup_true_lang.js +1 -1
  119. package/dist/components/BbBaseDatePickerInput/BbBaseDatePickerInput.vue_vue_type_script_setup_true_lang.js +1 -1
  120. package/dist/components/BbBaseInputContainer/BbBaseInputContainer.vue.d.ts +1 -1
  121. package/dist/components/BbBaseRadio/BbBaseRadio.vue_vue_type_script_setup_true_lang.js +1 -1
  122. package/dist/components/BbBaseRating/BbBaseRating.vue_vue_type_script_setup_true_lang.js +3 -3
  123. package/dist/components/BbBaseSelect/BbBaseSelect.vue_vue_type_script_setup_true_lang.js +1 -1
  124. package/dist/components/BbBaseSlider/BbBaseSlider.vue_vue_type_script_setup_true_lang.js +3 -3
  125. package/dist/components/BbBaseSwitch/BbBaseSwitch.vue_vue_type_script_setup_true_lang.js +1 -1
  126. package/dist/components/BbBaseTimePickerInput/BbBaseTimePickerInput.vue_vue_type_script_setup_true_lang.js +1 -1
  127. package/dist/components/BbBreadcrumbs/BbBreadcrumbs.vue_vue_type_script_setup_true_lang.js +71 -71
  128. package/dist/components/BbButton/BbButton.vue_vue_type_script_setup_true_lang.js +2 -2
  129. package/dist/components/BbDialog/BbDialog.vue_vue_type_script_setup_true_lang.js +102 -97
  130. package/dist/components/BbDropdown/AdaptiveDropdown.vue_vue_type_script_setup_true_lang.js +1 -1
  131. package/dist/components/BbDropdown/BbDropdown.vue_vue_type_script_setup_true_lang.js +58 -58
  132. package/dist/components/BbDropzone/BbDropzone.vue_vue_type_script_setup_true_lang.js +2 -2
  133. package/dist/components/BbIcon/BbIcon.vue_vue_type_script_setup_true_lang.js +33 -35
  134. package/dist/components/BbIcon/iconCache.d.ts +30 -0
  135. package/dist/components/BbIcon/iconCache.js +21 -3
  136. package/dist/components/BbOffCanvas/BbOffCanvas.vue_vue_type_script_setup_true_lang.js +57 -56
  137. package/dist/components/BbPagination/BbPagination.vue_vue_type_script_setup_true_lang.js +2 -2
  138. package/dist/components/BbPopover/BbPopover.vue_vue_type_script_setup_true_lang.js +138 -138
  139. package/dist/components/BbSelectPopover/BbSelectPopover.vue_vue_type_script_setup_true_lang.js +43 -43
  140. package/dist/components/BbSpinner/BbSpinner.vue_vue_type_script_setup_true_lang.js +1 -1
  141. package/dist/components/BbSpinner/types.d.ts +1 -1
  142. package/dist/components/BbTable/BbTable.vue_vue_type_script_setup_true_lang.js +8 -8
  143. package/dist/components/BbTable/BbTableDataRow.js +2 -2
  144. package/dist/components/BbToast/BbToastRegion.vue_vue_type_script_setup_true_lang.js +62 -62
  145. package/dist/components/BbTooltip/BbTooltip.vue_vue_type_script_setup_true_lang.js +81 -78
  146. package/dist/components/BbTooltip/types.d.ts +8 -1
  147. package/dist/components/ChipsBox/ChipsBox.vue_vue_type_script_setup_true_lang.js +1 -1
  148. package/dist/components/CommaBox/CommaBox.vue_vue_type_script_setup_true_lang.js +1 -1
  149. package/dist/components/OptionsContainer/OptionsContainer.vue_vue_type_script_setup_true_lang.js +1 -1
  150. package/dist/composables/useConfirm.d.ts +22 -0
  151. package/dist/composables/useConfirm.js +43 -40
  152. package/dist/composables/useSafeAreaInternal.js +1 -1
  153. package/dist/composables/useToast.d.ts +16 -0
  154. package/dist/composables/useToast.js +20 -16
  155. package/dist/composables/useViewportWidth.d.ts +20 -6
  156. package/dist/composables/useViewportWidth.js +8 -7
  157. package/dist/icon-scan.d.ts +276 -0
  158. package/dist/icon-scan.js +485 -0
  159. package/dist/icons-whitelist.d.ts +5 -4
  160. package/dist/llms-full.txt +1979 -1527
  161. package/dist/llms-medium.txt +461 -74
  162. package/dist/llms.txt +1 -1
  163. package/dist/nuxt.js +10 -7
  164. package/dist/plugin.js +1 -0
  165. package/dist/runtime/nuxt-plugin.js +2 -1
  166. package/dist/styles.css +1 -1
  167. package/dist/types/Config.d.ts +18 -0
  168. package/dist/utils/cssLayers.d.ts +91 -0
  169. package/dist/utils/cssLayers.js +43 -0
  170. package/dist/utils/injectLibraryStyles.d.ts +3 -1
  171. package/dist/utils/injectLibraryStyles.js +24 -23
  172. package/dist/vite-plugin.d.ts +74 -11
  173. package/dist/vite.js +292 -253
  174. package/llms.txt +1 -1
  175. package/package.json +7 -5
  176. package/scripts/lib/ensure-manifest.mjs +28 -5
  177. package/scripts/lib/eslint-plugin.d.ts +35 -0
  178. package/scripts/lib/eslint-plugin.mjs +299 -3
  179. package/scripts/lib/hand-roll-hints.mjs +50 -6
  180. package/scripts/lib/html-attributes.mjs +42 -0
  181. package/scripts/lib/mcp-config.mjs +38 -34
  182. package/scripts/lib/public-type-exports.mjs +246 -0
  183. package/scripts/lib/validate-bb-markup.mjs +205 -12
@@ -77,7 +77,7 @@ needs is declared here, not in markup:
77
77
  ```vue
78
78
  <template>
79
79
  <div
80
- class="max-w-2xl overflow-hidden rounded-[var(--bb-radius)] border border-[color:var(--bb-border)]"
80
+ class="max-w-2xl overflow-hidden rounded-(--bb-radius) border border-(--bb-border)"
81
81
  >
82
82
  <BbTable
83
83
  caption="Recent invoices"
@@ -163,7 +163,7 @@ const invoices: Invoice[] = [
163
163
  // wash matches the design-language attention accent — public API, no internals.
164
164
  const rowClass = (invoice: Invoice) =>
165
165
  invoice.status === 'overdue'
166
- ? 'bg-[color:color-mix(in_oklab,#d97706_8%,var(--bb-panel))]'
166
+ ? 'bg-[color-mix(in_oklab,#d97706_8%,var(--bb-panel))]'
167
167
  : '';
168
168
  </script>
169
169
  ```
@@ -256,7 +256,7 @@ CSS in a non-scoped style block.
256
256
  ```vue
257
257
  <template>
258
258
  <div
259
- class="max-w-2xl overflow-hidden rounded-[var(--bb-radius)] border border-[color:var(--bb-border)]"
259
+ class="max-w-2xl overflow-hidden rounded-(--bb-radius) border border-(--bb-border)"
260
260
  >
261
261
  <BbTable
262
262
  caption="Invoice status"
@@ -267,8 +267,8 @@ CSS in a non-scoped style block.
267
267
  >
268
268
  <!-- Cell slot: name = the column key (dots/non-word chars become `_`,
269
269
  dashes are kept).
270
- The glyphs are brand assets from the app's `iconDir`, referenced as
271
- `local:*` names — mapped to full literals, never template-composed. -->
270
+ The glyphs are mapped to FULL icon literals, never template-composed
271
+ (`lucide:${status}` would defeat the build-time icon scan). -->
272
272
  <template #status="{ content }">
273
273
  <BbBadge
274
274
  :prepend:icon="glyphs[content as Status]"
@@ -282,9 +282,7 @@ CSS in a non-scoped style block.
282
282
  <template #header:amount="{ label }">
283
283
  <span class="inline-flex items-center gap-1">
284
284
  {{ label }}
285
- <span class="text-xs font-normal text-[color:var(--bb-text-muted)]"
286
- >EUR</span
287
- >
285
+ <span class="text-xs font-normal text-(--bb-text-muted)">EUR</span>
288
286
  </span>
289
287
  </template>
290
288
  </BbTable>
@@ -316,11 +314,11 @@ const labels: Record<Status, string> = {
316
314
  overdue: 'Overdue',
317
315
  };
318
316
 
319
- // Status → full-name literals (icons policy: no `local:${status}` templates).
317
+ // Status → full-name literals (icons policy: no `lucide:${status}` templates).
320
318
  const glyphs: Record<Status, IconType> = {
321
- paid: 'local:check_circle',
322
- pending: 'local:clock',
323
- overdue: 'local:alert_circle',
319
+ paid: 'lucide:circle-check',
320
+ pending: 'lucide:clock',
321
+ overdue: 'lucide:circle-alert',
324
322
  };
325
323
 
326
324
  const variants: Record<Status, BadgeVariantType> = {
@@ -458,7 +456,7 @@ for "there is nothing to show, here's why."
458
456
  </div>
459
457
 
460
458
  <div
461
- class="overflow-hidden rounded-[var(--bb-radius)] border border-[color:var(--bb-border)]"
459
+ class="overflow-hidden rounded-(--bb-radius) border border-(--bb-border)"
462
460
  >
463
461
  <BbTable
464
462
  caption="Team members"
@@ -470,7 +468,7 @@ for "there is nothing to show, here's why."
470
468
  loading-text="Loading members…"
471
469
  >
472
470
  <template #no-data>
473
- <p class="p-3 text-center text-sm text-[color:var(--bb-text-muted)]">
471
+ <p class="p-3 text-center text-sm text-(--bb-text-muted)">
474
472
  No members match your filters yet.
475
473
  </p>
476
474
  </template>
@@ -544,7 +542,7 @@ type ItemsProvider<T> = (
544
542
  <!-- `items` is an async function; the table re-runs it (debounced) whenever
545
543
  an entry in `dependencies` changes, showing skeletons while it awaits. -->
546
544
  <div
547
- class="overflow-hidden rounded-[var(--bb-radius)] border border-[color:var(--bb-border)]"
545
+ class="overflow-hidden rounded-(--bb-radius) border border-(--bb-border)"
548
546
  >
549
547
  <BbTable
550
548
  caption="Invoices"
@@ -626,6 +624,55 @@ pagination, confirm-delete, toasts) is the records workspace recipe
626
624
  (`./recipes/vue/records-workspace.md`), which works unchanged under Inertia or
627
625
  Nuxt since the table itself never touches the router.
628
626
 
627
+ ### Filtering
628
+
629
+ **There is no `filter` prop, and its absence is not a gap.** Libraries that ship
630
+ one (Quasar's `filter` / `filter-method`, PrimeVue's per-column filters) are
631
+ answering two different questions with one name, and this table answers both
632
+ already — under names that do not contain the word "filter", which is the only
633
+ reason the story looks missing.
634
+
635
+ On a **server-driven** table, a filter is an input to the fetch. That is
636
+ `dependencies`: list your filter state and the provider re-runs, debounced, with
637
+ out-of-order responses discarded and the previous rows kept on failure. A
638
+ `filter` prop would be a second, weaker spelling of the same thing — one value
639
+ instead of many, and race handling left to you.
640
+
641
+ On a **client-side** table holding every row, filtering is a computed:
642
+
643
+ ```vue
644
+ <BbTable :items="filteredItems" :columns="columns" />
645
+ ```
646
+
647
+ Always correct, no new prop, and it cannot desync from a `total-items` count the
648
+ way a table that filtered its own rows behind your back would.
649
+
650
+ Pick the shape by where the rows come from:
651
+
652
+ | Your situation | The filter mechanism |
653
+ | -------------------------------------- | ---------------------------------------------------------------------------------------- |
654
+ | Server returns a page at a time | `:dependencies="[search, status, sort]"` — see § Async items and filters |
655
+ | A whole filtered listing, URL-mirrored | The records workspace recipe (chip rail, tabs, `useQueryObject`) |
656
+ | Filter UI inside one column's header | `#header:<key>:append` — keeps the built-in sort button (see § Custom cells and headers) |
657
+ | All rows already in memory | A computed feeding `items` |
658
+
659
+ For the **per-column** case, use the affix slot rather than a full
660
+ `#header:<key>` replacement, or you take over the sort button too:
661
+
662
+ ```vue
663
+ <template #header:status:append>
664
+ <BbSelectPopover v-model="status" :items="statuses" />
665
+ </template>
666
+ ```
667
+
668
+ The filter control is yours; the table's only job is to refetch when the value
669
+ lands in `dependencies`. That is the same division of labour as sorting, where
670
+ `v-model:sort` reports intent and your provider acts on it.
671
+
672
+ For a complete worked filter rail — one Filters menu, editable chips, URL
673
+ mirroring, tab counts — read the records workspace recipe rather than assembling
674
+ it here.
675
+
629
676
  ### Pagination
630
677
 
631
678
  `BbTable` never slices its own data — you do, or the server does. Feed it the
@@ -644,7 +691,7 @@ the same page ref.
644
691
  announcements (aria-rowcount / aria-rowindex); the actual slicing is
645
692
  yours (or the server's). -->
646
693
  <div
647
- class="overflow-hidden rounded-[var(--bb-radius)] border border-[color:var(--bb-border)]"
694
+ class="overflow-hidden rounded-(--bb-radius) border border-(--bb-border)"
648
695
  >
649
696
  <BbTable
650
697
  caption="Invoices"
@@ -658,7 +705,7 @@ the same page ref.
658
705
  />
659
706
  </div>
660
707
  <div class="flex items-center justify-between gap-2">
661
- <p class="text-xs text-[color:var(--bb-text-muted)]">
708
+ <p class="text-xs text-(--bb-text-muted)">
662
709
  {{ rangeStart }}–{{ rangeEnd }} of {{ invoices.length }}
663
710
  </p>
664
711
  <BbPagination v-model="page" :total-pages="totalPages" />
@@ -738,7 +785,7 @@ third click.
738
785
  cycle asc → desc → off; the table only REPORTS the model — you sort
739
786
  the data. -->
740
787
  <div
741
- class="overflow-hidden rounded-[var(--bb-radius)] border border-[color:var(--bb-border)]"
788
+ class="overflow-hidden rounded-(--bb-radius) border border-(--bb-border)"
742
789
  >
743
790
  <BbTable
744
791
  v-model:sort="sort"
@@ -749,7 +796,7 @@ third click.
749
796
  :items="sortedInvoices"
750
797
  />
751
798
  </div>
752
- <p class="text-xs text-[color:var(--bb-text-muted)]">
799
+ <p class="text-xs text-(--bb-text-muted)">
753
800
  Sort model: <code>{{ JSON.stringify(sort) }}</code>
754
801
  </p>
755
802
  </div>
@@ -861,12 +908,12 @@ The model's contract is what makes a column panel trivial:
861
908
  where it was. -->
862
909
  <ul
863
910
  aria-label="Columns"
864
- class="flex flex-wrap gap-2 text-xs text-[color:var(--bb-text-muted)]"
911
+ class="flex flex-wrap gap-2 text-xs text-(--bb-text-muted)"
865
912
  >
866
913
  <li
867
914
  v-for="(column, index) in panelColumns"
868
915
  :key="column.key"
869
- class="flex items-center gap-1 rounded-[var(--bb-radius-sm)] border border-[color:var(--bb-border)] py-0.5 pl-2 pr-1"
916
+ class="flex items-center gap-1 rounded-(--bb-radius-sm) border border-(--bb-border) py-0.5 pr-1 pl-2"
870
917
  >
871
918
  <BbCheckbox
872
919
  :label="column.label"
@@ -892,7 +939,7 @@ The model's contract is what makes a column panel trivial:
892
939
  </li>
893
940
  </ul>
894
941
  <div
895
- class="overflow-hidden rounded-[var(--bb-radius)] border border-[color:var(--bb-border)]"
942
+ class="overflow-hidden rounded-(--bb-radius) border border-(--bb-border)"
896
943
  >
897
944
  <BbTable
898
945
  v-model:order="order"
@@ -918,7 +965,7 @@ The model's contract is what makes a column panel trivial:
918
965
  </template>
919
966
  </BbTable>
920
967
  </div>
921
- <p class="text-xs text-[color:var(--bb-text-muted)]">
968
+ <p class="text-xs text-(--bb-text-muted)">
922
969
  Order model: <code>{{ JSON.stringify(order) }}</code> · hidden:
923
970
  <code>{{ JSON.stringify([...hidden]) }}</code>
924
971
  </p>
@@ -1106,7 +1153,7 @@ everywhere in the library, the destructive bulk action is gated by
1106
1153
  gated by `useConfirm`. -->
1107
1154
  <div
1108
1155
  v-if="selectedCount"
1109
- class="flex items-center gap-2 rounded-[var(--bb-radius)] border border-[color:var(--bb-border)] bg-[color:var(--bb-muted)] px-2.5 py-1.5"
1156
+ class="flex items-center gap-2 rounded-(--bb-radius) border border-(--bb-border) bg-(--bb-muted) px-2.5 py-1.5"
1110
1157
  >
1111
1158
  <span class="text-sm">{{ selectedCount }} selected</span>
1112
1159
  <BbButton
@@ -1121,7 +1168,7 @@ everywhere in the library, the destructive bulk action is gated by
1121
1168
  </div>
1122
1169
 
1123
1170
  <div
1124
- class="overflow-hidden rounded-[var(--bb-radius)] border border-[color:var(--bb-border)]"
1171
+ class="overflow-hidden rounded-(--bb-radius) border border-(--bb-border)"
1125
1172
  >
1126
1173
  <BbTable
1127
1174
  id="member-selection"
@@ -1260,7 +1307,7 @@ with the current selection, which is exactly where the new rows are known.
1260
1307
  >
1261
1308
  {{ filter.label }}
1262
1309
  </BbButton>
1263
- <span class="ml-auto text-xs text-[color:var(--bb-text-muted)]">
1310
+ <span class="ml-auto text-xs text-(--bb-text-muted)">
1264
1311
  {{ selected.length }} selected
1265
1312
  </span>
1266
1313
  </div>
@@ -1270,7 +1317,7 @@ with the current selection, which is exactly where the new rows are known.
1270
1317
  show the provider-side reconcile, the pattern paginated tables
1271
1318
  (where the prop must stay off) still need. -->
1272
1319
  <div
1273
- class="overflow-hidden rounded-[var(--bb-radius)] border border-[color:var(--bb-border)]"
1320
+ class="overflow-hidden rounded-(--bb-radius) border border-(--bb-border)"
1274
1321
  >
1275
1322
  <BbTable
1276
1323
  v-model="selected"
@@ -1365,7 +1412,7 @@ const fetchMembers = async (
1365
1412
  null) — not an array. `select-text` labels the radio column for
1366
1413
  screen readers. -->
1367
1414
  <div
1368
- class="overflow-hidden rounded-[var(--bb-radius)] border border-[color:var(--bb-border)]"
1415
+ class="overflow-hidden rounded-(--bb-radius) border border-(--bb-border)"
1369
1416
  >
1370
1417
  <BbTable
1371
1418
  v-model="planId"
@@ -1381,9 +1428,9 @@ const fetchMembers = async (
1381
1428
  selectable
1382
1429
  />
1383
1430
  </div>
1384
- <p class="text-sm text-[color:var(--bb-text-muted)]">
1431
+ <p class="text-sm text-(--bb-text-muted)">
1385
1432
  Chosen plan:
1386
- <span class="font-medium text-[color:var(--bb-text)]">{{
1433
+ <span class="font-medium text-(--bb-text)">{{
1387
1434
  chosen ? chosen.name : 'none yet'
1388
1435
  }}</span>
1389
1436
  </p>
@@ -1460,7 +1507,7 @@ the read-only `expanded` flag. Drive open/close through the callback; the
1460
1507
  you `toggleExpanded` (a callback) and `expanded` (read-only) — drive the
1461
1508
  toggle through the callback, never by mutating the slot prop. -->
1462
1509
  <div
1463
- class="max-w-2xl overflow-hidden rounded-[var(--bb-radius)] border border-[color:var(--bb-border)]"
1510
+ class="max-w-2xl overflow-hidden rounded-(--bb-radius) border border-(--bb-border)"
1464
1511
  >
1465
1512
  <BbTable
1466
1513
  v-model:expanded-items="expanded"
@@ -1478,9 +1525,9 @@ the read-only `expanded` flag. Drive open/close through the callback; the
1478
1525
  </template>
1479
1526
 
1480
1527
  <template #expand="{ item }">
1481
- <div class="bg-[color:var(--bb-muted)] px-3 py-2.5 text-sm">
1528
+ <div class="bg-(--bb-muted) px-3 py-2.5 text-sm">
1482
1529
  <p class="font-medium">{{ item.client }} · {{ item.number }}</p>
1483
- <p class="text-xs text-[color:var(--bb-text-muted)]">
1530
+ <p class="text-xs text-(--bb-text-muted)">
1484
1531
  Issued {{ item.issuedAt }} · net 30 · {{ item.lines }} line items
1485
1532
  </p>
1486
1533
  </div>
@@ -1627,7 +1674,7 @@ parent's.
1627
1674
  <template>
1628
1675
  <div class="flex max-w-2xl flex-col gap-1.5">
1629
1676
  <div
1630
- class="overflow-hidden rounded-[var(--bb-radius)] border border-[color:var(--bb-border)]"
1677
+ class="overflow-hidden rounded-(--bb-radius) border border-(--bb-border)"
1631
1678
  >
1632
1679
  <BbTable
1633
1680
  caption="Invoices"
@@ -1639,7 +1686,7 @@ parent's.
1639
1686
  @resize:column="onResize"
1640
1687
  />
1641
1688
  </div>
1642
- <p class="text-xs text-[color:var(--bb-text-muted)]">
1689
+ <p class="text-xs text-(--bb-text-muted)">
1643
1690
  Widths: <code>{{ JSON.stringify(widths) }}</code>
1644
1691
  </p>
1645
1692
  </div>
@@ -1744,7 +1791,7 @@ above it. The mechanics:
1744
1791
  the parent's tracks, so line items line up under the invoice columns.
1745
1792
  The toggle binds the scope's `expandProps` for wired-up aria state. -->
1746
1793
  <div
1747
- class="max-w-2xl overflow-hidden rounded-[var(--bb-radius)] border border-[color:var(--bb-border)]"
1794
+ class="max-w-2xl overflow-hidden rounded-(--bb-radius) border border-(--bb-border)"
1748
1795
  >
1749
1796
  <BbTable
1750
1797
  v-model:expanded-items="expanded"
@@ -1767,7 +1814,7 @@ above it. The mechanics:
1767
1814
  </template>
1768
1815
 
1769
1816
  <template #expand="{ item }">
1770
- <div class="bg-[color:var(--bb-muted)] px-1 py-1">
1817
+ <div class="bg-(--bb-muted) px-1 py-1">
1771
1818
  <BbTable
1772
1819
  :caption="`Line items of ${item.number}`"
1773
1820
  :columns="lineColumns"
@@ -1961,7 +2008,7 @@ customize the look:
1961
2008
  ```ts
1962
2009
  const rowClass = (item: Invoice) =>
1963
2010
  item.id === highlighted.value
1964
- ? 'bg-[color:color-mix(in_oklab,var(--bb-danger)_10%,var(--bb-panel))]'
2011
+ ? 'bg-[color-mix(in_oklab,var(--bb-danger)_10%,var(--bb-panel))]'
1965
2012
  : '';
1966
2013
  ```
1967
2014
 
@@ -1975,7 +2022,7 @@ const rowClass = (item: Invoice) =>
1975
2022
  box; this example repaints it explicitly via the public `row-class`
1976
2023
  API to show how to customize it (here, matching the same tint). -->
1977
2024
  <div
1978
- class="min-w-0 flex-1 overflow-hidden rounded-[var(--bb-radius)] border border-[color:var(--bb-border)]"
2025
+ class="min-w-0 flex-1 overflow-hidden rounded-(--bb-radius) border border-(--bb-border)"
1979
2026
  >
1980
2027
  <BbTable
1981
2028
  v-model:highlighted="highlighted"
@@ -1989,15 +2036,15 @@ const rowClass = (item: Invoice) =>
1989
2036
  </div>
1990
2037
 
1991
2038
  <aside
1992
- class="w-full shrink-0 rounded-[var(--bb-radius)] border border-[color:var(--bb-border)] p-3 text-sm sm:w-52"
2039
+ class="w-full shrink-0 rounded-(--bb-radius) border border-(--bb-border) p-3 text-sm sm:w-52"
1993
2040
  >
1994
2041
  <template v-if="active">
1995
2042
  <p class="font-medium">{{ active.client }}</p>
1996
- <p class="mt-0.5 text-xs text-[color:var(--bb-text-muted)]">
2043
+ <p class="mt-0.5 text-xs text-(--bb-text-muted)">
1997
2044
  {{ active.number }} · {{ active.amount }}
1998
2045
  </p>
1999
2046
  </template>
2000
- <p v-else class="text-xs text-[color:var(--bb-text-muted)]">
2047
+ <p v-else class="text-xs text-(--bb-text-muted)">
2001
2048
  Select an invoice to preview it.
2002
2049
  </p>
2003
2050
  </aside>
@@ -2037,7 +2084,7 @@ const active = computed(() =>
2037
2084
  // Primary tint for the open row — selection chrome stays on content, not hover.
2038
2085
  const rowClass = (invoice: Invoice) =>
2039
2086
  invoice.id === highlighted.value
2040
- ? 'cursor-pointer bg-[color:color-mix(in_oklab,var(--bb-primary)_8%,var(--bb-panel))]'
2087
+ ? 'cursor-pointer bg-[color-mix(in_oklab,var(--bb-primary)_8%,var(--bb-panel))]'
2041
2088
  : 'cursor-pointer';
2042
2089
  </script>
2043
2090
  ```
@@ -2068,7 +2115,7 @@ look with `row-class` if the default tint doesn't fit.
2068
2115
  focused row, Home/End jump, Enter/Space open it (same path as a
2069
2116
  click, so it toggles `highlighted` and emits `click:row`). -->
2070
2117
  <div
2071
- class="overflow-hidden rounded-[var(--bb-radius)] border border-[color:var(--bb-border)]"
2118
+ class="overflow-hidden rounded-(--bb-radius) border border-(--bb-border)"
2072
2119
  >
2073
2120
  <BbTable
2074
2121
  v-model:highlighted="openEventId"
@@ -2081,10 +2128,10 @@ look with `row-class` if the default tint doesn't fit.
2081
2128
  :row-class="rowClass"
2082
2129
  />
2083
2130
  </div>
2084
- <p class="text-xs text-[color:var(--bb-text-muted)]">
2131
+ <p class="text-xs text-(--bb-text-muted)">
2085
2132
  Tab into the table, move with the arrow keys, press Enter to open a row.
2086
2133
  Open event:
2087
- <span class="font-medium text-[color:var(--bb-text)]">{{
2134
+ <span class="font-medium text-(--bb-text)">{{
2088
2135
  openEvent ? `${openEvent.actor} — ${openEvent.action}` : 'none'
2089
2136
  }}</span>
2090
2137
  </p>
@@ -2130,7 +2177,7 @@ const openEvent = computed(() =>
2130
2177
  // customize it (the public API for doing so).
2131
2178
  const rowClass = (event: AuditEvent) =>
2132
2179
  event.id === openEventId.value
2133
- ? 'bg-[color:color-mix(in_oklab,var(--bb-primary)_8%,var(--bb-panel))]'
2180
+ ? 'bg-[color-mix(in_oklab,var(--bb-primary)_8%,var(--bb-panel))]'
2134
2181
  : '';
2135
2182
  </script>
2136
2183
  ```
@@ -2164,7 +2211,7 @@ open-in-new-tab for free.
2164
2211
  <!-- Row-level navigation is offloaded to BbButton: `href` (or `to` in a
2165
2212
  router app) makes it a real link, not a JS click handler. -->
2166
2213
  <div
2167
- class="max-w-2xl overflow-hidden rounded-[var(--bb-radius)] border border-[color:var(--bb-border)]"
2214
+ class="max-w-2xl overflow-hidden rounded-(--bb-radius) border border-(--bb-border)"
2168
2215
  >
2169
2216
  <BbTable
2170
2217
  actions-text="Actions"
@@ -2258,7 +2305,7 @@ rollback on failure, and overlay retirement inside the items function.
2258
2305
  <template>
2259
2306
  <div class="flex max-w-2xl flex-col gap-1.5">
2260
2307
  <div
2261
- class="overflow-hidden rounded-[var(--bb-radius)] border border-[color:var(--bb-border)]"
2308
+ class="overflow-hidden rounded-(--bb-radius) border border-(--bb-border)"
2262
2309
  >
2263
2310
  <BbTable
2264
2311
  caption="Sprint tasks — every cell saves itself"
@@ -2312,10 +2359,10 @@ rollback on failure, and overlay retirement inside the items function.
2312
2359
  </BbTable>
2313
2360
  </div>
2314
2361
 
2315
- <p v-if="lastFailure" class="text-xs text-[color:var(--bb-danger)]">
2362
+ <p v-if="lastFailure" class="text-xs text-(--bb-danger)">
2316
2363
  {{ lastFailure }}
2317
2364
  </p>
2318
- <p class="text-xs text-[color:var(--bb-text-muted)]">
2365
+ <p class="text-xs text-(--bb-text-muted)">
2319
2366
  No Save button anywhere — edits persist per field, optimistically.
2320
2367
  BB-121's save always fails and rolls back.
2321
2368
  </p>
@@ -2530,7 +2577,7 @@ your wrapper actually sits on before sprinkling `min-width: 0` everywhere.)
2530
2577
 
2531
2578
  ```vue
2532
2579
  <div
2533
- class="max-h-52 max-w-2xl overflow-auto rounded-[var(--bb-radius)] border border-[color:var(--bb-border)]"
2580
+ class="max-h-52 max-w-2xl overflow-auto rounded-(--bb-radius) border border-(--bb-border)"
2534
2581
  >
2535
2582
  <BbTable
2536
2583
  caption="Server fleet"
@@ -2649,7 +2696,7 @@ keyboard grammar work untouched. One prop, no knobs.
2649
2696
  <!-- Bounding the table's height is what makes it the scroller of its own
2650
2697
  rows; `virtual` windows them and implies the stuck header. -->
2651
2698
  <div
2652
- class="max-w-2xl overflow-hidden rounded-[var(--bb-radius)] border border-[color:var(--bb-border)]"
2699
+ class="max-w-2xl overflow-hidden rounded-(--bb-radius) border border-(--bb-border)"
2653
2700
  >
2654
2701
  <BbTable
2655
2702
  caption="Ledger"
@@ -2987,7 +3034,7 @@ reader.
2987
3034
  | `actionsText` | `string \| undefined` | | | Label used in the header of the actions column. |
2988
3035
  | `align` | `"left" \| "center" \| "right" \| undefined` | `"left"` | | Text alignment of the columns. |
2989
3036
  | `caption` | `string \| undefined` | | | Caption that describes the content of the table. Used for accessibility purposes. |
2990
- | `columns` | `InternalColumn<T>[] \| undefined` | `[]` | | Array of definitions of how the columns should be rendered. |
3037
+ | `columns` | `BbTableColumn<T>[] \| undefined` | `[]` | | Array of definitions of how the columns should be rendered. |
2991
3038
  | `compact` | `boolean \| undefined` | `false` | | Adds a CSS class that applies a compact style to the component. |
2992
3039
  | `dependencies` | `unknown[] \| undefined` | `[]` | | Defines an array of dependencies that will trigger actions in the component upon change. |
2993
3040
  | `depsDebounceTime` | `number \| undefined` | `0` | | Timeout used to debounce response to changes to dependencies. |
@@ -3022,7 +3069,7 @@ reader.
3022
3069
  | `readonly` | `boolean \| undefined` | `false` | | Sets the input in a readonly state. |
3023
3070
  | `reorderable` | `boolean \| undefined` | `false` | | Lets the user reorder the data columns: drag a header cell (AG Grid style — the column moves live under the pointer and a chip with its label follows) or, from the keyboard, use each header's reorder handle (ArrowLeft / ArrowRight move the … |
3024
3071
  | `resizable` | `boolean \| undefined` | `false` | | Lets the user resize the data columns of a root table: drag the handle on a header's trailing edge (the column follows live, the width commits on release), or press Alt + ArrowLeft / ArrowRight on the focused header; double-click the handle… |
3025
- | `rowClass` | `RowClasses<Item> \| undefined` | | | Defines the classes to be passed to each data row. Can also be a function of the row's item for dynamic values. |
3072
+ | `rowClass` | `BbTableRowClasses<Item> \| undefined` | | | Defines the classes to be passed to each data row. Can also be a function of the row's item for dynamic values. |
3026
3073
  | `selectable` | `boolean \| ((item: Item) => boolean) \| undefined` | | | Defines whether the table is selectable. Can be a global boolean that affects all rows or a function that accepts an item and returns a boolean that only affects that item. |
3027
3074
  | `selectAll` | `boolean \| undefined` | `false` | | Defines whether the "Select all" checkbox is checked. |
3028
3075
  | `selectAllLabel` | `string \| undefined` | | | Text of the label used by the "Select all" boolean. |