导航类

标签栏

当内容需要分组并在不同模块页面中展示,可使用 Tabs 标签栏目对不同的组/页之间进行切换

代码演示

如何引入

<script setup lang="ts">
    import { Tabs, TabPane } from '@fibrous/semi-ui-vue';
</script>

基本用法

标签栏支持四种样式的显示:线条式,按钮式,卡片式,斜线式。默认选中第一个启用的标签页。
标签页支持两种传入方式,两者渲染流程上有所区别:

  • 通过 tabList 传入标签页对象的数组,当使用 tabList 时每次只渲染当前传入的节点
  • 或使用 <TabPane> 逐项显式传入,使用 <TabPane> 时默认会渲染所有面板,可以通过将 keepDOM 设为 false 只渲染当前面板,此时不会有动画效果。

Vue 中标签页的文字写在 <TabPane> 的 #tab 插槽,图标写在 #icon 插槽。tabList 的数据项只放数据(itemKey、tab、disabled、closable),需要节点时使用 Tabs 的 #tab、#icon 作用域插槽,参数为 { item, index },不提供插槽时显示该项的 tab 文本。只要传了数组(含空数组),默认插槽就是当前标签页的内容,不再读作 TabPane。

文档

Semi Design 是由抖音前端团队与 UED 团队共同设计开发并维护的设计系统。设计系统包含设计语言以及一整套可复用的前端组件,帮助设计师与开发者更容易地打造高质量的、用户体验一致的、符合设计规范的 Web 应用。

区别于其他的设计系统而言,Semi Design 以用户中心、内容优先、设计人性化为设计理念,具有以下优势:

  • Semi Design 以内容优先进行设计。

  • 更容易地自定义主题。

  • 适用国际化场景。

  • 效率场景加入人性化关怀。

代码
<script setup lang="ts">
    import { TabPane, Tabs } from '@fibrous/semi-ui-vue';

    const paragraphStyle = { lineHeight: 1.8 };
    const questionStyle = { lineHeight: 1.8, color: 'var(--semi-color-text-0)', fontWeight: 600 };
    const answerStyle = { lineHeight: 1.8, color: 'var(--semi-color-text-1)' };
    const codeStyle = {
        margin: '24px 0',
        padding: '20px',
        border: 'none',
        whiteSpace: 'normal',
        borderRadius: 'var(--semi-border-radius-medium)',
        color: 'var(--semi-color-text-1)',
        backgroundColor: 'var(--semi-color-fill-0)',
    };
</script>

<template>
    <div>
        <Tabs type="line">
            <TabPane itemKey="1">
                <template #tab>文档</template>
                <h3>文档</h3>
                <p :style="paragraphStyle">Semi Design 是由抖音前端团队与 UED 团队共同设计开发并维护的设计系统。设计系统包含设计语言以及一整套可复用的前端组件,帮助设计师与开发者更容易地打造高质量的、用户体验一致的、符合设计规范的 Web 应用。</p>
                <p :style="paragraphStyle">区别于其他的设计系统而言,Semi Design 以用户中心、内容优先、设计人性化为设计理念,具有以下优势:</p>
                <ul>
                    <li>
                        <p>Semi Design 以内容优先进行设计。</p>
                    </li>
                    <li>
                        <p>更容易地自定义主题。</p>
                    </li>
                    <li>
                        <p>适用国际化场景。</p>
                    </li>
                    <li>
                        <p>效率场景加入人性化关怀。</p>
                    </li>
                </ul>
            </TabPane>
            <TabPane itemKey="2">
                <template #tab>快速起步</template>
                <h3>快速起步</h3>
                <pre :style="codeStyle"><code>yarn add @fibrous/semi-ui-vue</code></pre>
            </TabPane>
            <TabPane itemKey="3">
                <template #tab>帮助</template>
                <h3>帮助</h3>
                <p :style="questionStyle">Q:有新组件需求、或者现有组件feature不能满足业务需求?</p>
                <p :style="answerStyle">右上角问题反馈,提交issue,label选择Feature Request / New Component Request 我们会高优处理这些需求。</p>
                <p :style="questionStyle">Q:对组件的使用有疑惑?</p>
                <p :style="answerStyle">欢迎进我们的客服lark群进行咨询提问。</p>
            </TabPane>
        </Tabs>
    </div>
</template>
文档
代码
<script setup lang="ts">
    import { TabPane, Tabs } from '@fibrous/semi-ui-vue';
</script>

<template>
    <Tabs type="button">
        <TabPane itemKey="1">
            <template #tab>文档</template>
            文档
        </TabPane>
        <TabPane itemKey="2">
            <template #tab>快速起步</template>
            快速起步
        </TabPane>
        <TabPane itemKey="3">
            <template #tab>帮助</template>
            帮助
        </TabPane>
    </Tabs>
</template>
文档
代码
<script setup lang="ts">
    import { ref } from 'vue';
    import { Tabs } from '@fibrous/semi-ui-vue';

    const contentList = ['文档', '快速起步', '帮助'];
    const tabList = [
        { tab: '文档', itemKey: '1' },
        { tab: '快速起步', itemKey: '2' },
        { tab: '帮助', itemKey: '3' },
    ];
    const key = ref('1');
</script>

<template>
    <Tabs v-model:activeKey="key" :tabList="tabList" type="card">
        <div>{{ contentList[Number(key) - 1] }}</div>
    </Tabs>
</template>
文档
代码
<script setup lang="ts">
    import { ref } from 'vue';
    import { Tabs } from '@fibrous/semi-ui-vue';

    const contentList = ['文档', '快速起步', '帮助'];
    const tabList = [
        { tab: '文档', itemKey: '1' },
        { tab: '快速起步', itemKey: '2' },
        { tab: '帮助', itemKey: '3' },
    ];
    const key = ref('1');
</script>

<template>
    <Tabs v-model:activeKey="key" :tabList="tabList" type="slash">
        <div>{{ contentList[Number(key) - 1] }}</div>
    </Tabs>
</template>

带图标的

有图标的标签栏。

文档
代码
<script setup lang="ts">
    import { IconFile, IconGlobe, IconHelpCircle } from '@fibrous/semi-icons-vue';
    import { TabPane, Tabs } from '@fibrous/semi-ui-vue';
</script>

<template>
    <Tabs>
        <TabPane itemKey="1">
            <template #tab>
                <span><IconFile />文档</span>
            </template>
            文档
        </TabPane>
        <TabPane itemKey="2">
            <template #tab>
                <span><IconGlobe />快速起步</span>
            </template>
            快速起步
        </TabPane>
        <TabPane itemKey="3">
            <template #tab>
                <span><IconHelpCircle />帮助</span>
            </template>
            帮助
        </TabPane>
    </Tabs>
</template>

更多选项收入 More 展示

支持将多余 Tab 合并为「更多」下拉菜单,more 传入数字即可,数字表示收入下拉菜单的 Tab 数量。

Content of card tab 0
代码
<script setup lang="ts">
    import { TabPane, Tabs } from '@fibrous/semi-ui-vue';

    const indexes = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
</script>

<template>
    <Tabs :more="4" :style="{ width: '60%', margin: '20px' }" type="card">
        <TabPane v-for="i in indexes" :key="i" :itemKey="`Tab-${i}`">
            <template #tab>Tab-{{ i }}</template>
            Content of card tab {{ i }}
        </TabPane>
    </Tabs>
</template>

也支持高级配置,向 more 传入对象,内可传入

  • count: 表示收入下拉菜单的 Tab 数量
  • dropdownProps: 传入 Dropdown Props,会被透传到下拉菜单

「更多」触发器使用 #more 插槽自定义,下拉菜单的内容使用 #moreContent="{ items }" 作用域插槽自定义,items 是收入菜单的标签页。

Content of card tab 0
代码
<script setup lang="ts">
    import { Button, TabPane, Tabs, type TabsMore } from '@fibrous/semi-ui-vue';

    const indexes = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
    const more: TabsMore = { count: 4, dropdownProps: { trigger: 'click', position: 'bottomRight' } };
</script>

<template>
    <Tabs :more="more" :style="{ width: '60%', margin: '20px' }" type="card">
        <template #more>
            <Button type="tertiary">Click to show More</Button>
        </template>
        <TabPane v-for="i in indexes" :key="i" :itemKey="`Tab-${i}`">
            <template #tab>Tab-{{ i }}</template>
            Content of card tab {{ i }}
        </TabPane>
    </Tabs>
</template>

垂直的标签栏

type 为 line, card, button 支持水平和垂直两种模式,tabPosition='left|top', 默认为 top。type 为 slash 仅支持水平模式,无需设置。



文档

Semi Design 是由抖音前端团队与 UED 团队共同设计开发并维护的设计系统。设计系统包含设计语言以及一整套可复用的前端组件,帮助设计师与开发者更容易地打造高质量的、用户体验一致的、符合设计规范的 Web 应用。

区别于其他的设计系统而言,Semi Design 以用户中心、内容优先、设计人性化为设计理念,具有以下优势:

代码
<script setup lang="ts">
    import { ref } from 'vue';
    import { IconFile, IconGlobe, IconHelpCircle } from '@fibrous/semi-icons-vue';
    import { Radio, RadioGroup, TabPane, Tabs, type RadioValue, type TabType } from '@fibrous/semi-ui-vue';

    const type = ref<RadioValue | undefined>('line');
    const contentStyle = { padding: '0 24px' };
    const paragraphStyle = { lineHeight: 1.8 };
    const questionStyle = { lineHeight: 1.8, color: 'var(--semi-color-text-0)', fontWeight: 600 };
    const answerStyle = { lineHeight: 1.8, color: 'var(--semi-color-text-1)' };
    const codeStyle = {
        margin: '24px 0',
        padding: '20px',
        border: 'none',
        whiteSpace: 'normal',
        borderRadius: '6px',
        color: 'var(--semi-color-text-1)',
        backgroundColor: 'var(--semi-color-fill-0)',
    };
</script>

<template>
    <RadioGroup v-model="type" :style="{ display: 'flex', width: '200px', justifyContent: 'center' }" type="button">
        <Radio value="line">Line</Radio>
        <Radio value="card">Card</Radio>
        <Radio value="button">Button</Radio>
    </RadioGroup>
    <br />
    <br />
    <Tabs tabPosition="left" :type="type as TabType">
        <TabPane itemKey="1">
            <template #tab>
                <span><IconFile />文档</span>
            </template>
            <div :style="contentStyle">
                <h3>文档</h3>
                <p :style="paragraphStyle">Semi Design 是由抖音前端团队与 UED 团队共同设计开发并维护的设计系统。设计系统包含设计语言以及一整套可复用的前端组件,帮助设计师与开发者更容易地打造高质量的、用户体验一致的、符合设计规范的 Web 应用。</p>
                <p :style="paragraphStyle">区别于其他的设计系统而言,Semi Design 以用户中心、内容优先、设计人性化为设计理念,具有以下优势:</p>
            </div>
        </TabPane>
        <TabPane itemKey="2">
            <template #tab>
                <span><IconGlobe />快速起步</span>
            </template>
            <div :style="contentStyle">
                <h3>快速起步</h3>
                <pre :style="codeStyle"><code>yarn add @fibrous/semi-ui-vue</code></pre>
            </div>
        </TabPane>
        <TabPane itemKey="3">
            <template #tab>
                <span><IconHelpCircle />帮助</span>
            </template>
            <div :style="contentStyle">
                <h3>帮助</h3>
                <p :style="questionStyle">Q:有新组件需求、或者现有组件feature不能满足业务需求?</p>
                <p :style="answerStyle">右上角问题反馈,提交issue,label选择Feature Request / New Component Request 我们会高优处理这些需求。</p>
                <p :style="questionStyle">Q:对组件的使用有疑惑?</p>
                <p :style="answerStyle">欢迎进我们的客服lark群进行咨询提问。</p>
            </div>
        </TabPane>
    </Tabs>
</template>

滚动折叠

通过设置 collapsible 可以支持滚动折叠,目前只支持 horizontal 模式。

Content of card tab 0
代码
<script setup lang="ts">
    import { TabPane, Tabs } from '@fibrous/semi-ui-vue';

    const indexes = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
</script>

<template>
    <Tabs collapsible :style="{ width: '60%', margin: '20px' }" type="card">
        <TabPane v-for="i in indexes" :key="i" :itemKey="`Tab-${i}`">
            <template #tab>Tab-{{ i }}</template>
            Content of card tab {{ i }}
        </TabPane>
    </Tabs>
</template>

自定义滚动箭头渲染

通过 #arrow 作用域插槽修改滚动折叠模式下,左右切换箭头的渲染,参数为溢出的 items、位置 position、点击处理函数 onClick,以及默认箭头 defaultNode(可用 <component :is="defaultNode" /> 渲染)。

Content of card tab 0
代码
<script setup lang="ts">
    import { ref } from 'vue';
    import { Dropdown, TabPane, Tabs } from '@fibrous/semi-ui-vue';

    const activeKey = ref('Tab-0');
    const indexes = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
    const arrowStyle = {
        width: '32px',
        height: '32px',
        margin: '0 12px',
        display: 'flex',
        justifyContent: 'center',
        alignItems: 'center',
        padding: '0',
        border: 'none',
        borderRadius: '100%',
        background: 'var(--semi-grey-1)',
        color: 'var(--semi-color-text)',
        fontFamily: 'inherit',
        fontSize: 'inherit',
        cursor: 'pointer',
    };
</script>

<template>
    <Tabs v-model:activeKey="activeKey" collapsible :style="{ width: '50%', margin: '20px' }" type="card">
        <template #arrow="{ items, position, onClick }">
            <Dropdown>
                <button :style="arrowStyle" type="button" @click="onClick">
                    {{ position === 'start' ? '←' : '→' }}
                </button>
                <template #content>
                    <Dropdown.Menu>
                        <Dropdown.Item v-for="item in items" :key="item.itemKey" @click="activeKey = item.itemKey">
                            {{ item.itemKey }}
                        </Dropdown.Item>
                    </Dropdown.Menu>
                </template>
            </Dropdown>
        </template>
        <TabPane v-for="i in indexes" :key="i" :itemKey="`Tab-${i}`">
            <template #tab>Tab-{{ i }}</template>
            Content of card tab {{ i }}
        </TabPane>
    </Tabs>
</template>

修改切换箭头的渲染位置

通过 arrowPosition 来修改溢出指示器的位置,可选 start both end

Content of card tab 0
Content of card tab 0
Content of card tab 0
代码
<script setup lang="ts">
    import { TabPane, Tabs } from '@fibrous/semi-ui-vue';

    const positions = ['start', 'both', 'end'] as const;
    const indexes = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
</script>

<template>
    <Tabs v-for="position in positions" :key="position" :arrowPosition="position" collapsible :style="{ width: '60%', margin: '20px' }" type="card">
        <TabPane v-for="i in indexes" :key="i" :itemKey="`Tab-${i}`">
            <template #tab>Tab-{{ i }}</template>
            Content of card tab {{ i }}
        </TabPane>
    </Tabs>
</template>

自动溢出检测

通过设置 collapsible="auto" 可以启用自动溢出检测功能。组件会自动检测 Tab 是否溢出容器:

  • 当 Tab 超出容器宽度或发生换行时,自动启用折叠模式(显示左右箭头)
  • 当容器宽度增加或 Tab 数量减少后,所有 Tab 可以完整显示时,自动退出折叠模式

这个功能避免了开发者需要手动判断是否需要折叠的问题,特别适用于响应式布局场景。

当前 Tab 数量: 8

collapsible="auto" - 自动检测溢出

Content of Tab 1

固定宽度 400px,测试较窄容器

Content of Tab 1
代码
<script setup lang="ts">
    import { computed, ref } from 'vue';
    import { Button, TabPane, Tabs } from '@fibrous/semi-ui-vue';

    const count = ref(8);
    const indexes = computed(() => Array.from({ length: count.value }, (_, i) => i));

    const boxStyle = { border: '1px solid var(--semi-color-border)', padding: '12px' };
    const noteStyle = { marginBottom: '8px', color: 'var(--semi-color-text-2)', fontSize: '12px' };
</script>

<template>
    <div>
        <div :style="{ marginBottom: '12px' }">
            <Button :style="{ marginRight: '8px' }" @click="count = Math.max(3, count - 2)">减少 Tab</Button>
            <Button @click="count = Math.min(15, count + 2)">增加 Tab</Button>
            <span :style="{ marginLeft: '12px' }">当前 Tab 数量: {{ count }}</span>
        </div>

        <div :style="{ ...boxStyle, marginBottom: '16px' }">
            <p :style="noteStyle">collapsible="auto" - 自动检测溢出</p>
            <Tabs collapsible="auto" type="card">
                <TabPane v-for="i in indexes" :key="i" :itemKey="`${i}`">
                    <template #tab>Tab-{{ i + 1 }}</template>
                    Content of Tab {{ i + 1 }}
                </TabPane>
            </Tabs>
        </div>

        <div :style="{ ...boxStyle, maxWidth: '400px' }">
            <p :style="noteStyle">固定宽度 400px,测试较窄容器</p>
            <Tabs collapsible="auto" type="card">
                <TabPane v-for="i in indexes" :key="i" :itemKey="`${i}`">
                    <template #tab>Tab-{{ i + 1 }}</template>
                    Content of Tab {{ i + 1 }}
                </TabPane>
            </Tabs>
        </div>
    </div>
</template>

禁用

禁用标签栏中的某一个标签页。

文档
代码
<script setup lang="ts">
    import { TabPane, Tabs } from '@fibrous/semi-ui-vue';
</script>

<template>
    <Tabs defaultActiveKey="1">
        <TabPane itemKey="1">
            <template #tab>文档</template>
            文档
        </TabPane>
        <TabPane disabled itemKey="2">
            <template #tab>快速起步</template>
            快速起步
        </TabPane>
        <TabPane itemKey="3">
            <template #tab>帮助</template>
            帮助
        </TabPane>
    </Tabs>
</template>

标签栏内容扩展

使用 #tabBarExtraContent 插槽可以在标签栏右侧添加附加操作。

文档
代码
<script setup lang="ts">
    import { Button, TabPane, Tabs } from '@fibrous/semi-ui-vue';

    function onExtraClick() {
        alert('you have clicked me!');
    }
</script>

<template>
    <Tabs defaultActiveKey="1">
        <template #tabBarExtraContent>
            <Button @click="onExtraClick">Extra Action</Button>
        </template>
        <TabPane itemKey="1">
            <template #tab>文档</template>
            文档
        </TabPane>
        <TabPane itemKey="2">
            <template #tab>快速起步</template>
            快速起步
        </TabPane>
        <TabPane itemKey="3">
            <template #tab>帮助</template>
            帮助
        </TabPane>
    </Tabs>
</template>

标签栏二次封装

使用 #tabBar="{ tabBarProps, tabBar }" 作用域插槽可对标签栏进行二次封装。tabBarProps 只含数据(见下方 TabBarProps),tabBar 是默认标签栏节点,用 <component :is="tabBar" /> 渲染。

用 #tabBar 完全替换标签栏时,Tabs 的 aria-label、aria-labelledby 不会落到你自己的元素上:可访问名称写在自定义的 role="tablist" 元素上。TabPane 的 #tab 为纯文本时,tabBarProps.list 的对应项才带 tab 文本。

这是二次封装的Tab Bar,当前ActiveKey:1
文档
代码
<script setup lang="ts">
    import { TabPane, Tabs } from '@fibrous/semi-ui-vue';
</script>

<template>
    <Tabs defaultActiveKey="1">
        <template #tabBar="{ tabBarProps, tabBar }">
            <div class="tab-bar-box">
                这是二次封装的Tab Bar,当前ActiveKey:{{ tabBarProps.activeKey }}
                <component :is="tabBar" />
            </div>
        </template>
        <TabPane itemKey="1">
            <template #tab>文档</template>
            文档
        </TabPane>
        <TabPane itemKey="2">
            <template #tab>快速起步</template>
            快速起步
        </TabPane>
        <TabPane itemKey="3">
            <template #tab>帮助</template>
            帮助
        </TabPane>
    </Tabs>
</template>

拖拽排序

通过 #tabBar 插槽,在自己的 role="tablist" 元素里用 TabItem 渲染各个标签,即可结合拖拽实现标签栏的排序。TabItem 在 Tabs 内点击时会自行选中所在的标签页,draggable、拖放事件等原生属性与监听落在它的根元素上。示例使用浏览器原生拖放,只支持指针操作;需要键盘排序时可以改用 @dnd-kit/dom 等支持键盘的拖拽库。

文档内容
代码
<script setup lang="ts">
    import { ref } from 'vue';
    import { TabItem, TabPane, Tabs } from '@fibrous/semi-ui-vue';

    const activeKey = ref('1');
    const items = ref([
        { itemKey: '1', tab: '文档', content: '文档内容' },
        { itemKey: '2', tab: '表格', content: '表格内容' },
        { itemKey: '3', tab: '幻灯片', content: '幻灯片内容' },
        { itemKey: '4', tab: '表单', content: '表单内容' },
    ]);

    // HTML5 drag and drop on the TabItems: the website has no @dnd-kit/vue, and a Vue sortable list would wrap each tab
    // in a button-role element that nests focusable tabs. Known limit: pointer only; use dnd-kit for keyboard sorting.
    const draggingKey = ref<string | null>(null);
    const moveTo = (targetKey: string) => {
        const from = items.value.findIndex((item) => item.itemKey === draggingKey.value);
        const to = items.value.findIndex((item) => item.itemKey === targetKey);
        if (from < 0 || to < 0 || from === to) return;
        const [moved] = items.value.splice(from, 1);
        items.value.splice(to, 0, moved);
    };
</script>

<template>
    <Tabs v-model:activeKey="activeKey" type="line">
        <!-- the bar keeps Semi's own .semi-tabs-bar shell; the TabItems inside select their Tabs by themselves -->
        <template #tabBar>
            <div aria-orientation="horizontal" class="semi-tabs-bar semi-tabs-bar-line semi-tabs-bar-top" role="tablist">
                <TabItem
                    v-for="item in items"
                    :key="item.itemKey"
                    draggable="true"
                    :itemKey="item.itemKey"
                    :selected="activeKey === item.itemKey"
                    :style="{ cursor: 'grab', opacity: draggingKey === item.itemKey ? 0.5 : 1, display: 'inline-flex' }"
                    @dragend="draggingKey = null"
                    @dragenter.prevent="moveTo(item.itemKey)"
                    @dragover.prevent
                    @dragstart="draggingKey = item.itemKey"
                >
                    <template #tab>{{ item.tab }}</template>
                </TabItem>
            </div>
        </template>
        <TabPane v-for="item in items" :key="item.itemKey" :itemKey="item.itemKey">
            <div :style="{ padding: '20px' }">{{ item.content }}</div>
        </TabPane>
    </Tabs>
</template>

动态更新

通过绑定事件,可以使标签栏动态更新。

Content of Tab Pane 1
代码
<script setup lang="ts">
    import { ref } from 'vue';
    import { Button, ButtonGroup, TabPane, Tabs } from '@fibrous/semi-ui-vue';

    let newTabIndex = 0;
    const panes = ref([
        { title: 'Tab 1', content: 'Content of Tab Pane 1', itemKey: '1' },
        { title: 'Tab 2', content: 'Content of Tab Pane 2', itemKey: '2' },
    ]);
    const activeKey = ref('1');

    const add = () => {
        const index = newTabIndex++;
        panes.value.push({ title: `New Tab ${index}`, content: 'New Tab Pane', itemKey: `newTab${index}` });
        activeKey.value = `newTab${index}`;
    };

    const remove = () => {
        if (panes.value.length > 1) {
            panes.value.pop();
            activeKey.value = panes.value[panes.value.length - 1].itemKey;
        }
    };
</script>

<template>
    <Tabs v-model:activeKey="activeKey">
        <template #tabBarExtraContent>
            <ButtonGroup>
                <Button @click="add">新增</Button>
                <Button @click="remove">删除</Button>
            </ButtonGroup>
        </template>
        <TabPane v-for="pane in panes" :key="pane.itemKey" :itemKey="pane.itemKey">
            <template #tab>{{ pane.title }}</template>
            {{ pane.content }}
        </TabPane>
    </Tabs>
</template>

关闭

关闭标签栏中的某一个标签页。
四种样式的页签都支持关闭选项,在对应的标签页上设置 closable 来开启。禁用的标签页不能关闭。标签页的移除由使用方在关闭回调中完成。

文档
代码
<script setup lang="ts">
    import { ref } from 'vue';
    import { TabPane, Tabs } from '@fibrous/semi-ui-vue';

    const tabList = ref([
        { tab: '文档', itemKey: '1', text: '文档', closable: true },
        { tab: '快速起步', itemKey: '2', text: '快速起步', closable: true },
        { tab: '帮助', itemKey: '3', text: '帮助', closable: false },
    ]);

    const close = (key: string) => {
        tabList.value = tabList.value.filter((t) => t.itemKey !== key);
    };
</script>

<template>
    <Tabs defaultActiveKey="1" type="card" @tabClose="close">
        <TabPane v-for="t in tabList" :key="t.itemKey" :closable="t.closable" :itemKey="t.itemKey">
            <template #tab>{{ t.tab }}</template>
            {{ t.text }}
        </TabPane>
    </Tabs>
</template>

API 参考

Tab

Props

属性说明类型默认值
activeKey当前激活的标签页的 itemKey,配合 v-model:activeKey 使用。传 null 时不激活任何标签页,仍是受控;不传或为 undefined 时按非受控处理。string | nullsemiGlobalDefault("Tabs", "activeKey")
arrowPosition折叠模式下,左右切换箭头的位置。"both" | "start" | "end"semiDefault("Tabs", "arrowPosition", "both")
collapsible是否开启滚动折叠(仅水平模式)。传 'auto' 时在标签溢出或换行时自动折叠,放得下时自动退出。boolean | "auto"semiDefault("Tabs", "collapsible", false)
contentStyle内容区域外层的样式。StyleValuesemiGlobalDefault("Tabs", "contentStyle")
defaultActiveKey非受控时初始选中的 itemKey。不传时取第一个启用且有 itemKey 的标签页。stringsemiGlobalDefault("Tabs", "defaultActiveKey")
dropdownProps折叠模式下,分别透传给起始侧与末尾侧箭头下拉菜单的 Dropdown 属性。TabsDropdownPropssemiGlobalDefault("Tabs", "dropdownProps")
keepDOM使用 TabPane 子元素时,是否渲染未激活面板的 DOM。为 false 时只渲染当前面板,没有切换动画。booleansemiDefault("Tabs", "keepDOM", true)
lazyRender懒渲染,面板被激活过才渲染进 DOM。booleansemiDefault("Tabs", "lazyRender", false)
more将末尾的一部分标签页收入「更多」下拉菜单。传数字表示收入菜单的标签数;传对象时 count 为标签数,dropdownProps 透传给下拉菜单。触发器与菜单内容分别用 more 与 moreContent 插槽自定义。number | TabsMoresemiGlobalDefault("Tabs", "more")
preventScroll组件内部调用 focus 时,是否阻止浏览器滚动文档以显示新聚焦的元素。booleansemiGlobalDefault("Tabs", "preventScroll")
showRestInDropdown折叠模式下,是否将被收起的标签页展示在下拉菜单中。booleansemiDefault("Tabs", "showRestInDropdown", true)
size标签栏尺寸,目前仅线条式(line)标签栏支持。TabSizesemiDefault("Tabs", "size", "large")
tabBarClassName标签栏的类名。stringsemiGlobalDefault("Tabs", "tabBarClassName")
tabBarStyle标签栏的样式。StyleValuesemiGlobalDefault("Tabs", "tabBarStyle")
tabList标签页的数据数组,每项含 itemKey、tab、disabled、closable。只要传了数组(含空数组),默认插槽就是当前标签页的内容,并优先于 TabPane 子元素;标签内的节点用 tab 与 icon 插槽。PlainTab[]semiGlobalDefault("Tabs", "tabList")
tabPaneMotion是否使用动画切换面板。booleansemiDefault("Tabs", "tabPaneMotion", true)
tabPosition标签栏位置:top 为水平,left 为垂直。TabPositionsemiDefault("Tabs", "tabPosition", "top")
type标签栏样式:line、card、button、slash。slash 仅支持水平模式。TabTypesemiDefault("Tabs", "type", "line")
visibleTabsStyle折叠模式下,整体滚动区域的样式。StyleValuesemiGlobalDefault("Tabs", "visibleTabsStyle")

Events

事件说明回调参数
update:activeKey激活的标签页变化时触发,供 v-model:activeKey 回写。[activeKey: string]
change切换标签页时触发,参数为新激活的 itemKey;与 update:activeKey 同时发出。[activeKey: string]
tabClick单击,或用 Enter、Space 激活标签页时触发;用键盘激活时事件是 KeyboardEvent。[activeKey: string, event: MouseEvent | KeyboardEvent]
tabClose关闭标签页时触发,参数为被关闭标签页的 itemKey。标签页的移除由使用方完成。[tabKey: string]
visibleTabsChange折叠模式下溢出项的可见状态变化时触发,参数为 itemKey 到是否可见的 Map。Type[visibleState: Map<string, boolean>]

Slots

插槽说明作用域参数
defaultTabPane 子元素;传了 tabList 时是当前标签页的内容。TabPane 必须是 Tabs 的直接子元素。any
tabtabList 中每个标签页的标签,参数为 item 与 index;不提供时显示该项的 tab 文本。TabsTabSlotProps
icontabList 中每个标签页的图标,参数为 item 与 index;返回空内容则不渲染图标。TabsTabSlotProps
tabBarExtraContent标签栏的附加内容,位于 tablist 之外。any
tabBar替换整个标签栏。参数 tabBarProps 只含数据,tabBar 是默认标签栏节点,可用 component :is 渲染;自定义标签栏里的 TabItem 会自行控制所在的 Tabs。TabsTabBarSlotProps
arrow替换折叠模式下的每个滚动箭头,参数为被滚出的 items、position、onClick 与默认箭头 defaultNode。TabsArrowSlotProps
more替换「更多」菜单的触发器。any
moreContent替换「更多」菜单的内容,参数 items 为收入菜单的标签页。TabsMoreContentSlotProps

Exposes

名称说明类型
无

activeKey 配合 v-model:activeKey;aria-label、aria-labelledby 落在 role="tablist" 元素上,class、style 与其他原生属性落在根元素上。

PlainTab

tabList 的数据项,只含数据。

属性说明类型默认值
itemKey标签页的唯一标识,对应 activeKeystring无
tab标签页文字;有 #tab 插槽时以插槽为准string | number无
disabled是否禁用boolean无
closable是否允许关闭boolean无

TabsMore

more 传对象时的形状。

属性说明类型默认值
count收入下拉菜单的 Tab 数量number无
dropdownProps透传给下拉菜单的 Dropdown 属性TabsDropdownItemProps无

TabsDropdownItemProps 是 Dropdown 的属性,外加 class、style 与 onVisibleChange。dropdownProps 的 start、end 也使用该类型。

TabBarProps

#tabBar 插槽的 tabBarProps,是默认标签栏的数据。

属性说明类型
activeKey当前激活的 itemKey,受控的空值为 nullstring | null
list标签页数据;TabPane 的 #tab 为纯文本时才带 tabPlainTab[]
type标签栏样式'line' | 'card' | 'button' | 'slash'
size尺寸'small' | 'medium' | 'large'
tabPosition位置'top' | 'left'
collapsible是否折叠boolean | 'auto'
showRestInDropdown折叠模式下,收起的标签是否展示在下拉菜单中boolean
more收入「更多」菜单的配置number | TabsMore
arrowPosition折叠模式下箭头的位置'both' | 'start' | 'end'
visibleTabsStyle折叠模式下整体滚动区域的样式StyleValue
dropdownProps折叠模式下箭头下拉菜单的 Dropdown 属性TabsDropdownProps
classtabBarClassNamestring
styletabBarStyleStyleValue

TabPane

Props

属性说明类型默认值
itemKey标签页的唯一标识,对应 activeKey。stringundefined
disabled是否禁用该标签页。booleanundefined
closable是否允许关闭该标签页,关闭时触发 Tabs 的 tabClose 事件。booleanundefined

Events

事件说明回调参数
无

Slots

插槽说明作用域参数
default面板内容。any
tab标签栏中的标签内容,由 Tabs 渲染。纯文本时才会出现在 tabBar 插槽参数 tabBarProps.list 项的 tab 字段中。any
icon标签栏中该标签的图标,由 Tabs 渲染。any

Exposes

名称说明类型
无

class、style 与原生属性(包括 id、role、aria-*、tabindex)落在面板根元素上;id、role="tabpanel"、aria-hidden 与同标签页配对的 aria-labelledby 由组件生成,不会被覆盖,tabindex 默认为 0,可以覆盖。

TabItem

自定义标签栏(#tabBar 插槽)中单个标签的组件。在 Tabs 内点击会自行选中所在的标签页,并触发 Tabs 的 change 与 tabClick。

Props

属性说明类型默认值
itemKey标签的唯一标识。string""
selected是否为选中状态。booleanfalse
disabled是否禁用;禁用时点击、关闭按钮与 Enter、Space、Delete、Backspace 键均不生效,关闭按钮仍会显示。booleanfalse
closable是否显示关闭按钮。booleanfalse
size尺寸,默认取所在 Tabs 的 size。TabSizeundefined
type样式,默认取所在 Tabs 的 type,在 Tabs 之外为 line。TabTypeundefined
tabPosition位置,默认取所在 Tabs 的 tabPosition,在 Tabs 之外为 top。TabPositionundefined

Events

事件说明回调参数
click点击标签时触发,参数为 itemKey 与事件;禁用时不触发。在 Tabs 之内,点击本身已会选中该标签页。[itemKey: string, event: MouseEvent]

Slots

插槽说明作用域参数
tab标签内容。any
icon标签图标;返回空内容则不渲染图标。any

Exposes

名称说明类型
无

class、style 与原生属性落在根元素上;role、id、aria-selected、aria-disabled、aria-controls 与 tabindex 由组件管理,不会被覆盖。

Accessibility

ARIA

  • 关于 role
    • TabBar 中只包含 Tab 的元素对应的 role 为 tablist,切换箭头、「更多」和 tabBarExtraContent 在它之外
    • TabBar 中的 Tab 对应的 role 为 tab
    • TabPane 对应的 role 为 tabpanel
  • aria-label、aria-labelledby: 传给 Tabs 时落在 role="tablist" 的元素上,用于给标签栏命名
  • aria-orientation: 表明 TabBar 的方向,有 vertical 和 horizontal 两种。当传入 tabPosition 为 left 时, aria-orientation 会被设置为 vertical,tabPosition 为 top 时,设置为 horizontal
  • aria-disabled: 当 TabPane 设置为 disabled 时,对应 Tab 的 aria-disabled 会被设置为 true
  • aria-selected: 表明 Tab 是否被选中
  • aria-controls: 指向 Tab 标签所控制的 TabPane;文档中只有当前选中项的面板时(使用 tabList,或 keepDOM 为 false),只有选中的 Tab 带有此属性
  • aria-labelledby: 指向设置 TabPane 标签的元素

键盘和焦点

WAI-ARIA: https://www.w3.org/WAI/ARIA/apg/patterns/tabpanel/

  • 选项卡可以被获取到焦点,但禁用的选项卡除外
  • 键盘用户可以使用 Tab 键,将焦点移动到已被选择的选项卡元素的选项卡面板上
  • 当焦点位于水平选项卡列表中的选项卡元素上时,使用 左右箭头 来切换选项(RTL 页面中左右箭头方向对调)
  • 当焦点位于垂直选项卡列表中的选项卡元素上时,使用 上下箭头 来切换选项
  • 当焦点位于选项卡列表中的未被激活的选项卡元素上时,可以使用 Space 或 Enter 键来激活该选项卡
  • 当键盘用户想要直接将焦点聚焦到选项卡列表中的最后一个选项卡元素时:
    • Mac 用户:fn + 右箭头
    • Windows 用户:End
  • 当键盘用户想要直接将焦点聚焦到选项卡列表中的第一个选项卡元素时:
    • Mac 用户:fn + 左箭头
    • Windows 用户:Home
  • 使用 more 时,默认的「更多」触发器是原生 button,可以用 Tab 键聚焦,Enter 或 Space 打开下拉菜单,并带有 aria-haspopup="menu" 与 aria-expanded
  • 当选项卡允许被删除时:
    • 用户可以使用 Delete 或 Backspace 键删除选项卡,禁用的选项卡除外
    • 删除后,焦点转移到被删除选项卡元素的后一个元素上;若被删除元素无后一个元素则转移到前一个元素上

设计变量

下表是组件内部的 Sass 变量,不能覆写。定制样式请覆写 --semi-* CSS 变量(见 Design Token 页),或写不分层的 CSS 规则。
Sass 变量值用法
$transition_duration-tabs_tab_line-bordervar(--semi-transition_duration-none)线条式标签页标示线-边框-动画持续时间
$transition_function-tabs_tab_line-bordervar(--semi-transition_function-easeIn)线条式标签页标示线-边框-过渡曲线
$transition_delay-tabs_tab_line-bordervar(--semi-transition_delay-none)线条式标签页标示线-边框-延迟时间
$transition_duration-tabs_tab_line-textvar(--semi-transition_duration-none)线条式标签页-文字-动画持续时间
$transition_function-tabs_tab_line-textvar(--semi-transition_function-easeIn)线条式标签页-文字-过渡曲线
$transition_delay-tabs_tab_line-textvar(--semi-transition_delay-none)线条式标签页-文字-延迟时间
$transition_duration-tabs_tab_button-bgvar(--semi-transition_duration-none)按钮式标签页-背景色-动画持续时间
$transition_function-tabs_tab_button-bgvar(--semi-transition_function-easeIn)按钮式标签页-背景色-过渡曲线
$transition_delay-tabs_tab_button-bgvar(--semi-transition_delay-none)按钮式标签页-背景色-延迟时间
$transition_duration-tabs_tab_card-bgvar(--semi-transition_duration-none)卡片式标签页文字-背景色-动画持续时间
$transition_function-tabs_tab_card-bgvar(--semi-transition_function-easeIn)卡片式标签页文字-背景色-过渡曲线
$transition_delay-tabs_tab_card-bgvar(--semi-transition_delay-none)卡片式标签页文字-背景色-延迟时间
$transform_scale-tabs_tab_line-itemvar(--semi-transform_scale-none)线条式标签页item 放大
$transform_scale-tabs_tab_button-itemvar(--semi-transform_scale-none)按钮式标签页item 放大
$transform_scale-tabs_tab_card-itemvar(--semi-transform_scale-none)线条式标签页item 放大
$animation_transform_translateX-tabs_tabPanel-leftShow60px左侧展示时,tabPanel的水平偏移值
$animation_transform_translateX-tabs_tabPanel-rightShow-60px右侧展示时,tabPanel的水平偏移值
$animation_opacity-tabs_tabPanel_show0tabPanel的动画开始时透明度
$animation_duration-tabs_tabPanel-show200mstabPanel的展示动画持续时间
$animation_function-tabs_tabPanel-showease-in-outtabPanel的展示动画曲线
$animation_delay-tabs_tabPanel-show0stabPanel的展示动画延迟时间
$color-tabs_tab_line_default-border-defaultvar(--semi-color-border)线条式页签轨道颜色 - 默认
$color-tabs_tab_line_default-text-defaultvar(--semi-color-text-2)线条式页签文本颜色 - 默认
$color-tabs_tab_line_default-text-hovervar(--semi-color-text-0)线条式页签文本颜色 - 悬浮
$color-tabs_tab_line_default-border-hovervar(--semi-color-fill-0)线条式页签标示线颜色 - 悬浮
$color-tabs_tab_line_default-text-activevar(--semi-color-text-0)线条式页签文本颜色 - 按下
$color-tabs_tab_line_default-border-activevar(--semi-color-fill-1)线条式页签标示线颜色 - 按下
$color-tabs_tab_line_selected-text-defaultvar(--semi-color-text-0)线条式页签文本颜色 - 选中
$color-tabs_tab_line_indicator_selected-icon-defaultvar(--semi-color-primary)线条式页签标示线颜色 - 选中
$color-tabs_tab_line_vertical_selected-bg-defaultvar(--semi-color-primary-light-default)垂直线条式页签背景颜色 - 选中
$color-tabs_tab_line_vertical-bg-hovervar(--semi-color-fill-0)垂直线条式页签背景颜色 - 悬浮
$color-tabs_tab_line_vertical-bg-activevar(--semi-color-fill-1)垂直线条式页签背景颜色 - 按下
$color-tabs_tab_line_disabled-text-defaultvar(--semi-color-disabled-text)禁用线条式页签文本颜色 - 默认
$color-tabs_tab_line_disabled-text-hovervar(--semi-color-disabled-text)禁用线条式页签文本颜色 - 悬浮
$color-tabs_tab_card_default-border-defaultvar(--semi-color-border)卡片式页签容器底部长线颜色 - 默认
$color-tabs_tab_button_selected-bg-defaultvar(--semi-color-primary-light-default)按钮式页签背景颜色 - 选中
$color-tabs_tab_button_selected-text-defaultvar(--semi-color-primary)按钮式页签文本颜色 - 选中
$color-tabs_tab_button-text-defaultvar(--semi-color-text-2)按钮式页签文本颜色 - 默认
$color-tabs_tab_button-bg-hovervar(--semi-color-fill-0)按钮式页签背景颜色 - 悬浮
$color-tabs_tab_button-bg-activevar(--semi-color-fill-1)按钮式页签背景颜色 - 按下
$color-tabs_tab_card_indicator_selected-icon-defaultvar(--semi-color-border)卡片式页签选中页签描边
$color-tabs_tab_card-bg-hovervar(--semi-color-fill-0)卡片式页签背景颜色 - 悬浮
$color-tabs_tab_card_selected-bg-defaultvar(--semi-color-bg-1)卡片式页签背景颜色 - 选中
$color-tabs_tab_card-bg-activevar(--semi-color-fill-1)卡片式页签背景颜色 -按下
$color-tabs_tab-icon-defaultvar(--semi-color-text-2)页签图标颜色 - 默认
$color-tabs_tab-icon-hovervar(--semi-color-text-0)页签图标颜色 - 悬浮
$color-tabs_tab-icon-activevar(--semi-color-text-0)页签图标颜色 - 按下
$color-tabs_tab_selected-icon-defaultvar(--semi-color-primary)页签图标颜色 - 选中
$color-tabs_tab-outline-focus$color-focus-ring页签轮廓 - 聚焦
$color-tabs_tab-pane-text-defaultvar(--semi-color-text-0)标签页内容文本颜色 - 默认
$color-tabs_tab-pane_arrow-text-defaultvar(--semi-color-primary)滚动折叠箭头颜色 - 默认
$color-tabs_tab-pane_arrow-border-defaulttransparent滚动折叠箭头边框颜色 - 默认
$color-tabs_tab-pane_arrow-bg-defaulttransparent滚动折叠箭头背景色 - 默认
$color-tabs_tab-pane_arrow-text-hovervar(--semi-color-primary)滚动折叠箭头颜色 - 悬浮
$color-tabs_tab-pane_arrow-border-hovertransparent滚动折叠箭头边框颜色 - 悬浮
$color-tabs_tab-pane_arrow-text-activevar(--semi-color-primary)滚动折叠箭头颜色 - 按下
$color-tabs_tab-pane_arrow-border-activetransparent滚动折叠箭头边框颜色 - 按下
$color-tabs_tab-pane_arrow_disabled-bg-defaulttransparent
$color-tabs_tab-pane_arrow_disabled-bg-hovertransparent
$color-tabs_tab-pane_arrow_disabled-text-defaultvar(--semi-color-disabled-text)
$color-tabs_tab-pane_arrow_disabled-text-hovervar(--semi-color-disabled-text)
$color-tabs_tab_slash_linevar(--semi-color-text-2)斜线式页签分割线颜色
$font-tabs_tab-fontWeight$font-weight-regular页签文本字重 - 默认
$font-tabs_tab_active-fontWeight$font-weight-bold页签文本字重 - 选中
$height-tabs_overflow_list300px页签折叠收起菜单高度
$width-tabs_bar_line-border$border-thickness-control线条式页签底部分割线宽度
$width-tabs_bar_line_tab-border2px页签标示线宽度
$width-tabs_bar_card-border$border-thickness-control卡片式页签容器底部长线宽度
$width-tabs-outline$width-focus-ring聚焦轮廓宽度
$width-tabs-outline-offset-2px聚焦轮廓偏移宽度
$width-tabs_bar_line-outline-offset-1px线条式页签聚焦轮廓偏移宽度
$width-tabs_tab-pane_arrow-border0px滚动折叠箭头边框宽度
$width-tabs_tab_slash_line8px斜线式页签分割线宽度
$height-tabs_tab_slash_line14px斜线式页签分割线高度
$height-tabs_bar_extra_large50px大尺寸页签高度
$font-tabs_bar_extra_large-lineHeight$height-tabs_bar_extra_large大尺寸页签文字行高
$height-tabs_bar_extra_small36px小尺寸页签高度
$font-tabs_bar_extra_small-lineHeight$height-tabs_bar_extra_small小尺寸页签文字行高
$spacing-tabs_tab-more_trigger_icon-marginLeft8px
$spacing-tabs_tab-more_trigger_icon-marginRight8px
$spacing-tabs_tab-more_trigger_icon-marginTop0px
$spacing-tabs_tab-more_trigger_icon-marginBottom0px
$spacing-tabs_tab-pane_arrow8px滚动折叠箭头内边距
$spacing-tabs_bar_extra-paddingY0px附加操作垂直内边距
$spacing-tabs_bar_extra-paddingX5px附加操作水平内边距
$spacing-tabs_tab_icon-marginRight$spacing-tight附加操作垂直内边距
$spacing-tabs_tab_icon-top3px页签图标顶部位置
$spacing-tabs_overflow_icon-marginRight4px页签折叠切换按钮右侧外边距
$spacing-tabs_overflow_icon-marginLeft4px页签折叠切换按钮左侧外边距
$spacing-tabs_bar_line_tab-paddingTop$spacing-base线条式页签
$spacing-tabs_bar_line_tab-paddingRight$spacing-extra-tight线条式页签右侧内边距
$spacing-tabs_bar_line_tab-paddingBottom$spacing-base - $width-tabs_bar_line_tab-border线条式页签底部内边距
$spacing-tabs_bar_line_tab-paddingLeft$spacing-extra-tight线条式页签左侧内边距
$spacing-tabs_bar_line_tab-marginRight$spacing-loose线条式页签右侧外边距
$spacing-tabs_bar_line_tab_small-paddingTop$spacing-tight小尺寸线条式页签顶部内边距
$spacing-tabs_bar_line_tab_small-paddingRight$spacing-extra-tight小尺寸线条式页签右侧内边距
$spacing-tabs_bar_line_tab_small-paddingBottom$spacing-tight - $width-tabs_bar_line_tab-border小尺寸线条式页签底部内边距
$spacing-tabs_bar_line_tab_small-paddingLeft$spacing-extra-tight小尺寸线条式页签左侧内边距
$spacing-tabs_bar_line_tab_medium-paddingTop$spacing-base-tight中等尺寸线条式页签顶部内边距
$spacing-tabs_bar_line_tab_medium-paddingRight$spacing-extra-tight中等尺寸线条式页签右侧内边距
$spacing-tabs_bar_line_tab_medium-paddingBottom$spacing-base-tight - $width-tabs_bar_line_tab-border中等尺寸线条式页签底部内边距
$spacing-tabs_bar_line_tab_medium-paddingLeft$spacing-extra-tight中等尺寸线条式页签左侧内边距
$spacing-tabs_bar_line_tab_left-padding12px垂直线条式页签左侧内边距
$spacing-tabs_bar_line_tab_left_small-padding$spacing-tight - 2px小尺寸垂直线条式页签左侧内边距
$spacing-tabs_bar_line_tab_left_medium-padding$spacing-base-tight - 2px中等尺寸垂直线条式页签左侧内边距
$spacing-tabs_bar_slash_tab-paddingY12px斜线式页签上下内边距
$spacing-tabs_bar_slash_tab-paddingX0px斜线式页签水平内边距
$spacing-tabs_bar_slash-marginRight16px斜线式页签右侧外边距
$spacing-tabs_bar_slash_line_marginLeft16px斜线式页签斜线左侧外边距
$spacing-tabs_bar_slash_line_marginTop3px斜线式页签斜线顶部外边距
$spacing-tabs_bar_slash_line_marginBottom3px斜线式页签斜线底部外边距
$spacing-tabs_content-paddingY5px页签内容区垂直方向内边距
$spacing-tabs_content-paddingX0页签内容区水平方向内边距
$spacing-tabs_content_left-paddingX5px垂直页签内容区垂直方向内边距
$spacing-tabs_content_left-paddingY0垂直页签内容区水平方向内边距
$spacing-tabs_bar_card_tab-marginRight$spacing-tight卡片式页签右侧外边距
$spacing-tabs_bar_card_tab_active-paddingTop$spacing-tight卡片式选中页签顶部内边距
$spacing-tabs_bar_card_tab_active-paddingBottom$spacing-tight - 1px卡片式选中页签底部内边距
$spacing-tabs_bar_card_tab_active-paddingLeft$spacing-base-tight卡片式选中页签左侧内边距
$spacing-tabs_bar_card_tab_active-paddingRight$spacing-base-tight卡片式选中页签右侧内边距
$spacing-tabs_bar_card_tab_left-marginBottom$spacing-tight垂直卡片式页签底部外边距
$spacing-tabs_bar_card_tab_left_active-paddingY$spacing-tight垂直卡片式选中页签垂直内边距
$spacing-tabs_bar_card_tab_left_active-paddingX$spacing-base-tight垂直卡片式选中页签水平内边距
$spacing-tabs_bar_card_tab-paddingY$spacing-tight卡片式选中页签垂直内边距
$spacing-tabs_bar_card_tab-paddingX$spacing-base-tight卡片式选中页签水平内边距
$spacing-tabs_bar_button_tab_left-marginBottom$spacing-tight垂直按钮式页签底部外边距
$spacing-tabs_bar_button_tab-marginRight$spacing-tight按钮式页签右侧外边距
$spacing-tabs_bar_button_tab-paddingY$spacing-tight按钮式页签垂直内边距
$spacing-tabs_bar_button_tab-paddingX$spacing-base-tight按钮式页签水平内边距
$radius-tabs_tab_cardvar(--semi-border-radius-small) var(--semi-border-radius-small) 0 0卡片式页签四向圆角
$radius-tabs_tab_card_leftvar(--semi-border-radius-small) 0 0 var(--semi-border-radius-small)垂直卡片式页签四向圆角
$radius-tabs_tab_buttonvar(--semi-border-radius-small)按钮式页签圆角
$font-tabs_bar_large-fontSize$font-size-regular大号模式 字体大小
$font-tabs_bar_small-fontSize$font-size-regular小号模式 字体大小
$font-tabs_bar_medium-fontSize$font-size-regular中等模式 字体大小

文案规范

  • 标签文案需要准确清晰地解释标签内容
  • 用简短的,易区分的标签
  • 尽量保持在一个词以内

FAQ

  • 为什么在 Tabs 中使用 Typography 的省略 ellipsis 失效?

    因为 Tabs 渲染 TabPane 时,默认是全部渲染 display: none。此时这些组件无法获取到正确的宽度或高度值。建议开启 lazyRender,或者关闭 keepDOM。

  • 为什么在 Tabs 中使用 Collapse/Collapsible/Resizable Table 等组件的高度或宽度值不对?

    原因同上,另外如果 collapse 不需要动画,也可以把它的 motion 设为 false 来关闭动画效果。此时无需获取组件的高度。