Skip to content

Commit 02be37d

Browse files
authored
docs(BTabs): Updates based on v-model changes (#2760)
1 parent 30a9175 commit 02be37d

File tree

10 files changed

+239
-39
lines changed

10 files changed

+239
-39
lines changed

apps/docs/src/data/components/tabs.data.ts

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,6 @@ export default {
1616
description:
1717
"Use a specific ID for this tab's tab control button. If not provided, one will automatically be generated",
1818
},
19-
unmountLazy: {
20-
type: 'boolean',
21-
default: undefined,
22-
description:
23-
'When set and lazy is also set, the content will be unmounted when the tab is not active',
24-
},
2519
noBody: {
2620
type: 'boolean',
2721
default: false,
@@ -44,7 +38,7 @@ export default {
4438
description:
4539
"CSS class (or classes) to apply to the tab's control button inner link element",
4640
},
47-
...pick(showHideProps, ['lazy']),
41+
...pick(showHideProps, ['lazy', 'unmountLazy']),
4842
...pick(buildCommonProps(), ['active', 'disabled', 'id', 'tag', 'title']),
4943
} satisfies Record<keyof BvnComponentProps['BTab'], PropertyReference>,
5044
},

apps/docs/src/docs.md

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -395,7 +395,13 @@ Alternatively the ESM package is available as well
395395

396396
</HighlightCard>
397397

398-
## Tree-shake CSS
398+
## Tree-shaking
399+
400+
If you are concerned about the size of your application, you should utilize
401+
[tree-shaking](https://vuejs.org/guide/best-practices/performance#bundle-size-and-tree-shaking).
402+
Below are some pointers on optimizing tree-shaking in the context of BootstrapVueNext.
403+
404+
### Tree-shake CSS
399405

400406
If you are using one of the preferred installation methods, JS will be tree-shaken by default. The one thing we are not able to do automatically is optimize CSS. Methods like PurgeCSS are not ideal because of a limitation with the dynamic nature of class renderings and Vue (Problematic code like: `[btn-${props.variant}]: props.variant !== undefined`). With that being said, BootstrapVueNext does not handle CSS imports from Bootstrap, we only add some additional CSS ourselves. So, using a method such as [Lean Sass Imports](https://getbootstrap.com/docs/5.3/customize/optimize/#lean-sass-imports) from the Bootstrap documentation is likely the best way to achieve the tiniest possible application size. Though it is not automatic, it should prove the safest bet for minifying your application.
401407

@@ -407,6 +413,21 @@ Practically the `createBootstrap` plugin is ~20kb gzipped with `toast` and `moda
407413

408414
<BootstrapPluginWarning />
409415

416+
### Exposed methods and tree-shaking
417+
418+
In order to correctly type exposed methods, you need to explicitly import them from BootstrapVueNext. When doeing this,
419+
import the component (not just the type) and use the full path to improve tree-shaking.
420+
421+
<HighlightCard>
422+
423+
```vue
424+
<script setup lang="ts">
425+
import {BTab} from 'bootstrap-vue-next/components/BTabs'
426+
</script>
427+
```
428+
429+
</HighlightCard>
430+
410431
## Comparison with BootstrapVue
411432

412433
BootstrapVue is the parent project for which this is based on. We consider BootstrapVue as the best implementation of Bootstrap `v4`. We strive for a full compatibility list for BootstrapVue. However, due to the nature of the rewrite, some features may be missing or changed. If anyone has spotted a missing compatibility feature, we request that you submit a GitHub issue or contribute to the [parity report](https://github.com/bootstrap-vue-next/bootstrap-vue-next/blob/main/CONTRIBUTING.md#help-verify-bootstrapvue-and-bootstrap-v5-parity).
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
<template>
2+
<div>
3+
<!-- Tabs with card integration -->
4+
<BCard no-body>
5+
<BTabs
6+
v-model:index="tabIndex"
7+
v-model="tabId"
8+
small
9+
card
10+
>
11+
<BTab
12+
id="tab-general"
13+
v-model:active="general"
14+
title="General"
15+
>I'm the first fading tab</BTab
16+
>
17+
<BTab
18+
id="tab-edit-profile"
19+
v-model:active="editProfile"
20+
title="Edit profile"
21+
>
22+
I'm the second tab
23+
<BCard>I'm the card in tab</BCard>
24+
</BTab>
25+
<BTab
26+
id="tab-premium"
27+
v-model:active="premium"
28+
title="Premium Plan"
29+
disabled
30+
>Sibzamini!</BTab
31+
>
32+
<BTab
33+
id="tab-info"
34+
v-model:active="info"
35+
title="Info"
36+
>I'm the last tab</BTab
37+
>
38+
</BTabs>
39+
</BCard>
40+
41+
<!-- Control buttons-->
42+
<div class="text-center">
43+
<BButtonGroup class="mt-2">
44+
<BButton @click="general = true">General</BButton>
45+
<BButton @click="editProfile = true">Edit Profile</BButton>
46+
<BButton @click="premium = true">Premium</BButton>
47+
<BButton @click="info = true">Info</BButton>
48+
</BButtonGroup>
49+
50+
<div class="text-muted mt-2">Current Tab: index = {{ tabIndex }}, id = {{ tabId }}</div>
51+
</div>
52+
</div>
53+
</template>
54+
55+
<script setup lang="ts">
56+
import {ref} from 'vue'
57+
58+
const tabIndex = ref(0)
59+
const tabId = ref(undefined)
60+
61+
const general = ref(true)
62+
const editProfile = ref(false)
63+
const premium = ref(false)
64+
const info = ref(false)
65+
</script>
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
<template>
2+
<div>
3+
<!-- Tabs with card integration -->
4+
<BCard no-body>
5+
<BTabs
6+
v-model:index="tabIndex"
7+
v-model="tabId"
8+
small
9+
card
10+
>
11+
<BTab
12+
id="tab-general"
13+
ref="tabGeneral"
14+
title="General"
15+
>I'm the first fading tab</BTab
16+
>
17+
<BTab
18+
id="tab-edit-profile"
19+
ref="tabEditProfile"
20+
title="Edit profile"
21+
>
22+
I'm the second tab
23+
<BCard>I'm the card in tab</BCard>
24+
</BTab>
25+
<BTab
26+
id="tab-premium"
27+
ref="tabPremium"
28+
title="Premium Plan"
29+
disabled
30+
>Sibzamini!</BTab
31+
>
32+
<BTab
33+
id="tab-info"
34+
ref="tabInfo"
35+
title="Info"
36+
>I'm the last tab</BTab
37+
>
38+
</BTabs>
39+
</BCard>
40+
41+
<!-- Control buttons-->
42+
<div class="text-center">
43+
<BButtonGroup
44+
id="tab-controls"
45+
class="mt-2"
46+
>
47+
<BButton @click="tabGeneral?.activate()">General</BButton>
48+
<BButton @click="tabEditProfile?.activate()">Edit Profile</BButton>
49+
<BButton @click="tabPremium?.activate()">Premium</BButton>
50+
<BButton @click="tabInfo?.activate()">Info</BButton>
51+
</BButtonGroup>
52+
53+
<div class="text-muted mt-2">Current Tab: index = {{ tabIndex }}, id = {{ tabId }}</div>
54+
</div>
55+
</div>
56+
</template>
57+
58+
<script setup lang="ts">
59+
import {ref, useTemplateRef} from 'vue'
60+
// Import BTab explicitly path to get the correct type for exposed methods
61+
// and use the full path to improve tree shaking
62+
import {BTab} from 'bootstrap-vue-next/components/BTabs'
63+
64+
const tabIndex = ref(0)
65+
const tabId = ref(undefined)
66+
67+
const tabGeneral = useTemplateRef<typeof BTab>('tabGeneral')
68+
const tabEditProfile = useTemplateRef<typeof BTab>('tabEditProfile')
69+
const tabPremium = useTemplateRef<typeof BTab>('tabPremium')
70+
const tabInfo = useTemplateRef<typeof BTab>('tabInfo')
71+
</script>

apps/docs/src/docs/components/demo/TabsLazy.vue

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,13 @@
22
<!-- #region template -->
33
<BTabs content-class="mt-3">
44
<!-- This tabs content will always be mounted -->
5-
<BTab title="Regular tab"><BAlert :model-value="true">I'm always mounted</BAlert></BTab>
5+
<BTab title="Regular tab"><BAlert show>I'm always mounted</BAlert></BTab>
66

77
<!-- This tabs content will not be mounted until the tab is shown -->
8-
<!-- and will be un-mounted when hidden -->
98
<BTab
109
title="Lazy tab"
1110
lazy
12-
><BAlert :model-value="true">I'm lazy mounted!</BAlert></BTab
11+
><BAlert show>I'm lazy mounted!</BAlert></BTab
1312
>
1413
</BTabs>
1514
<!-- #endregion template -->

apps/docs/src/docs/components/demo/TabsLazyAll.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
content-class="mt-3"
55
lazy
66
>
7-
<BTab title="Tab 1"><BAlert :model-value="true">I'm lazy mounted!</BAlert></BTab>
8-
<BTab title="Tab 2"><BAlert :model-value="true">I'm lazy mounted too!</BAlert></BTab>
7+
<BTab title="Tab 1"><BAlert show>I'm lazy mounted!</BAlert></BTab>
8+
<BTab title="Tab 2"><BAlert show>I'm lazy mounted too!</BAlert></BTab>
99
</BTabs>
1010
<!-- #endregion template -->
1111
</template>

apps/docs/src/docs/components/demo/TabsExternalControls.vue renamed to apps/docs/src/docs/components/demo/TabsModelControl.vue

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,33 @@
44
<BCard no-body>
55
<BTabs
66
v-model:index="tabIndex"
7+
v-model="tabId"
78
small
89
card
910
>
10-
<BTab title="General">I'm the first fading tab</BTab>
11-
<BTab title="Edit profile">
11+
<BTab
12+
id="tab-general"
13+
title="General"
14+
>I'm the first fading tab</BTab
15+
>
16+
<BTab
17+
id="tab-edit-profile"
18+
title="Edit profile"
19+
>
1220
I'm the second tab
1321
<BCard>I'm the card in tab</BCard>
1422
</BTab>
1523
<BTab
24+
id="tab-premium"
1625
title="Premium Plan"
1726
disabled
1827
>Sibzamini!</BTab
1928
>
20-
<BTab title="Info">I'm the last tab</BTab>
29+
<BTab
30+
id="tab-info"
31+
title="Info"
32+
>I'm the last tab</BTab
33+
>
2134
</BTabs>
2235
</BCard>
2336

@@ -28,7 +41,7 @@
2841
<BButton @click="tabIndex++">Next</BButton>
2942
</BButtonGroup>
3043

31-
<div class="text-muted">Current Tab: {{ tabIndex }}</div>
44+
<div class="text-muted mt-2">Current Tab: index = {{ tabIndex }}, id = {{ tabId }}</div>
3245
</div>
3346
</div>
3447
</template>
@@ -37,4 +50,5 @@
3750
import {ref} from 'vue'
3851
3952
const tabIndex = ref(0)
53+
const tabId = ref<string | undefined>(undefined)
4054
</script>
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<template>
2+
<!-- #region template -->
3+
<BTabs content-class="mt-3">
4+
<!-- This tabs content will always be mounted -->
5+
<BTab title="Regular tab"><BAlert show>I'm always mounted</BAlert></BTab>
6+
7+
<!-- This tabs content will not be mounted until the tab is shown -->
8+
<!-- and will be un-mounted when hidden -->
9+
<BTab
10+
title="Lazy tab"
11+
lazy
12+
unmount-lazy
13+
><BAlert show>I'm lazy mounted and will unmount when deactivated!</BAlert></BTab
14+
>
15+
</BTabs>
16+
<!-- #endregion template -->
17+
</template>

apps/docs/src/docs/components/tabs.md

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ Visually move the tab controls to the bottom by setting the prop `end`.
8282
::: warning
8383

8484
- Bottom placement visually works best with the `pills` variant. When using the default `tabs`
85-
variant, you may want to provided your own custom styling classes, as Bootstrap v4 CSS assumes the
85+
variant, you may want to provide your own custom styling classes, as Bootstrap CSS assumes the
8686
tabs will always be placed on the top of the tabs content.
8787
- To provide a better user experience with bottom placed controls, ensure that the content of each
8888
tab pane is the same height and fits completely within the visible viewport, otherwise the user
@@ -176,15 +176,15 @@ Sometimes it's preferred to load components & data only when activating a tab, i
176176
all tabs (and associated data) when rendering the `<BTabs>` set.
177177

178178
Individual `<BTab>` components can be lazy loaded via the `lazy` prop, which when set doesn't mount
179-
the content of the `<BTab>` until it is activated (shown), and will be un-mounted when the tab is
180-
deactivated (hidden):
181-
182-
::: danger
183-
There is currently a bug in `lazy` that causes an infinite recursion
184-
:::
179+
the content of the `<BTab>` until it is activated (shown):
185180

186181
<<< DEMO ./demo/TabsLazy.vue#template{vue-html}
187182

183+
By default, once the tab is activated, the content will remain mounted. To un-mounted the content
184+
when the tab is deactivated (hidden) use the `unmount-lazy` prop.
185+
186+
<<< DEMO ./demo/TabsUnmountLazy.vue#template{vue-html}
187+
188188
One can also make all tab's lazy by setting the `lazy` prop on the parent `<BTabs>` component:
189189

190190
<<< DEMO ./demo/TabsLazyAll.vue#template{vue-html}
@@ -194,8 +194,6 @@ One can also make all tab's lazy by setting the `lazy` prop on the parent `<BTab
194194
Keyboard navigation is enabled by default for ARIA compliance with tablists when a tab button has
195195
focus.
196196

197-
<NotYetImplemented>no-key-nave prop and keyboard navigations as described below is not fully implemented</NotYetImplemented>
198-
199197
| Keypress | Action |
200198
| --------------------------------------------------------------------- | ---------------------------------------------- |
201199
| <kbd>Left</kbd> or <kbd>Up</kbd> | Activate the previous non-disabled tab |
@@ -221,11 +219,10 @@ browser navigation with TAB key.
221219
Use the `<BTabs>` `v-model` to control which tab is active by setting the `v-model` to the index
222220
(zero-based) of the tab to be shown (see example below).
223221

224-
Alternatively, you can use the `active` prop on each `<BTab>` with the `.sync` modifier to activate
222+
Alternatively, you can use the boolean model named `active` on each `<BTab>` to activate
225223
the tab, or to detect if a particular tab is active.
226224

227-
<NotYetImplemented>.activate() and .deactivate()</NotYetImplemented>
228-
Each `<BTab>`instance also provides two public methods to activate or deactivate the tab. The
225+
Each `<BTab>`instance also exposes to activate or deactivate the tab. The
229226
methods are`.activate()`and`.deactivate()`, respectively. If activation or deactivation fails
230227
(i.e. a tab is disabled or no tab is available to move activation to), then the currently active tab
231228
will remain active and the method will return `false`. You will need a reference to the `<BTab>` in
@@ -254,7 +251,15 @@ It is recommended to use the `disabled` attribute on the `<BTab>` component inst
254251

255252
### External controls using `v-model`
256253

257-
<<< DEMO ./demo/TabsExternalControls.vue
254+
<<< DEMO ./demo/TabsModelControl.vue
255+
256+
### External controls using `active` model
257+
258+
<<< DEMO ./demo/TabsActiveModelControl.vue
259+
260+
### External controls using exposed methods
261+
262+
<<< DEMO ./demo/TabsExposedMethodControl.vue
258263

259264
### Dynamic tabs + tabs-end slot
260265

0 commit comments

Comments
 (0)