Skip to Content
@anker-in/headless-ui 2.0 is released 🎉

Tabs (Tabs1)

选项卡容器组件,用于组织和展示不同类别的内容,支持多种内容块类型和主题样式。【✅ 已发布】

加载中...
当前视口: 1920px × 600px场景: 左对齐三标签展示
打开链接

功能特性

  • 多内容块支持 - 可包含 ShelfDisplay、Faq、WhyChoose、BrandEquity 等 8 种内容块
  • 智能标签显示 - 仅在 2 个及以上标签时显示标签按钮,单标签时自动隐藏
  • 主题支持 - 支持亮色(light)和暗色(dark)两种主题
  • 灵活对齐 - 支持左对齐、居中、右对齐三种布局
  • 形状切换 - 支持方形(square)和圆形(round)两种样式
  • 章节标题 - 可选的组件标题展示
  • 标签扩展信息 - 每个标签支持标题、副标题、说明文字
  • 无障碍友好 - 基于 Radix UI Tabs 实现,完全符合 WAI-ARIA 规范
  • 键盘导航 - 支持 Tab 键切换焦点,方向键切换标签
  • 按需渲染 - 未激活的标签页内容不会渲染,提升性能

Props 参数

TabsProps

Prop类型默认值必需说明
dataTabsData-标签页数据配置对象
classNamestring''-自定义根容器类名

TabsData 配置

参数类型默认值必需说明
tabsTab[]-标签页列表
theme'light' | 'dark''light'主题模式
shape'round' | 'square''square'卡片形状
align'left' | 'center' | 'right''left'对齐方式
sectionTitlestring--组件标题

Tab 对象

参数类型必需说明
idstring标签页唯一标识
tabNamestring标签页名称
tabContentContentBlock[]标签页内容块列表
captionstring-标签页标题
subtitlestring-标签页副标题

支持的内容块类型

类型blockType 值说明
ShelfDisplay'ipc-shelfdisplay'产品货架展示
MultiLayoutGraphicBlock'ipc-multiLayoutGraphicBlock'多布局图文块
AccordionCards'ipc-accordioncards'手风琴卡片
Faq'ipc-faq'常见问题
Graphic'ipc-graphic'图文块
WhyChoose'ipc-whychoose'为何选择
BrandEquity'ipc-brand-equity'品牌权益
BrandCardLink'ipc-brand-card-link'品牌卡片链接

使用示例

最简示例

import { Tabs } from '@anker-in/headless-ui/biz' <Tabs data={{ theme: 'light', shape: 'square', align: 'left', tabs: [ { id: 'tab1', tabName: '畅销商品', tabContent: [ { blockType: 'ipc-shelfdisplay', products: [...], }, ], }, { id: 'tab2', tabName: '折扣商品', tabContent: [ { blockType: 'ipc-shelfdisplay', products: [...], }, ], }, ], }} />

基础产品分类展示

<Tabs data={{ theme: 'light', shape: 'square', align: 'left', tabs: [ { id: 'bestseller', tabName: '畅销商品', tabContent: [ { blockType: 'ipc-shelfdisplay', products: [ { img: { url: '...', alt: 'Product' }, title: '商品名称', price: '¥299', basePrice: '¥399', }, ], }, ], }, { id: 'discount', tabName: '折扣商品', tabContent: [ { blockType: 'ipc-shelfdisplay', products: [...], }, ], }, ], }} />

带章节标题

<Tabs data={{ sectionTitle: '热门分类', theme: 'light', shape: 'round', align: 'center', tabs: [ { id: 'category1', tabName: '充电器', tabContent: [ { blockType: 'ipc-shelfdisplay', products: [...], }, ], }, { id: 'category2', tabName: '充电宝', tabContent: [ { blockType: 'ipc-shelfdisplay', products: [...], }, ], }, ], }} />

FAQ 标签页

<Tabs data={{ theme: 'dark', shape: 'square', align: 'left', tabs: [ { id: 'general', tabName: '常规问题', caption: '一般性问题解答', tabContent: [ { blockType: 'ipc-faq', productData: [ { title: '如何退货?', desc: '您可以在收到商品后 30 天内申请退货...', img: { url: '...', alt: 'FAQ' }, }, ], }, ], }, { id: 'shipping', tabName: '物流配送', caption: '配送相关问题', tabContent: [ { blockType: 'ipc-faq', productData: [...], }, ], }, ], }} />

品牌权益标签页

<Tabs data={{ theme: 'light', shape: 'round', align: 'center', tabs: [ { id: 'benefits', tabName: '会员权益', tabContent: [ { blockType: 'ipc-brand-equity', items: [ { icon: { url: '...', alt: 'Warranty' }, title: 'Hassle-Free Warranty', description: 'Comprehensive warranty protection...', }, ], }, ], }, ], }} />

单标签(无标签按钮)

<Tabs data={{ theme: 'light', shape: 'square', align: 'left', tabs: [ { id: 'content', tabName: '主要内容', tabContent: [ { blockType: 'ipc-whychoose', productData: [...], }, ], }, ], }} />

响应式行为

标签栏对齐方式

根据 align 属性自动调整标签栏对齐:

align 值对齐效果适用场景
left左对齐默认,内容较多的场景
center居中标签数量少、页面对称的场景
right右对齐特殊布局需求

主题切换

theme 值效果应用场景
light亮色主题浅色背景页面
dark暗色主题深色背景页面,自动应用 aiui-dark

标签按钮显示逻辑

  • 标签数量 ≥ 2: 显示标签按钮,用户可切换
  • 标签数量 = 1: 自动隐藏标签按钮,直接显示内容

设计规范

标签页数量建议

  • 最少: 1 个(单标签时自动隐藏标签按钮)
  • 推荐: 2-5 个标签页
  • 最多: 建议不超过 8 个(避免标签栏过长)

主题选择

  • 亮色主题 (theme="light"): 用于浅色背景页面
  • 暗色主题 (theme="dark"): 用于深色背景页面,会自动应用 aiui-dark

对齐方式选择

  • 左对齐 (align="left"): 默认,适合内容较多的场景
  • 居中 (align="center"): 适合标签数量少、页面对称的场景
  • 右对齐 (align="right"): 特殊布局需求

标签命名建议

  • 简短明了,建议不超过 8 个字符
  • 使用名词或名词短语
  • 避免使用动词
  • 示例:
    • ✅ 畅销商品、折扣专区、新品推荐
    • ❌ 查看畅销、获取折扣、推荐给你

无障碍性

ARIA 支持

  • ✅ 基于 Radix UI Tabs,完全符合 WAI-ARIA 规范
  • ✅ 自动设置 role="tablist", role="tab", role="tabpanel" 属性
  • ✅ 自动管理 aria-selected, aria-controls, aria-labelledby 状态
  • ✅ 禁用的标签页自动设置 aria-disabled="true"

键盘导航

  • Tab 键: 切换焦点
  • 方向键: 切换标签
  • Enter/Space: 激活标签

建议

  • 为标签按钮提供清晰、简洁的文本标签
  • 避免使用仅图标的标签(应配合文本)
  • 确保标签文本对比度符合 WCAG AA 标准

性能优化

  • 使用 React.forwardRef() - 支持 ref 转发
  • 按需渲染 - 未激活的标签页内容不会渲染
  • 单标签优化 - 单标签时自动隐藏标签按钮,减少 DOM 节点
  • 条件渲染 - 使用条件渲染优化内容块加载

内容块渲染策略

当前实现仅渲染 tabContent[0](第一个内容块)。如需多个内容块,需要修改组件实现。

常见问题

为什么单标签时看不到标签按钮?

这是设计上的优化。当只有一个标签时,标签按钮会自动隐藏,因为没有切换的需求。如需强制显示,可以修改源代码中的条件判断。

如何设置默认激活的标签页?

默认激活第一个标签页(tabs[0])。Radix UI Tabs 支持 defaultValuevalue 属性来控制选中状态,但当前组件实现中固定为第一个。

每个标签页可以包含多个内容块吗?

理论上可以,tabContent 是一个数组,但当前实现仅渲染 tabContent[0](第一个内容块)。如需多个内容块,需要修改组件实现。

支持哪些内容块类型?

当前支持 8 种内容块:

  1. ShelfDisplay - 产品货架
  2. MultiLayoutGraphicBlock - 多布局图文
  3. AccordionCards - 手风琴卡片
  4. Faq - 常见问题
  5. Graphic - 图文块
  6. WhyChoose - 为何选择
  7. BrandEquity - 品牌权益
  8. BrandCardLink - 品牌卡片链接

如何自定义标签按钮样式?

通过全局 CSS 覆盖 .tabs-list.tabs-trigger 类的样式:

.tabs-list { /* 自定义标签栏样式 */ } .tabs-trigger { /* 自定义标签按钮样式 */ }

caption 和 subtitle 显示在哪里?

它们显示在标签页内容区域的顶部,通过 Title 组件渲染。如果两者都为空,则不显示。

如何实现受控模式(手动控制选中状态)?

当前组件是非受控模式。如需受控模式,可以在父组件中管理 value 状态,并通过 props 传递给 Tabs 组件。

技术实现

基于 Radix UI Tabs

组件基于 Radix UI Tabs  实现,提供完整的无障碍支持。

核心逻辑

// 智能标签按钮显示 const showTabs = tabs.length >= 2 // 内容块渲染 {tabs.map((tab) => ( <Tabs.Content value={tab.id} key={tab.id}> {renderContentBlock(tab.tabContent[0])} </Tabs.Content> ))} // 内容块类型判断 function renderContentBlock(block: ContentBlock) { switch (block.blockType) { case 'ipc-shelfdisplay': return <ShelfDisplay data={block} /> case 'ipc-faq': return <Faq data={block} /> // ...更多内容块类型 } }

类型定义

export type TabsProps = { data: { sectionTitle?: string theme: Theme shape: Shape align: Align tabs: { id: string tabName: string caption?: string subtitle?: string tabContent: | (ShelfDisplayProps['data'] & { blockType: 'ipc-shelfdisplay' })[] | (MultiLayoutGraphicBlockProps['data'] & { blockType: 'ipc-multiLayoutGraphicBlock' })[] | (AccordionCardsType['data'] & { blockType: 'ipc-accordioncards' })[] | (FaqProps['data'] & { blockType: 'ipc-faq' })[] | (GraphicProps['data'] & { blockType: 'ipc-graphic' })[] | (WhyChooseProps['data'] & { blockType: 'ipc-whychoose' })[] | (BrandEquityProps['data'] & { blockType: 'ipc-brand-equity' })[] | (BrandCardLinkProps['data'] & { blockType: 'ipc-brand-card-link' })[] }[] } className?: string }

相关资源

Last updated on