组件

Tabs

一个 React 标签页组件,采用 Liquid Glass 标签栏、滑动指示器,并支持键盘导航。

Tabs 用于在同一页面的一组相关面板之间切换。标签栏共享一块玻璃表面,半透明指示器会跟随当前标签移动。

标签页通过 items 数组传入。每个条目的 value 会把标签按钮与对应面板关联起来,content 则渲染在该面板中。非受控用法使用 defaultValue,受控用法使用 value 与 onValueChange。

基础示例

标签按钮可以同时包含文字与图标。默认会激活第一个可用的标签。

Profile

Update your name, photo, and contact details.

尺寸

支持 xs / sm / md / lg / xl,默认 md。标签高度、内边距、文字、图标、间距与面板文字会一起缩放。

xs
Workspace summary and recent activity.
sm
Workspace summary and recent activity.
md
Workspace summary and recent activity.
lg
Workspace summary and recent activity.
xl
Workspace summary and recent activity.

受控用法

value 与 onValueChange 让当前标签完全由外部状态控制。把 value 设为 null 可以渲染没有激活标签的状态。

Showing the overview panel.

Active tab: Overview

纵向布局

使用 orientation="vertical" 切换为左右布局。方向键会跟随方向变化,因此纵向标签使用 ArrowDown 与 ArrowUp 移动。

General

Project name, description, and visibility.

禁用标签

在组件上设置 disabled 会禁用所有标签;在单个 item 上设置 disabled 只会禁用该标签。禁用标签仍然可见,并保留在标签栏中。

Disabled group
Workspace summary.
One disabled tab
Workspace summary.

保留面板

切换到其他标签时,面板默认会卸载。给条目设置 keepMounted 可以让面板保留在 DOM 中,从而在切换标签后保留本地状态。

This panel unmounts when another tab becomes active, so the field is cleared.

聚焦即激活

默认情况下,方向键只移动焦点,需要按 Enter 或 Space 才会激活标签。设置 activateOnFocus 后,焦点移动时会直接切换面板。

Showing the overview panel.

Active tab: Overview. Focus the list and press an arrow key to switch without pressing Enter.

仅图标标签

标签默认由 label 命名。只渲染图标时,请提供 aria-label 或 aria-labelledby。

Update your name, photo, and contact details.

无障碍

Tabs 渲染由 tab 按钮组成的 tablist 与关联的 tabpanel。激活的标签暴露 aria-selected,每个面板通过 aria-controls 与 aria-labelledby 关联。

方向键沿布局方向移动焦点,Home 与 End 跳到首尾;activateOnFocus 为 false 时,Enter 或 Space 激活当前焦点标签。请用 aria-label 或 aria-labelledby 为标签栏命名;纯图标标签需要自己的名称。键盘细节见可访问性指南。

API 参考

Tabs

属性类型默认值说明
itemsreadonly TabsItemProps[]—组件渲染的标签与面板。
valueany—受控的当前值。设为 null 时不激活任何标签。
defaultValueany第一个可用项非受控时的初始值。
onValueChange(value: any, details) => void—当前值变化时调用。
orientation"horizontal" | "vertical""horizontal"布局与键盘方向。
activateOnFocusbooleanfalse方向键移动焦点时是否立即激活标签。
loopFocusbooleantrue焦点到达末尾后是否回到第一个标签。
disabledbooleanfalse禁用所有标签。
size"xs" | "sm" | "md" | "lg" | "xl""md"标签高度、内边距、文字、图标与间距。
aria-labelstring—标签栏的无障碍名称。
aria-labelledbystring—用外部元素命名标签栏。
aria-describedbystring—外部说明文字的 ID。
renderReactElement | ((props, state) => ReactElement)—替换根元素。
refRef<HTMLDivElement>—转发到根元素的 ref。
classNamestring—合并到根元素的 Tailwind 类名。
styleCSSProperties—内联样式,合并到与 className 相同的元素。
ui{ root?: ClassValue; list?: ClassValue; glass?: ClassValue; overlay?: ClassValue; indicator?: ClassValue; tab?: ClassValue; icon?: ClassValue; label?: ClassValue; panels?: ClassValue; panel?: ClassValue; panelContent?: ClassValue }—按 data-slot 组织的内部槽位类名。

TabsItem

属性类型默认值说明
valueany—关联标签与面板的值。
labelReactNode—标签内的可见文字。
iconReactNode—文字前的装饰性图标。
contentReactNode—标签激活时显示的面板内容。
keepMountedbooleanfalse其他标签激活时是否保留面板 DOM。
disabledbooleanfalse禁用该标签。
aria-labelstring—仅图标标签的无障碍名称。
aria-labelledbystring—用外部元素命名仅图标标签。
nativeButtonbooleantrue标签是否渲染原生 <button>。
renderReactElement | ((props, state) => ReactElement)—替换标签元素。
refRef<HTMLElement>—转发到标签元素的 ref。
classNamestring—合并到标签按钮的 Tailwind 类名;面板请使用 ui.panel。
styleCSSProperties—内联样式,合并到与 className 相同的元素。
ui{ tab?: ClassValue; icon?: ClassValue; label?: ClassValue; panel?: ClassValue; panelContent?: ClassValue }—按 data-slot 组织的该标签内部槽位类名。

根 ui 会先合并到每个标签与面板,再合并该 item 的 ui。item 的 className 只作用于标签按钮;面板请通过 ui.panel 设置。

属性说明
data-active标签处于激活状态时存在。
data-disabled组件或标签禁用时存在。
data-orientation表示方向(horizontal 或 vertical)。
data-activation-direction表示新激活标签相对上一个标签的方向。
data-hidden面板已挂载但未激活时存在。
data-starting-style面板开始进入动画时存在。
data-ending-style面板退出动画时存在。
data-slot标记内部部件(root、list、glass、overlay、indicator、tab、icon、label、panels、panel、panel-content)。

主题

组件使用共享玻璃材质。可以在父级调整 --ui-glass-* token,用 className 控制布局,并通过 ui 按 data-slot 调整内部槽位。组件级数值位于 src/theme/tabs.ts。Token 分层与预设见主题指南。

相关组件

  • Accordion — 没有标签栏的堆叠折叠内容。
  • Toggle Group — 不作为内容导航的紧凑视图切换。
  • Scroll Area — 面板需要独立滚动容器时使用。