@@ -134,6 +134,18 @@ In sticky mode, the tab will be fixed to top when scroll to top.
```
+### Shrink
+
+In shrink mode, the tabs will be shrinked to the left.
+
+```html
+
+
+ content {{ index }}
+
+
+```
+
### Custom title
Use title slot to custom tab title.
@@ -236,6 +248,7 @@ export default {
| border | Whether to show border when `type="line"` | _boolean_ | `false` |
| ellipsis | Whether to ellipsis too long title | _boolean_ | `true` |
| sticky | Whether to use sticky mode | _boolean_ | `false` |
+| shrink `v3.2.8` | Whether to shrink the the tabs to the left | _boolean_ | `false` |
| swipeable | Whether to enable gestures to slide left and right | _boolean_ | `false` |
| lazy-render | Whether to enable tab content lazy render | _boolean_ | `true` |
| scrollspy | Whether to use scrollspy mode | _boolean_ | `false` |
diff --git a/packages/vant/src/tab/README.zh-CN.md b/packages/vant/src/tab/README.zh-CN.md
index a218419bc..7520335c1 100644
--- a/packages/vant/src/tab/README.zh-CN.md
+++ b/packages/vant/src/tab/README.zh-CN.md
@@ -143,6 +143,18 @@ export default {
> Tips: 如果页面顶部有其他内容,可以通过 offset-top 属性设置吸顶时与顶部的距离。
+### 收缩布局
+
+通过 `shrink` 属性可以开启收缩布局,开启后,所有的标签会向左侧收缩对齐。
+
+```html
+
+
+ 内容 {{ index }}
+
+
+```
+
### 自定义标签
通过 `title` 插槽可以自定义标签内容。
@@ -249,6 +261,7 @@ export default {
| border | 是否显示标签栏外边框,仅在 `type="line"` 时有效 | _boolean_ | `false` |
| ellipsis | 是否省略过长的标题文字 | _boolean_ | `true` |
| sticky | 是否使用粘性布局 | _boolean_ | `false` |
+| shrink `v3.2.8` | 是否开启左侧收缩布局 | _boolean_ | `false` |
| swipeable | 是否开启手势左右滑动切换 | _boolean_ | `false` |
| lazy-render | 是否开启延迟渲染(首次切换到标签时才触发内容渲染) | _boolean_ | `true` |
| scrollspy | 是否开启滚动导航 | _boolean_ | `false` |
diff --git a/packages/vant/src/tab/demo/Shrink.vue b/packages/vant/src/tab/demo/Shrink.vue
new file mode 100644
index 000000000..194af34e7
--- /dev/null
+++ b/packages/vant/src/tab/demo/Shrink.vue
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+ {{ t('content') }} {{ index }}
+
+
+
+
+ {{ t('content') }} {{ index }}
+
+
+
+
diff --git a/packages/vant/src/tab/demo/index.vue b/packages/vant/src/tab/demo/index.vue
index 7153f1441..4f648cdae 100644
--- a/packages/vant/src/tab/demo/index.vue
+++ b/packages/vant/src/tab/demo/index.vue
@@ -5,6 +5,7 @@ import VanIcon from '../../icon';
import { ref } from 'vue';
import { useTranslate } from '../../../docs/site/use-translate';
import { Toast } from '../../toast';
+import Shrink from './Shrink.vue';
const t = useTranslate({
'zh-CN': {
@@ -131,6 +132,8 @@ const beforeChange = (name: number) => {
+
+
diff --git a/packages/vant/src/tab/test/__snapshots__/demo.spec.ts.snap b/packages/vant/src/tab/test/__snapshots__/demo.spec.ts.snap
index a198e5382..5d9131313 100644
--- a/packages/vant/src/tab/test/__snapshots__/demo.spec.ts.snap
+++ b/packages/vant/src/tab/test/__snapshots__/demo.spec.ts.snap
@@ -10,7 +10,7 @@ exports[`should render demo and match snapshot 1`] = `
>
+
+
+
+
+
+
+ Tab 1
+
+
+
+
+ Tab 2
+
+
+
+
+ Tab 3
+
+
+
+
+ Tab 4
+
+
+
+
+
+
+
+
+ Content 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Tab 1
+
+
+
+
+ Tab 2
+
+
+
+
+ Tab 3
+
+
+
+
+ Tab 4
+
+
+
+
+
+
+ Content 1
+
+
+
+
+
+
+
+
+
+
@@ -649,7 +831,7 @@ exports[`should render demo and match snapshot 1`] = `
>
@@ -719,7 +901,7 @@ exports[`should render demo and match snapshot 1`] = `
@@ -729,7 +911,7 @@ exports[`should render demo and match snapshot 1`] = `
@@ -739,7 +921,7 @@ exports[`should render demo and match snapshot 1`] = `
@@ -814,7 +996,7 @@ exports[`should render demo and match snapshot 1`] = `
>
@@ -824,7 +1006,7 @@ exports[`should render demo and match snapshot 1`] = `
@@ -834,7 +1016,7 @@ exports[`should render demo and match snapshot 1`] = `
@@ -844,7 +1026,7 @@ exports[`should render demo and match snapshot 1`] = `
@@ -921,7 +1103,7 @@ exports[`should render demo and match snapshot 1`] = `
>
@@ -354,7 +354,7 @@ exports[`swipe switch tab after swiping tab content 1`] = `
@@ -364,7 +364,7 @@ exports[`swipe switch tab after swiping tab content 1`] = `
@@ -431,7 +431,7 @@ exports[`swipe switch tab after swiping tab content 2`] = `
>
@@ -441,7 +441,7 @@ exports[`swipe switch tab after swiping tab content 2`] = `
@@ -451,7 +451,7 @@ exports[`swipe switch tab after swiping tab content 2`] = `
@@ -521,7 +521,7 @@ exports[`swipe switch tab after swiping tab content 3`] = `
>
@@ -531,7 +531,7 @@ exports[`swipe switch tab after swiping tab content 3`] = `
@@ -541,7 +541,7 @@ exports[`swipe switch tab after swiping tab content 3`] = `
diff --git a/packages/vant/src/tab/test/__snapshots__/insert.spec.tsx.snap b/packages/vant/src/tab/test/__snapshots__/insert.spec.tsx.snap
index 010ea8025..2786e8e55 100644
--- a/packages/vant/src/tab/test/__snapshots__/insert.spec.tsx.snap
+++ b/packages/vant/src/tab/test/__snapshots__/insert.spec.tsx.snap
@@ -9,7 +9,7 @@ exports[`should render Tab inside a component correctly 1`] = `
>
diff --git a/packages/vant/src/tabs/TabsTitle.tsx b/packages/vant/src/tabs/TabsTitle.tsx
index 1215b4a2d..a42cf2559 100644
--- a/packages/vant/src/tabs/TabsTitle.tsx
+++ b/packages/vant/src/tabs/TabsTitle.tsx
@@ -14,6 +14,7 @@ export default defineComponent({
color: String,
title: String,
badge: numericProp,
+ shrink: Boolean,
isActive: Boolean,
disabled: Boolean,
controls: String,
@@ -79,10 +80,14 @@ export default defineComponent({
id={props.id}
role="tab"
class={[
- bem({
- active: props.isActive,
- disabled: props.disabled,
- }),
+ bem([
+ props.type,
+ {
+ shrink: props.shrink,
+ active: props.isActive,
+ disabled: props.disabled,
+ },
+ ]),
]}
style={style.value}
tabindex={props.disabled ? undefined : props.isActive ? 0 : -1}
diff --git a/packages/vant/src/tabs/index.less b/packages/vant/src/tabs/index.less
index 8464c40f1..9363e4806 100644
--- a/packages/vant/src/tabs/index.less
+++ b/packages/vant/src/tabs/index.less
@@ -38,6 +38,30 @@
cursor: not-allowed;
}
+ &--shrink {
+ flex: none;
+ padding: 0 var(--van-padding-xs);
+ }
+
+ &--card {
+ color: var(--van-tabs-default-color);
+ border-right: var(--van-border-width-base) solid
+ var(--van-tabs-default-color);
+
+ &:last-child {
+ border-right: none;
+ }
+
+ &.van-tab--active {
+ color: var(--van-white);
+ background-color: var(--van-tabs-default-color);
+ }
+
+ &--disabled {
+ color: var(--van-tab-disabled-text-color);
+ }
+ }
+
&__text {
&--ellipsis {
display: -webkit-box;
@@ -93,6 +117,7 @@
padding-bottom: 15px; /* 15px padding to hide scrollbar in mobile safari */
}
+ &--line&--shrink,
&--line&--complete {
padding-right: var(--van-padding-xs);
padding-left: var(--van-padding-xs);
@@ -104,25 +129,10 @@
margin: 0 var(--van-padding-md);
border: var(--van-border-width-base) solid var(--van-tabs-default-color);
border-radius: var(--van-border-radius-sm);
+ }
- .van-tab {
- color: var(--van-tabs-default-color);
- border-right: var(--van-border-width-base) solid
- var(--van-tabs-default-color);
-
- &:last-child {
- border-right: none;
- }
-
- &.van-tab--active {
- color: var(--van-white);
- background-color: var(--van-tabs-default-color);
- }
-
- &--disabled {
- color: var(--van-tab-disabled-text-color);
- }
- }
+ &--card&--shrink {
+ display: inline-flex;
}
}