Skip to content

Commit c345117

Browse files
committed
- BsButton: improve inner element spacing when dropdown-toggle is enabled.
- BsButton: improve spacing between icon and caret when `default-slot` is empty or undefined and `dropdown-toggle` is enabled. - BsTab: fixed bug that caused `v-if` to not work as expected. - Update CHANGELOG.md - Bump to version v2.1.6
1 parent b0aa2cd commit c345117

File tree

11 files changed

+70
-99
lines changed

11 files changed

+70
-99
lines changed

CHANGELOG.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,23 @@
33
> All notable changes to this project will be documented in this file.
44
55

6+
## v2.1.6
7+
8+
Released: February 01, 2025
9+
10+
### Features & Improvements
11+
12+
- **BsButton**:
13+
- Improve inner element spacing and padding when `dropdown-toggle` is enabled.
14+
- Improve spacing between icon and caret when `default-slot` is **empty** or
15+
**undefined** and `dropdown-toggle` is enabled.
16+
- **BsTooltip**: improve show or hide animation timing.
17+
18+
### Bug Fixes
19+
20+
- **BsTab**: fixed bug that caused `v-if` to not work as expected.
21+
22+
623
## v2.1.5
724

825
Released: December 30, 2024

package.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "vue-mdbootstrap",
3-
"version": "2.1.5",
3+
"version": "2.1.6",
44
"description": "Bootstrap5 Material Design Components for Vue.js",
55
"author": {
66
"name": "Ahmad Fajar",
@@ -84,17 +84,17 @@
8484
"@types/body-scroll-lock": "^3.1.2",
8585
"@types/lodash": "^4.17.13",
8686
"@types/luxon": "^3.4.2",
87-
"@types/node": "^22.10.2",
87+
"@types/node": "^22.13.0",
8888
"@vue/tsconfig": "^0.7.0",
8989
"bootstrap": "5.2.3",
9090
"clean-css-cli": "^5.6.3",
9191
"npm-run-all": "^4.1.5",
9292
"rimraf": "^6.0.1",
9393
"rollup-plugin-dts": "^6.1.1",
94-
"sass": "^1.83.0",
94+
"sass": "^1.83.4",
9595
"terser": "^5.37.0",
96-
"typescript": "^5.7.2",
97-
"vite": "^6.0.6",
96+
"typescript": "^5.7.3",
97+
"vite": "^6.0.11",
9898
"vue-router": "^4.5.0"
9999
},
100100
"browserslist": [

scss/banner.scss

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*!
2-
* Vue MDBootstrap v2.1.5
2+
* Vue MDBootstrap v2.1.6
33
* Released under the BSD-3 License.
44
* Copyright Ahmad Fajar (https://ahmadfajar.github.io).
55
*/

src/components/Button/BsButton.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ export default defineComponent<TBsButton>({
4949
h<TBsButtonInner>(
5050
BsButtonInner,
5151
{
52+
class: { 'empty-text': !slots.default && thisProps.dropdownToggle },
5253
dropdownToggle: props.dropdownToggle,
5354
// @ts-ignore
5455
iconMode: (thisProps.mode === 'icon') as Prop<boolean>,

src/components/Button/button.scss

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -106,16 +106,22 @@
106106
@include borders.radius(var(--#{vars.$prefix-bs}btn-border-radius));
107107
display: flex;
108108
padding: 0;
109+
}
109110

110-
&.dropdown-toggle {
111-
&::after {
112-
align-self: center;
113-
margin-right: 0.875rem;
114-
margin-left: 0;
115-
}
111+
> .dropdown-toggle {
112+
&::after {
113+
align-self: center;
114+
margin-right: 0.875rem;
115+
margin-left: 0;
116+
}
117+
118+
> .#{vars.$prefix}btn-inner {
119+
padding-right: calc(var(--#{vars.$prefix-bs}btn-state-padding-x) / 2);
120+
}
116121

117-
> .#{vars.$prefix}btn-inner {
118-
padding-right: calc(var(--#{vars.$prefix-bs}btn-state-padding-x) - 0.2rem);
122+
&.empty-text {
123+
> .has-icon {
124+
padding-right: vars.$padding-xs;
119125
}
120126
}
121127
}

src/components/Tabs/BsTab.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,13 @@ export default defineComponent<TBsTabPanel>({
3232
expose({ isActive });
3333

3434
const classNames = computed(() => {
35-
// console.log(`computed-tab-${thisProps.id}:active`, isActive.value);
3635
return ['tab-pane', isActive.value === true ? 'active' : ''];
3736
});
3837

3938
onBeforeMount(() => {
4039
const vm = getCurrentInstance();
4140
if (vm && tabProvider) {
41+
// console.log('Registering tabPanel:', thisProps.id);
4242
tabProvider.registerTabPanel(vm);
4343
}
4444
});

src/components/Tabs/BsTabs.ts

Lines changed: 6 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,9 @@
1-
import type { ComponentInternalInstance } from 'vue';
2-
import {
3-
computed,
4-
defineComponent,
5-
nextTick,
6-
onMounted,
7-
provide,
8-
ref,
9-
shallowRef,
10-
watch,
11-
} from 'vue';
12-
import Helper from '../../utils/Helper';
13-
import { useRenderTabView, useTabViewClassNames } from './mixins/tabsApi';
14-
import { tabsProps } from './mixins/tabsProps';
15-
import TabsProvider from './mixins/TabsProvider';
16-
import type { TBsTabs, TOrientation, TTabsOptionProps } from './types';
1+
import { useRenderTabView, useTabViewClassNames } from '@/components/Tabs/mixins/tabsApi.ts';
2+
import { tabsProps } from '@/components/Tabs/mixins/tabsProps.ts';
3+
import TabsProvider from '@/components/Tabs/mixins/TabsProvider';
4+
import type { TBsTabs, TOrientation, TTabsOptionProps } from '@/components/Tabs/types';
5+
import Helper from '@/utils/Helper';
6+
import { computed, defineComponent, nextTick, onMounted, provide, ref, watch } from 'vue';
177

188
export default defineComponent<TBsTabs>({
199
name: 'BsTabs',
@@ -30,7 +20,6 @@ export default defineComponent<TBsTabs>({
3020
],
3121
setup(props, { emit, slots }) {
3222
const thisProps = props as Readonly<TTabsOptionProps>;
33-
const tabPanels = shallowRef<ComponentInternalInstance[]>([]);
3423
const tabProvider = new TabsProvider(
3524
thisProps,
3625
emit,
@@ -47,15 +36,6 @@ export default defineComponent<TBsTabs>({
4736
const tagName = computed<string>(() => (thisProps.variant === 'pills' ? 'ul' : 'div'));
4837
const tabViewClasses = computed(() => useTabViewClassNames(thisProps, orientation));
4938

50-
watch(
51-
() => [tabProvider.tabPanels, thisProps.variant, thisProps.tabPosition],
52-
([panels]) => {
53-
if (Array.isArray(panels)) {
54-
// console.log(`${uid}-panel-length:`, panels.length);
55-
nextTick().then(() => (tabPanels.value = Array.from(panels)));
56-
}
57-
}
58-
);
5939
watch(
6040
() => thisProps.modelValue,
6141
(value) => {
@@ -65,7 +45,6 @@ export default defineComponent<TBsTabs>({
6545
);
6646
onMounted(() => {
6747
nextTick().then(() => {
68-
tabPanels.value = tabProvider.tabPanels;
6948
tabProvider.setActiveTab(thisProps.modelValue as string | number);
7049
});
7150
});
@@ -77,7 +56,6 @@ export default defineComponent<TBsTabs>({
7756
orientation,
7857
tagName,
7958
tabViewClasses,
80-
tabPanels,
8159
tabSlidingRef,
8260
scrollOffset,
8361
tabProvider

src/components/Tabs/mixins/TabsProvider.ts

Lines changed: 20 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -8,29 +8,31 @@ import type {
88
TTabsVariant,
99
} from '@/types';
1010
import Helper from '@/utils/Helper';
11-
import type { ComponentInternalInstance, Ref } from 'vue';
12-
import { isRef } from 'vue';
11+
import type { ComponentInternalInstance, Ref, ShallowReactive } from 'vue';
12+
import { isRef, shallowReactive } from 'vue';
1313

1414
/**
1515
* Class TabsProvider which is used for BsTab's component dependency injection.
1616
*
1717
* @author Ahmad Fajar
18-
* @since 22/11/2022, modified: 18/08/2024 19:57
18+
* @since 22/11/2022, modified: 01/02/2025 16:18
1919
*/
2020
class TabsProvider {
21-
private _tabItems: ComponentInternalInstance[];
22-
private _tabPanels: ComponentInternalInstance[];
2321
private _activeTab: ComponentInternalInstance | undefined;
2422
private _activeTabIndex: number | undefined;
2523
private _props: TTabsBaseProps;
2624
private readonly _emit: TEmitFn;
25+
public tabItems: ShallowReactive<ComponentInternalInstance[]>;
26+
public tabPanels: ShallowReactive<ComponentInternalInstance[]>;
2727

2828
constructor(tabConfig: Readonly<TTabsBaseProps>, emitter: TEmitFn, activeTab?: number) {
2929
this._props = tabConfig;
30-
this._tabItems = [];
31-
this._tabPanels = [];
30+
this._activeTab = undefined;
3231
this._activeTabIndex = activeTab;
3332
this._emit = emitter;
33+
34+
this.tabItems = shallowReactive<ComponentInternalInstance[]>([]);
35+
this.tabPanels = shallowReactive<ComponentInternalInstance[]>([]);
3436
}
3537

3638
get activeTab(): ComponentInternalInstance | undefined {
@@ -69,22 +71,14 @@ class TabsProvider {
6971
return this._props.variant;
7072
}
7173

72-
get tabItems(): ComponentInternalInstance[] {
73-
return this._tabItems;
74-
}
75-
76-
get tabPanels(): ComponentInternalInstance[] {
77-
return this._tabPanels;
78-
}
79-
8074
/**
8175
* Register a TabIem.
8276
*
8377
* @param {ComponentInternalInstance} item The TabIem item
8478
* @returns {number} The TabIem index position
8579
*/
8680
registerTabItem(item: ComponentInternalInstance): number {
87-
return this._tabItems.push(item);
81+
return this.tabItems.push(item);
8882
}
8983

9084
/**
@@ -94,7 +88,7 @@ class TabsProvider {
9488
* @returns {number} The TabPanel index position
9589
*/
9690
registerTabPanel(item: ComponentInternalInstance): number {
97-
return this._tabPanels.push(item);
91+
return this.tabPanels.push(item);
9892
}
9993

10094
/**
@@ -103,8 +97,8 @@ class TabsProvider {
10397
* @returns {void}
10498
*/
10599
unRegisterAll(): void {
106-
this._tabItems = [];
107-
this._tabPanels = [];
100+
this.tabItems = [];
101+
this.tabPanels = [];
108102
}
109103

110104
/**
@@ -115,20 +109,18 @@ class TabsProvider {
115109
*/
116110
unRegisterTab(key: string | number): void {
117111
if (Helper.isNumber(key)) {
118-
this._tabItems.splice(key, 1);
119-
this._tabPanels.splice(key, 1);
112+
this.tabItems.splice(key, 1);
113+
this.tabPanels.splice(key, 1);
120114
} else {
121-
let idx = this._tabPanels.findIndex(
115+
let idx = this.tabPanels.findIndex(
122116
(el) => (el.props as TTabItemOptionProps).id === key
123117
);
124118
if (idx === -1) {
125-
idx = this._tabItems.findIndex(
126-
(el) => (el.props as TTabItemOptionProps).id === key
127-
);
119+
idx = this.tabItems.findIndex((el) => (el.props as TTabItemOptionProps).id === key);
128120
}
129121

130-
this._tabItems.splice(idx, 1);
131-
this._tabPanels.splice(idx, 1);
122+
this.tabItems.splice(idx, 1);
123+
this.tabPanels.splice(idx, 1);
132124
}
133125
}
134126

@@ -155,7 +147,7 @@ class TabsProvider {
155147
Helper.isString(key) && pid === `tabItem-${key}`;
156148
}
157149
});
158-
this.tabPanels.forEach((el, idx) => {
150+
this.tabPanels.forEach((el: ShallowReactive<ComponentInternalInstance>, idx) => {
159151
const pid = (el.props as TTabItemOptionProps).id;
160152

161153
if ((Helper.isNumber(key) && key === idx) || (Helper.isString(key) && key === pid)) {
@@ -177,7 +169,6 @@ class TabsProvider {
177169
(el.exposed as TRecord).isActive = false;
178170
}
179171
}
180-
// console.log(`tabPane-${pid}:active`, (<TTabItemOptionProps>el.props).active);
181172
});
182173
}
183174

src/components/Tabs/mixins/tabsApi.ts

Lines changed: 5 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,7 @@ import BsTabItem from '@/components/Tabs/BsTabItem';
44
import BsTabLabel from '@/components/Tabs/BsTabLabel';
55
import TabsProvider from '@/components/Tabs/mixins/TabsProvider';
66
import { Touch } from '@/directives';
7-
import {
8-
cssPrefix,
9-
useHasLink,
10-
useHasRouter,
11-
useMergeClass,
12-
useRenderRouter,
13-
} from '@/mixins/CommonApi';
7+
import { cssPrefix, useHasLink, useHasRouter, useMergeClass, useRenderRouter } from '@/mixins/CommonApi';
148
import type {
159
IVNode,
1610
TBsIcon,
@@ -24,15 +18,7 @@ import type {
2418
TTabsOptionProps,
2519
} from '@/types';
2620
import Helper from '@/utils/Helper';
27-
import type {
28-
ComponentInternalInstance,
29-
ComputedRef,
30-
Prop,
31-
Ref,
32-
ShallowRef,
33-
Slots,
34-
VNode,
35-
} from 'vue';
21+
import type { ComputedRef, Prop, Ref, Slots, VNode } from 'vue';
3622
import { createCommentVNode, h, normalizeClass, toDisplayString, withDirectives } from 'vue';
3723

3824
export function useTabViewClassNames(
@@ -331,7 +317,6 @@ function renderVerticalTabView(
331317
props: Readonly<TTabsOptionProps>,
332318
tagName: ComputedRef<string>,
333319
tabClasses: ComputedRef<string[]>,
334-
tabItems: ShallowRef<ComponentInternalInstance[]>,
335320
provider: TabsProvider
336321
): VNode {
337322
return h(
@@ -357,7 +342,7 @@ function renderVerticalTabView(
357342
role: 'tablist',
358343
'aria-orientation': 'vertical',
359344
},
360-
tabItems.value.map((it, idx) => {
345+
provider.tabPanels.map((it, idx) => {
361346
return h<TBsTabItem>(BsTabItem, {
362347
key: `tab-item-${idx}`,
363348
...createTabItemProps(
@@ -434,7 +419,6 @@ function renderHorizontalTabView(
434419
props: Readonly<TTabsOptionProps>,
435420
tagName: ComputedRef<string>,
436421
tabClasses: ComputedRef<string[]>,
437-
tabItems: ShallowRef<ComponentInternalInstance[]>,
438422
sliderRef: Ref<HTMLElement | undefined>,
439423
scrollOffset: Ref<number>,
440424
provider: TabsProvider
@@ -470,7 +454,7 @@ function renderHorizontalTabView(
470454
: '',
471455
],
472456
},
473-
tabItems.value.map((it, idx) =>
457+
provider.tabPanels.map((it, idx) =>
474458
h<TBsTabItem>(BsTabItem, {
475459
key: `tab-item-${idx}`,
476460
...createTabItemProps(
@@ -513,20 +497,18 @@ export function useRenderTabView(
513497
orientation: ComputedRef<TOrientation>,
514498
tagName: ComputedRef<string>,
515499
tabClasses: ComputedRef<string[]>,
516-
tabItems: ShallowRef<ComponentInternalInstance[]>,
517500
sliderRef: Ref<HTMLElement | undefined>,
518501
scrollOffset: Ref<number>,
519502
provider: TabsProvider
520503
): VNode {
521504
if (orientation.value === 'vertical') {
522-
return renderVerticalTabView(slots, props, tagName, tabClasses, tabItems, provider);
505+
return renderVerticalTabView(slots, props, tagName, tabClasses, provider);
523506
} else {
524507
return renderHorizontalTabView(
525508
slots,
526509
props,
527510
tagName,
528511
tabClasses,
529-
tabItems,
530512
sliderRef,
531513
scrollOffset,
532514
provider

0 commit comments

Comments
 (0)