加载中...
当前视口: 1920px × 600px场景: 左对齐三标签展示
打开链接功能特性
- ✅ 多内容块支持 - 可包含 ShelfDisplay、Faq、WhyChoose、BrandEquity 等 8 种内容块
- ✅ 智能标签显示 - 仅在 2 个及以上标签时显示标签按钮,单标签时自动隐藏
- ✅ 主题支持 - 支持亮色(light)和暗色(dark)两种主题
- ✅ 灵活对齐 - 支持左对齐、居中、右对齐三种布局
- ✅ 形状切换 - 支持方形(square)和圆形(round)两种样式
- ✅ 章节标题 - 可选的组件标题展示
- ✅ 标签扩展信息 - 每个标签支持标题、副标题、说明文字
- ✅ 无障碍友好 - 基于 Radix UI Tabs 实现,完全符合 WAI-ARIA 规范
- ✅ 键盘导航 - 支持 Tab 键切换焦点,方向键切换标签
- ✅ 按需渲染 - 未激活的标签页内容不会渲染,提升性能
Props 参数
TabsProps
| Prop | 类型 | 默认值 | 必需 | 说明 |
|---|---|---|---|---|
data | TabsData | - | ✅ | 标签页数据配置对象 |
className | string | '' | - | 自定义根容器类名 |
TabsData 配置
| 参数 | 类型 | 默认值 | 必需 | 说明 |
|---|---|---|---|---|
tabs | Tab[] | - | ✅ | 标签页列表 |
theme | 'light' | 'dark' | 'light' | ✅ | 主题模式 |
shape | 'round' | 'square' | 'square' | ✅ | 卡片形状 |
align | 'left' | 'center' | 'right' | 'left' | ✅ | 对齐方式 |
sectionTitle | string | - | - | 组件标题 |
Tab 对象
| 参数 | 类型 | 必需 | 说明 |
|---|---|---|---|
id | string | ✅ | 标签页唯一标识 |
tabName | string | ✅ | 标签页名称 |
tabContent | ContentBlock[] | ✅ | 标签页内容块列表 |
caption | string | - | 标签页标题 |
subtitle | string | - | 标签页副标题 |
支持的内容块类型
| 类型 | 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 支持 defaultValue 和 value 属性来控制选中状态,但当前组件实现中固定为第一个。
每个标签页可以包含多个内容块吗?
理论上可以,tabContent 是一个数组,但当前实现仅渲染 tabContent[0](第一个内容块)。如需多个内容块,需要修改组件实现。
支持哪些内容块类型?
当前支持 8 种内容块:
- ShelfDisplay - 产品货架
- MultiLayoutGraphicBlock - 多布局图文
- AccordionCards - 手风琴卡片
- Faq - 常见问题
- Graphic - 图文块
- WhyChoose - 为何选择
- BrandEquity - 品牌权益
- 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
}相关资源
- Storybook 文档 - 查看更多交互示例
- 完整 README 文档 - 详细的 API 文档和使用指南
- Figma 设计稿 - 查看设计规范
- Radix UI Tabs 文档 - 了解底层实现
- 源代码 - GitHub 源代码
Last updated on