代码演示
如何引入
<script lang="ts">
import { Tabs } from '@fibrae/semi-ui-svelte';
</script>
基本用法
标签栏支持四种样式的显示:线条式,按钮式,卡片式,斜线式。默认选中第一个启用的标签页。
标签页支持两种传入方式,两者渲染流程上有所区别:
- 通过
tabList传入标签页对象的数组,当使用tabList时每次只渲染当前传入的节点 - 或使用
<TabPane>逐项显式传入,使用<TabPane>时默认会渲染所有面板,可以通过将keepDOM设为false只渲染当前面板,此时不会有动画效果。
Svelte 没有 TabPane,标签页只通过 tabList 传入。tabList 的数据项只放数据(itemKey、tab、disabled、closable),需要节点时使用 Tabs 的 tab、icon snippet,参数为 { item, index },不提供 tab snippet 时显示该项的 tab 文本;内容写在 panel snippet 中,参数为 { item, index, itemKey },每个标签页是各自的 tabpanel,keepDOM、lazyRender 与切换动画对它生效。不提供 panel 时,Tabs 的 children 是当前标签页的内容。activeKey 用 bind:activeKey 绑定,不提供 defaultActiveKey,初始值直接写 activeKey="1"。
代码
<script lang="ts">
import { Tabs, type PlainTab } from '@fibrae/semi-ui-svelte';
const tabList: PlainTab[] = [
{ itemKey: '1', tab: '文档' },
{ itemKey: '2', tab: '快速起步' },
{ itemKey: '3', tab: '帮助' },
];
const paragraphStyle = 'line-height: 1.8';
const questionStyle = 'line-height: 1.8; color: var(--semi-color-text-0); font-weight: 600';
const answerStyle = 'line-height: 1.8; color: var(--semi-color-text-1)';
const codeStyle = 'margin: 24px 0; padding: 20px; border: none; white-space: normal; border-radius: var(--semi-border-radius-medium); color: var(--semi-color-text-1); background-color: var(--semi-color-fill-0)';
</script>
<div>
<Tabs {tabList} type="line">
{#snippet panel({ itemKey })}
{#if itemKey === '1'}
<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>
{:else if itemKey === '2'}
<h3>快速起步</h3>
<pre style={codeStyle}><code>yarn add @fibrae/semi-ui-svelte</code></pre>
{:else}
<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>
{/if}
{/snippet}
</Tabs>
</div>代码
<script lang="ts">
import { Tabs, type PlainTab } from '@fibrae/semi-ui-svelte';
const tabList: PlainTab[] = [
{ itemKey: '1', tab: '文档' },
{ itemKey: '2', tab: '快速起步' },
{ itemKey: '3', tab: '帮助' },
];
</script>
<Tabs {tabList} type="button">
{#snippet panel({ item })}{item.tab}{/snippet}
</Tabs>代码
<script lang="ts">
import { Tabs, type PlainTab } from '@fibrae/semi-ui-svelte';
const contentList = ['文档', '快速起步', '帮助'];
const tabList: PlainTab[] = [
{ tab: '文档', itemKey: '1' },
{ tab: '快速起步', itemKey: '2' },
{ tab: '帮助', itemKey: '3' },
];
let key = $state<string | null | undefined>('1');
</script>
<Tabs bind:activeKey={key} {tabList} type="card">
<div>{contentList[Number(key) - 1]}</div>
</Tabs>代码
<script lang="ts">
import { Tabs, type PlainTab } from '@fibrae/semi-ui-svelte';
const contentList = ['文档', '快速起步', '帮助'];
const tabList: PlainTab[] = [
{ tab: '文档', itemKey: '1' },
{ tab: '快速起步', itemKey: '2' },
{ tab: '帮助', itemKey: '3' },
];
let key = $state<string | null | undefined>('1');
</script>
<Tabs bind:activeKey={key} {tabList} type="slash">
<div>{contentList[Number(key) - 1]}</div>
</Tabs>带图标的
有图标的标签栏。
代码
<script lang="ts">
import { IconFile, IconGlobe, IconHelpCircle } from '@fibrae/semi-icons-svelte';
import { Tabs, type PlainTab } from '@fibrae/semi-ui-svelte';
const tabList: PlainTab[] = [
{ itemKey: '1', tab: '文档' },
{ itemKey: '2', tab: '快速起步' },
{ itemKey: '3', tab: '帮助' },
];
const icons = { '1': IconFile, '2': IconGlobe, '3': IconHelpCircle } as const;
</script>
<Tabs {tabList}>
{#snippet tab({ item })}
{@const Icon = icons[item.itemKey as keyof typeof icons]}
<span><Icon />{item.tab}</span>
{/snippet}
{#snippet panel({ item })}{item.tab}{/snippet}
</Tabs>更多选项收入 More 展示
支持将多余 Tab 合并为「更多」下拉菜单,more 传入数字即可,数字表示收入下拉菜单的 Tab 数量。
代码
<script lang="ts">
import { Tabs, type PlainTab } from '@fibrae/semi-ui-svelte';
const tabList: PlainTab[] = Array.from({ length: 10 }, (_, i) => ({ itemKey: `Tab-${i}`, tab: `Tab-${i}` }));
</script>
<Tabs more={4} style="width: 60%; margin: 20px" {tabList} type="card">
{#snippet panel({ index })}Content of card tab {index}{/snippet}
</Tabs>也支持高级配置,向 more 传入对象,内可传入
count: 表示收入下拉菜单的 Tab 数量dropdownProps: 传入 Dropdown 属性,会被透传到下拉菜单
「更多」触发器使用 moreTrigger snippet 自定义,下拉菜单的内容使用 moreContent snippet 自定义,参数 { items } 是收入菜单的标签页。
代码
<script lang="ts">
import { Button, Tabs, type PlainTab, type TabsMore } from '@fibrae/semi-ui-svelte';
const tabList: PlainTab[] = Array.from({ length: 10 }, (_, i) => ({ itemKey: `Tab-${i}`, tab: `Tab-${i}` }));
const more: TabsMore = { count: 4, dropdownProps: { trigger: 'click', position: 'bottomRight' } };
</script>
<Tabs {more} style="width: 60%; margin: 20px" {tabList} type="card">
{#snippet moreTrigger()}
<Button type="tertiary">Click to show More</Button>
{/snippet}
{#snippet panel({ index })}Content of card tab {index}{/snippet}
</Tabs>垂直的标签栏
type 为 line, card, button 支持水平和垂直两种模式,tabPosition='left|top', 默认为 top。type 为 slash 仅支持水平模式,无需设置。
代码
<script lang="ts">
import { IconFile, IconGlobe, IconHelpCircle } from '@fibrae/semi-icons-svelte';
import { Radio, RadioGroup, Tabs, type PlainTab, type RadioValue, type TabType } from '@fibrae/semi-ui-svelte';
let value = $state<RadioValue | undefined>('line');
const type = $derived(value as TabType);
const tabList: PlainTab[] = [
{ itemKey: '1', tab: '文档' },
{ itemKey: '2', tab: '快速起步' },
{ itemKey: '3', tab: '帮助' },
];
const icons = { '1': IconFile, '2': IconGlobe, '3': IconHelpCircle } as const;
const contentStyle = 'padding: 0 24px';
const paragraphStyle = 'line-height: 1.8';
const questionStyle = 'line-height: 1.8; color: var(--semi-color-text-0); font-weight: 600';
const answerStyle = 'line-height: 1.8; color: var(--semi-color-text-1)';
const codeStyle = 'margin: 24px 0; padding: 20px; border: none; white-space: normal; border-radius: 6px; color: var(--semi-color-text-1); background-color: var(--semi-color-fill-0)';
</script>
<RadioGroup bind:value style="display: flex; width: 200px; justify-content: center" type="button">
<Radio value="line">Line</Radio>
<Radio value="card">Card</Radio>
<Radio value="button">Button</Radio>
</RadioGroup>
<br />
<br />
<Tabs {tabList} tabPosition="left" {type}>
{#snippet tab({ item })}
{@const Icon = icons[item.itemKey as keyof typeof icons]}
<span><Icon />{item.tab}</span>
{/snippet}
{#snippet panel({ itemKey })}
<div style={contentStyle}>
{#if itemKey === '1'}
<h3>文档</h3>
<p style={paragraphStyle}>Semi Design 是由抖音前端团队与 UED 团队共同设计开发并维护的设计系统。设计系统包含设计语言以及一整套可复用的前端组件,帮助设计师与开发者更容易地打造高质量的、用户体验一致的、符合设计规范的 Web 应用。</p>
<p style={paragraphStyle}>区别于其他的设计系统而言,Semi Design 以用户中心、内容优先、设计人性化为设计理念,具有以下优势:</p>
{:else if itemKey === '2'}
<h3>快速起步</h3>
<pre style={codeStyle}><code>yarn add @fibrae/semi-ui-svelte</code></pre>
{:else}
<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>
{/if}
</div>
{/snippet}
</Tabs>滚动折叠
通过设置 collapsible 可以支持滚动折叠,目前只支持 horizontal 模式。
代码
<script lang="ts">
import { Tabs, type PlainTab } from '@fibrae/semi-ui-svelte';
const tabList: PlainTab[] = Array.from({ length: 10 }, (_, i) => ({ itemKey: `Tab-${i}`, tab: `Tab-${i}` }));
</script>
<Tabs collapsible style="width: 60%; margin: 20px" {tabList} type="card">
{#snippet panel({ index })}Content of card tab {index}{/snippet}
</Tabs>自定义滚动箭头渲染
通过 arrow snippet 修改滚动折叠模式下,左右切换箭头的渲染,参数为 { items, position, onClick, defaultNode }:溢出的标签页、位置、点击处理函数,以及默认箭头 defaultNode(用 {@render defaultNode()} 渲染)。
代码
<script lang="ts">
import { Dropdown, DropdownItem, DropdownMenu, Tabs, type PlainTab } from '@fibrae/semi-ui-svelte';
let activeKey = $state<string | null | undefined>('Tab-0');
const tabList: PlainTab[] = Array.from({ length: 10 }, (_, i) => ({ itemKey: `Tab-${i}`, tab: `Tab-${i}` }));
const arrowStyle = 'width: 32px; height: 32px; margin: 0 12px; display: flex; justify-content: center; align-items: center; padding: 0; border: none; border-radius: 100%; background: var(--semi-grey-1); color: var(--semi-color-text); font-family: inherit; font-size: inherit; cursor: pointer';
</script>
<Tabs bind:activeKey collapsible style="width: 50%; margin: 20px" {tabList} type="card">
{#snippet arrow({ items, position, onClick })}
<Dropdown>
{#snippet child({ props })}
<button {...props} style={arrowStyle} type="button" onclick={onClick}>
{position === 'start' ? '←' : '→'}
</button>
{/snippet}
{#snippet content()}
<DropdownMenu>
{#each items as item (item.itemKey)}
<DropdownItem onclick={() => (activeKey = item.itemKey)}>{item.itemKey}</DropdownItem>
{/each}
</DropdownMenu>
{/snippet}
</Dropdown>
{/snippet}
{#snippet panel({ index })}Content of card tab {index}{/snippet}
</Tabs>修改切换箭头的渲染位置
通过 arrowPosition 来修改溢出指示器的位置,可选 start both end
代码
<script lang="ts">
import { Tabs, type PlainTab } from '@fibrae/semi-ui-svelte';
const positions = ['start', 'both', 'end'] as const;
const tabList: PlainTab[] = Array.from({ length: 10 }, (_, i) => ({ itemKey: `Tab-${i}`, tab: `Tab-${i}` }));
</script>
{#each positions as position (position)}
<Tabs arrowPosition={position} collapsible style="width: 60%; margin: 20px" {tabList} type="card">
{#snippet panel({ index })}Content of card tab {index}{/snippet}
</Tabs>
{/each}自动溢出检测
通过设置 collapsible="auto" 可以启用自动溢出检测功能。组件会自动检测 Tab 是否溢出容器:
- 当 Tab 超出容器宽度或发生换行时,自动启用折叠模式(显示左右箭头)
- 当容器宽度增加或 Tab 数量减少后,所有 Tab 可以完整显示时,自动退出折叠模式
这个功能避免了开发者需要手动判断是否需要折叠的问题,特别适用于响应式布局场景。
collapsible="auto" - 自动检测溢出
固定宽度 400px,测试较窄容器
代码
<script lang="ts">
import { Button, Tabs, type PlainTab } from '@fibrae/semi-ui-svelte';
let count = $state(8);
const tabList = $derived<PlainTab[]>(Array.from({ length: count }, (_, i) => ({ itemKey: `${i}`, tab: `Tab-${i + 1}` })));
const boxStyle = 'border: 1px solid var(--semi-color-border); padding: 12px';
const noteStyle = 'margin-bottom: 8px; color: var(--semi-color-text-2); font-size: 12px';
</script>
{#snippet panel({ index }: { index: number })}Content of Tab {index + 1}{/snippet}
<div>
<div style="margin-bottom: 12px">
<Button style="margin-right: 8px" onclick={() => (count = Math.max(3, count - 2))}>减少 Tab</Button>
<Button onclick={() => (count = Math.min(15, count + 2))}>增加 Tab</Button>
<span style="margin-left: 12px">当前 Tab 数量: {count}</span>
</div>
<div style={`${boxStyle}; margin-bottom: 16px`}>
<p style={noteStyle}>collapsible="auto" - 自动检测溢出</p>
<Tabs collapsible="auto" {panel} {tabList} type="card" />
</div>
<div style={`${boxStyle}; max-width: 400px`}>
<p style={noteStyle}>固定宽度 400px,测试较窄容器</p>
<Tabs collapsible="auto" {panel} {tabList} type="card" />
</div>
</div>禁用
禁用标签栏中的某一个标签页。
代码
<script lang="ts">
import { Tabs, type PlainTab } from '@fibrae/semi-ui-svelte';
const tabList: PlainTab[] = [
{ itemKey: '1', tab: '文档' },
{ itemKey: '2', tab: '快速起步', disabled: true },
{ itemKey: '3', tab: '帮助' },
];
</script>
<Tabs activeKey="1" {tabList}>
{#snippet panel({ item })}{item.tab}{/snippet}
</Tabs>标签栏内容扩展
使用 tabBarExtraContent snippet 可以在标签栏右侧添加附加操作。
代码
<script lang="ts">
import { Button, Tabs, type PlainTab } from '@fibrae/semi-ui-svelte';
const tabList: PlainTab[] = [
{ itemKey: '1', tab: '文档' },
{ itemKey: '2', tab: '快速起步' },
{ itemKey: '3', tab: '帮助' },
];
const onExtraClick = () => {
alert('you have clicked me!');
};
</script>
<Tabs activeKey="1" {tabList}>
{#snippet tabBarExtraContent()}
<Button onclick={onExtraClick}>Extra Action</Button>
{/snippet}
{#snippet panel({ item })}{item.tab}{/snippet}
</Tabs>标签栏二次封装
使用 tabBar snippet 可对标签栏进行二次封装,参数为 { tabBarProps, tabBar }。tabBarProps 只含数据(见下方 TabBarProps),tabBar 是默认标签栏,用 {@render tabBar()} 渲染。
用 tabBar 完全替换标签栏时,Tabs 的 aria-label、aria-labelledby 不会落到你自己的元素上:可访问名称写在自定义的 role="tablist" 元素上。
代码
<script lang="ts">
import { Tabs, type PlainTab } from '@fibrae/semi-ui-svelte';
const tabList: PlainTab[] = [
{ itemKey: '1', tab: '文档' },
{ itemKey: '2', tab: '快速起步' },
{ itemKey: '3', tab: '帮助' },
];
</script>
<Tabs activeKey="1" {tabList}>
{#snippet tabBar({ tabBarProps, tabBar })}
<div class="tab-bar-box">
这是二次封装的Tab Bar,当前ActiveKey:{tabBarProps.activeKey}
{@render tabBar()}
</div>
{/snippet}
{#snippet panel({ item })}{item.tab}{/snippet}
</Tabs>拖拽排序
通过 tabBar snippet,在自己的 role="tablist" 元素里用 TabItem 渲染各个标签,即可结合拖拽实现标签栏的排序。TabItem 在 Tabs 内点击时会自行选中所在的标签页,draggable、拖放事件等原生属性与监听落在它的根元素上。示例使用浏览器原生拖放,只支持指针操作;需要键盘排序时可以改用支持键盘的拖拽库。
<script lang="ts">
import { TabItem } from '@fibrae/semi-ui-svelte';
</script>
代码
<script lang="ts">
import { TabItem, Tabs, type PlainTab } from '@fibrae/semi-ui-svelte';
let activeKey = $state<string | null | undefined>('1');
let tabList = $state<PlainTab[]>([
{ itemKey: '1', tab: '文档' },
{ itemKey: '2', tab: '表格' },
{ itemKey: '3', tab: '幻灯片' },
{ itemKey: '4', tab: '表单' },
]);
const contents: Record<string, string> = { '1': '文档内容', '2': '表格内容', '3': '幻灯片内容', '4': '表单内容' };
// HTML5 drag and drop on the TabItems: the website has no sortable library for Svelte, and a sortable list would wrap
// each tab in a button-role element that nests focusable tabs. Known limit: pointer only; use a sortable library for keyboard sorting.
let draggingKey = $state<string | null>(null);
const moveTo = (targetKey: string) => {
const from = tabList.findIndex((item) => item.itemKey === draggingKey);
const to = tabList.findIndex((item) => item.itemKey === targetKey);
if (from < 0 || to < 0 || from === to) return;
const next = [...tabList];
const [moved] = next.splice(from, 1);
next.splice(to, 0, moved);
tabList = next;
};
</script>
<Tabs bind:activeKey {tabList} type="line">
<!-- the bar keeps Semi's own .semi-tabs-bar shell; the TabItems inside select their Tabs by themselves -->
{#snippet tabBar()}
<div aria-orientation="horizontal" class="semi-tabs-bar semi-tabs-bar-line semi-tabs-bar-top" role="tablist">
{#each tabList as item (item.itemKey)}
<TabItem
draggable="true"
itemKey={item.itemKey}
selected={activeKey === item.itemKey}
style={`cursor: grab; opacity: ${draggingKey === item.itemKey ? 0.5 : 1}; display: inline-flex`}
ondragend={() => (draggingKey = null)}
ondragenter={(event) => {
event.preventDefault();
moveTo(item.itemKey);
}}
ondragover={(event) => event.preventDefault()}
ondragstart={() => (draggingKey = item.itemKey)}
>
{#snippet tab()}{item.tab}{/snippet}
</TabItem>
{/each}
</div>
{/snippet}
{#snippet panel({ itemKey })}
<div style="padding: 20px">{contents[itemKey]}</div>
{/snippet}
</Tabs>动态更新
通过绑定事件,可以使标签栏动态更新。
代码
<script lang="ts">
import { Button, ButtonGroup, Tabs, type PlainTab } from '@fibrae/semi-ui-svelte';
let newTabIndex = 0;
let tabList = $state<PlainTab[]>([
{ tab: 'Tab 1', itemKey: '1' },
{ tab: 'Tab 2', itemKey: '2' },
]);
const contents: Record<string, string> = { '1': 'Content of Tab Pane 1', '2': 'Content of Tab Pane 2' };
let activeKey = $state<string | null | undefined>('1');
const add = () => {
const index = newTabIndex++;
tabList = [...tabList, { tab: `New Tab ${index}`, itemKey: `newTab${index}` }];
activeKey = `newTab${index}`;
};
const remove = () => {
if (tabList.length > 1) {
tabList = tabList.slice(0, -1);
activeKey = tabList[tabList.length - 1].itemKey;
}
};
</script>
<Tabs bind:activeKey {tabList}>
{#snippet tabBarExtraContent()}
<ButtonGroup>
<Button onclick={add}>新增</Button>
<Button onclick={remove}>删除</Button>
</ButtonGroup>
{/snippet}
{#snippet panel({ itemKey })}{contents[itemKey] ?? 'New Tab Pane'}{/snippet}
</Tabs>关闭
关闭标签栏中的某一个标签页。
四种样式的页签都支持关闭选项,在对应的标签页上设置 closable 来开启。禁用的标签页不能关闭。标签页的移除由使用方在关闭回调中完成。
代码
<script lang="ts">
import { Tabs, type PlainTab } from '@fibrae/semi-ui-svelte';
let tabList = $state<PlainTab[]>([
{ tab: '文档', itemKey: '1', closable: true },
{ tab: '快速起步', itemKey: '2', closable: true },
{ tab: '帮助', itemKey: '3', closable: false },
]);
const close = (key: string) => {
tabList = tabList.filter((t) => t.itemKey !== key);
};
</script>
<Tabs onTabClose={close} {tabList} type="card">
{#snippet panel({ item })}{item.tab}{/snippet}
</Tabs>API 参考
Tab
Props
| 属性 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| activeKey | 当前激活的标签页的 itemKey,可用 bind:activeKey 双向绑定。传 null 时不激活任何标签页,仍是受控;不传或为 undefined 时按非受控处理,默认选中第一个启用的标签页。 | string | null | - |
| arrow | 替换折叠模式下每个滚动箭头的 snippet,参数为 { items, position, onClick, defaultNode }:被滚出的标签页、位置、点击处理函数和默认箭头(用 {@render defaultNode()} 渲染)。 | TypeSnippet<[TabsArrowSnippetProps]> | - |
| arrowPosition | 折叠模式下,左右切换箭头的位置。 | 'both' | 'start' | 'end' | "both" |
| children | 没有 panel 时的内容区:当前标签页的内容,是以所选标签命名的单个 tabpanel。 | Snippet | - |
| collapsible | 是否开启滚动折叠(仅水平模式)。传 'auto' 时在标签溢出或换行时自动折叠,放得下时自动退出。 | boolean | 'auto' | false |
| contentStyle | 内容区域外层的样式字符串。 | string | - |
| dropdownProps | 折叠模式下,分别透传给起始侧与末尾侧箭头下拉菜单的 Dropdown 属性。 | TabsDropdownProps | - |
| icon | tabList 中每个标签页图标的 snippet,参数为 { item, index };图标容器始终渲染,即使 snippet 没有输出。 | TypeSnippet<[TabsTabSnippetProps]> | - |
| keepDOM | 使用 panel 时,是否渲染未激活面板的 DOM。为 false 时只渲染当前面板,没有切换动画。 | boolean | true |
| lazyRender | 懒渲染,面板被激活过才渲染进 DOM。 | boolean | false |
| more | 将末尾的一部分标签页收入「更多」下拉菜单。传数字表示收入菜单的标签数;传对象时 count 为标签数,dropdownProps 透传给下拉菜单。触发器与菜单内容分别用 moreTrigger 与 moreContent snippet 自定义。 | number | TabsMore | - |
| moreContent | 替换「更多」菜单内容的 snippet,参数 { items } 为收入菜单的标签页。 | TypeSnippet<[TabsMoreContentSnippetProps]> | - |
| moreTrigger | 替换「更多」菜单触发器的 snippet。 | Snippet | - |
| onChange | 切换标签页时调用,参数为新激活的 itemKey。 | Type(activeKey: string) => void | - |
| onTabClick | 单击,或用 Enter、Space 激活标签页时调用;用键盘激活时事件是 KeyboardEvent。 | Type(activeKey: string, event: MouseEvent | KeyboardEvent) => void | - |
| onTabClose | 关闭标签页时调用,参数为被关闭标签页的 itemKey。标签页的移除由使用方完成。 | Type(tabKey: string) => void | - |
| onVisibleTabsChange | 折叠模式下溢出项的可见状态变化时调用,参数为 itemKey 到是否可见的 Map。 | Type(visibleState: Map<string, boolean>) => void | - |
| panel | tabList 中每个标签页内容的 snippet,参数为 { item, index, itemKey };传入后每个标签页都是各自的 tabpanel,keepDOM、lazyRender 与切换动画对它生效。 | TypeSnippet<[TabsPanelSnippetProps]> | - |
| preventScroll | 组件内部调用 focus 时,是否阻止浏览器滚动文档以显示新聚焦的元素。 | boolean | - |
| showRestInDropdown | 折叠模式下,是否将被收起的标签页展示在下拉菜单中。 | boolean | true |
| size | 标签栏尺寸,目前仅线条式(line)标签栏支持。 | TabSize | "large" |
| tab | tabList 中每个标签页标签的 snippet,参数为 { item, index };不提供时显示该项的 tab 文本。 | TypeSnippet<[TabsTabSnippetProps]> | - |
| tabBar | 替换整个标签栏的 snippet。参数 { tabBarProps, tabBar }:tabBarProps 只含数据,tabBar 是默认标签栏,用 {@render tabBar()} 渲染;自定义标签栏里的 TabItem 会自行控制所在的 Tabs。 | TypeSnippet<[TabsTabBarSnippetProps]> | - |
| tabBarClassName | 标签栏的类名。 | string | - |
| tabBarExtraContent | 标签栏附加内容的 snippet,位于 tablist 之外。 | Snippet | - |
| tabBarStyle | 标签栏的样式字符串。 | string | - |
| tabList | 标签页的数据数组,每项含 itemKey、tab、disabled、closable,只放数据;标签内的节点用 tab 与 icon snippet,内容用 panel snippet 或 children。 | PlainTab[] | [] |
| tabPaneMotion | 是否使用动画切换面板。 | boolean | true |
| tabPosition | 标签栏位置:top 为水平,left 为垂直。 | TabPosition | "top" |
| type | 标签栏样式:line、card、button、slash。slash 仅支持水平模式。 | TabType | "line" |
| visibleTabsStyle | 折叠模式下,整体滚动区域的样式字符串。 | string | - |
activeKey 配合 bind:activeKey;aria-label、aria-labelledby 落在 role="tablist" 元素上,class、style 与其他原生属性落在根元素上。
PlainTab
tabList 的数据项,只含数据。
| 属性 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| itemKey | 标签页的唯一标识,对应 activeKey | string | 无 |
| tab | 标签页文字;有 tab snippet 时以它为准 | string | number | 无 |
| disabled | 是否禁用 | boolean | 无 |
| closable | 是否允许关闭 | boolean | 无 |
TabsMore
more 传对象时的形状。
| 属性 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| count | 收入下拉菜单的 Tab 数量 | number | 无 |
| dropdownProps | 透传给下拉菜单的 Dropdown 属性 | TabsDropdownItemProps | 无 |
TabsDropdownItemProps 是 Dropdown 的属性,外加 class、style 与 onVisibleChange。dropdownProps 的 start、end 也使用该类型。
TabBarProps
tabBar snippet 的 tabBarProps,是默认标签栏的数据。
| 属性 | 说明 | 类型 |
|---|---|---|
| activeKey | 当前激活的 itemKey,受控的空值为 null | string | null |
| list | 标签页数据 | PlainTab[] |
| 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 | 折叠模式下整体滚动区域的样式 | string |
| dropdownProps | 折叠模式下箭头下拉菜单的 Dropdown 属性 | TabsDropdownProps |
| class | tabBarClassName | string |
| style | tabBarStyle | string |
TabPane
Svelte 没有 TabPane,标签页的内容用 Tabs 的 panel snippet 提供。
TabItem
自定义标签栏(tabBar snippet)中单个标签的组件。在 Tabs 内点击会自行选中所在的标签页,并触发 Tabs 的 onChange 与 onTabClick。
Props
| 属性 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| closable | 是否显示关闭按钮。 | boolean | false |
| disabled | 是否禁用;禁用时点击、关闭按钮与 Enter、Space、Delete、Backspace 键均不生效,关闭按钮仍会显示。 | boolean | false |
| icon | 标签图标的 snippet;图标容器始终渲染,即使 snippet 没有输出。 | Snippet | - |
| itemKey | 标签的唯一标识。 | string | "" |
| onClick | 点击标签时调用,参数为 itemKey 与事件;禁用时不调用。在 Tabs 之内,点击本身已会选中该标签页。 | Type(itemKey: string, event: MouseEvent) => void | - |
| selected | 是否为选中状态。 | boolean | false |
| size | 尺寸,默认取所在 Tabs 的 size。 | TabSize | - |
| tab | 标签内容的 snippet。 | Snippet | - |
| tabPosition | 位置,默认取所在 Tabs 的 tabPosition,在 Tabs 之外为 top。 | TabPosition | - |
| type | 样式,默认取所在 Tabs 的 type,在 Tabs 之外为 line。 | TabType | - |
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
- TabBar 中只包含 Tab 的元素对应的 role 为
- 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 用户:
- 当键盘用户想要直接将焦点聚焦到选项卡列表中的第一个选项卡元素时:
- Mac 用户:
fn+左箭头 - Windows 用户:
Home
- Mac 用户:
- 使用
more时,默认的「更多」触发器是原生button,可以用Tab键聚焦,Enter或Space打开下拉菜单,并带有aria-haspopup="menu"与aria-expanded - 当选项卡允许被删除时:
- 用户可以使用
Delete或Backspace键删除选项卡,禁用的选项卡除外 - 删除后,焦点转移到被删除选项卡元素的后一个元素上;若被删除元素无后一个元素则转移到前一个元素上
- 用户可以使用
设计变量
| Sass 变量 | 值 | 用法 |
|---|---|---|
| $transition_duration-tabs_tab_line-border | var(--semi-transition_duration-none) | 线条式标签页标示线-边框-动画持续时间 |
| $transition_function-tabs_tab_line-border | var(--semi-transition_function-easeIn) | 线条式标签页标示线-边框-过渡曲线 |
| $transition_delay-tabs_tab_line-border | var(--semi-transition_delay-none) | 线条式标签页标示线-边框-延迟时间 |
| $transition_duration-tabs_tab_line-text | var(--semi-transition_duration-none) | 线条式标签页-文字-动画持续时间 |
| $transition_function-tabs_tab_line-text | var(--semi-transition_function-easeIn) | 线条式标签页-文字-过渡曲线 |
| $transition_delay-tabs_tab_line-text | var(--semi-transition_delay-none) | 线条式标签页-文字-延迟时间 |
| $transition_duration-tabs_tab_button-bg | var(--semi-transition_duration-none) | 按钮式标签页-背景色-动画持续时间 |
| $transition_function-tabs_tab_button-bg | var(--semi-transition_function-easeIn) | 按钮式标签页-背景色-过渡曲线 |
| $transition_delay-tabs_tab_button-bg | var(--semi-transition_delay-none) | 按钮式标签页-背景色-延迟时间 |
| $transition_duration-tabs_tab_card-bg | var(--semi-transition_duration-none) | 卡片式标签页文字-背景色-动画持续时间 |
| $transition_function-tabs_tab_card-bg | var(--semi-transition_function-easeIn) | 卡片式标签页文字-背景色-过渡曲线 |
| $transition_delay-tabs_tab_card-bg | var(--semi-transition_delay-none) | 卡片式标签页文字-背景色-延迟时间 |
| $transform_scale-tabs_tab_line-item | var(--semi-transform_scale-none) | 线条式标签页item 放大 |
| $transform_scale-tabs_tab_button-item | var(--semi-transform_scale-none) | 按钮式标签页item 放大 |
| $transform_scale-tabs_tab_card-item | var(--semi-transform_scale-none) | 线条式标签页item 放大 |
| $animation_transform_translateX-tabs_tabPanel-leftShow | 60px | 左侧展示时,tabPanel的水平偏移值 |
| $animation_transform_translateX-tabs_tabPanel-rightShow | -60px | 右侧展示时,tabPanel的水平偏移值 |
| $animation_opacity-tabs_tabPanel_show | 0 | tabPanel的动画开始时透明度 |
| $animation_duration-tabs_tabPanel-show | 200ms | tabPanel的展示动画持续时间 |
| $animation_function-tabs_tabPanel-show | ease-in-out | tabPanel的展示动画曲线 |
| $animation_delay-tabs_tabPanel-show | 0s | tabPanel的展示动画延迟时间 |
| $color-tabs_tab_line_default-border-default | var(--semi-color-border) | 线条式页签轨道颜色 - 默认 |
| $color-tabs_tab_line_default-text-default | var(--semi-color-text-2) | 线条式页签文本颜色 - 默认 |
| $color-tabs_tab_line_default-text-hover | var(--semi-color-text-0) | 线条式页签文本颜色 - 悬浮 |
| $color-tabs_tab_line_default-border-hover | var(--semi-color-fill-0) | 线条式页签标示线颜色 - 悬浮 |
| $color-tabs_tab_line_default-text-active | var(--semi-color-text-0) | 线条式页签文本颜色 - 按下 |
| $color-tabs_tab_line_default-border-active | var(--semi-color-fill-1) | 线条式页签标示线颜色 - 按下 |
| $color-tabs_tab_line_selected-text-default | var(--semi-color-text-0) | 线条式页签文本颜色 - 选中 |
| $color-tabs_tab_line_indicator_selected-icon-default | var(--semi-color-primary) | 线条式页签标示线颜色 - 选中 |
| $color-tabs_tab_line_vertical_selected-bg-default | var(--semi-color-primary-light-default) | 垂直线条式页签背景颜色 - 选中 |
| $color-tabs_tab_line_vertical-bg-hover | var(--semi-color-fill-0) | 垂直线条式页签背景颜色 - 悬浮 |
| $color-tabs_tab_line_vertical-bg-active | var(--semi-color-fill-1) | 垂直线条式页签背景颜色 - 按下 |
| $color-tabs_tab_line_disabled-text-default | var(--semi-color-disabled-text) | 禁用线条式页签文本颜色 - 默认 |
| $color-tabs_tab_line_disabled-text-hover | var(--semi-color-disabled-text) | 禁用线条式页签文本颜色 - 悬浮 |
| $color-tabs_tab_card_default-border-default | var(--semi-color-border) | 卡片式页签容器底部长线颜色 - 默认 |
| $color-tabs_tab_button_selected-bg-default | var(--semi-color-primary-light-default) | 按钮式页签背景颜色 - 选中 |
| $color-tabs_tab_button_selected-text-default | var(--semi-color-primary) | 按钮式页签文本颜色 - 选中 |
| $color-tabs_tab_button-text-default | var(--semi-color-text-2) | 按钮式页签文本颜色 - 默认 |
| $color-tabs_tab_button-bg-hover | var(--semi-color-fill-0) | 按钮式页签背景颜色 - 悬浮 |
| $color-tabs_tab_button-bg-active | var(--semi-color-fill-1) | 按钮式页签背景颜色 - 按下 |
| $color-tabs_tab_card_indicator_selected-icon-default | var(--semi-color-border) | 卡片式页签选中页签描边 |
| $color-tabs_tab_card-bg-hover | var(--semi-color-fill-0) | 卡片式页签背景颜色 - 悬浮 |
| $color-tabs_tab_card_selected-bg-default | var(--semi-color-bg-1) | 卡片式页签背景颜色 - 选中 |
| $color-tabs_tab_card-bg-active | var(--semi-color-fill-1) | 卡片式页签背景颜色 -按下 |
| $color-tabs_tab-icon-default | var(--semi-color-text-2) | 页签图标颜色 - 默认 |
| $color-tabs_tab-icon-hover | var(--semi-color-text-0) | 页签图标颜色 - 悬浮 |
| $color-tabs_tab-icon-active | var(--semi-color-text-0) | 页签图标颜色 - 按下 |
| $color-tabs_tab_selected-icon-default | var(--semi-color-primary) | 页签图标颜色 - 选中 |
| $color-tabs_tab-outline-focus | $color-focus-ring | 页签轮廓 - 聚焦 |
| $color-tabs_tab-pane-text-default | var(--semi-color-text-0) | 标签页内容文本颜色 - 默认 |
| $color-tabs_tab-pane_arrow-text-default | var(--semi-color-primary) | 滚动折叠箭头颜色 - 默认 |
| $color-tabs_tab-pane_arrow-border-default | transparent | 滚动折叠箭头边框颜色 - 默认 |
| $color-tabs_tab-pane_arrow-bg-default | transparent | 滚动折叠箭头背景色 - 默认 |
| $color-tabs_tab-pane_arrow-text-hover | var(--semi-color-primary) | 滚动折叠箭头颜色 - 悬浮 |
| $color-tabs_tab-pane_arrow-border-hover | transparent | 滚动折叠箭头边框颜色 - 悬浮 |
| $color-tabs_tab-pane_arrow-text-active | var(--semi-color-primary) | 滚动折叠箭头颜色 - 按下 |
| $color-tabs_tab-pane_arrow-border-active | transparent | 滚动折叠箭头边框颜色 - 按下 |
| $color-tabs_tab-pane_arrow_disabled-bg-default | transparent | |
| $color-tabs_tab-pane_arrow_disabled-bg-hover | transparent | |
| $color-tabs_tab-pane_arrow_disabled-text-default | var(--semi-color-disabled-text) | |
| $color-tabs_tab-pane_arrow_disabled-text-hover | var(--semi-color-disabled-text) | |
| $color-tabs_tab_slash_line | var(--semi-color-text-2) | 斜线式页签分割线颜色 |
| $font-tabs_tab-fontWeight | $font-weight-regular | 页签文本字重 - 默认 |
| $font-tabs_tab_active-fontWeight | $font-weight-bold | 页签文本字重 - 选中 |
| $height-tabs_overflow_list | 300px | 页签折叠收起菜单高度 |
| $width-tabs_bar_line-border | $border-thickness-control | 线条式页签底部分割线宽度 |
| $width-tabs_bar_line_tab-border | 2px | 页签标示线宽度 |
| $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-border | 0px | 滚动折叠箭头边框宽度 |
| $width-tabs_tab_slash_line | 8px | 斜线式页签分割线宽度 |
| $height-tabs_tab_slash_line | 14px | 斜线式页签分割线高度 |
| $height-tabs_bar_extra_large | 50px | 大尺寸页签高度 |
| $font-tabs_bar_extra_large-lineHeight | $height-tabs_bar_extra_large | 大尺寸页签文字行高 |
| $height-tabs_bar_extra_small | 36px | 小尺寸页签高度 |
| $font-tabs_bar_extra_small-lineHeight | $height-tabs_bar_extra_small | 小尺寸页签文字行高 |
| $spacing-tabs_tab-more_trigger_icon-marginLeft | 8px | |
| $spacing-tabs_tab-more_trigger_icon-marginRight | 8px | |
| $spacing-tabs_tab-more_trigger_icon-marginTop | 0px | |
| $spacing-tabs_tab-more_trigger_icon-marginBottom | 0px | |
| $spacing-tabs_tab-pane_arrow | 8px | 滚动折叠箭头内边距 |
| $spacing-tabs_bar_extra-paddingY | 0px | 附加操作垂直内边距 |
| $spacing-tabs_bar_extra-paddingX | 5px | 附加操作水平内边距 |
| $spacing-tabs_tab_icon-marginRight | $spacing-tight | 附加操作垂直内边距 |
| $spacing-tabs_tab_icon-top | 3px | 页签图标顶部位置 |
| $spacing-tabs_overflow_icon-marginRight | 4px | 页签折叠切换按钮右侧外边距 |
| $spacing-tabs_overflow_icon-marginLeft | 4px | 页签折叠切换按钮左侧外边距 |
| $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-padding | 12px | 垂直线条式页签左侧内边距 |
| $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-paddingY | 12px | 斜线式页签上下内边距 |
| $spacing-tabs_bar_slash_tab-paddingX | 0px | 斜线式页签水平内边距 |
| $spacing-tabs_bar_slash-marginRight | 16px | 斜线式页签右侧外边距 |
| $spacing-tabs_bar_slash_line_marginLeft | 16px | 斜线式页签斜线左侧外边距 |
| $spacing-tabs_bar_slash_line_marginTop | 3px | 斜线式页签斜线顶部外边距 |
| $spacing-tabs_bar_slash_line_marginBottom | 3px | 斜线式页签斜线底部外边距 |
| $spacing-tabs_content-paddingY | 5px | 页签内容区垂直方向内边距 |
| $spacing-tabs_content-paddingX | 0 | 页签内容区水平方向内边距 |
| $spacing-tabs_content_left-paddingX | 5px | 垂直页签内容区垂直方向内边距 |
| $spacing-tabs_content_left-paddingY | 0 | 垂直页签内容区水平方向内边距 |
| $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_card | var(--semi-border-radius-small) var(--semi-border-radius-small) 0 0 | 卡片式页签四向圆角 |
| $radius-tabs_tab_card_left | var(--semi-border-radius-small) 0 0 var(--semi-border-radius-small) | 垂直卡片式页签四向圆角 |
| $radius-tabs_tab_button | var(--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 来关闭动画效果。此时无需获取组件的高度。