Tabs 标签页
页面内分类切换 · 两种风格:下划线 Tabs(页面级)/ 分段控件 Segmented(局部分组)。
实时预览
下方渲染的就是 src/components/ui/Tabs/Tabs.tsx 与 src/components/ui/Segmented/Segmented.tsx 本体,通过 react-native-web 翻译成浏览器节点。
下划线 Tabs · 页面级
分段控件 · 局部 · md(默认)
分段控件 · sm(紧凑,模型下拉等局促位)
下划线 Tabs
页面级分类切换,全宽分布。来源:src/components/ui/Tabs/styles.ts、Tabs.tsx。
| 元素 | 规则 |
|---|---|
| 容器 | 高 44px(fixed.hitTarget),背景 c.surface,底部 hairline c.outline |
| Tab 项 | flex: 1 平分,14px(type.sm),激活态 c.primary + 字重 600(非激活 c.foregroundMuted + 500) |
| 下划线 | 2px c.primary,宽 36px(icon.xl,居中、非随 label),底对齐 |
分段控件
局部分组(如 Filter "全部 / 已完成 / 待跟进")。来源:src/components/ui/Segmented/styles.ts、Segmented.tsx。
| 元素 | 规则 |
|---|---|
| 容器 | alignSelf: 'flex-start' 内容自适应宽,背景 c.surfaceContainerHigh(亮色 #F0F0F0),圆角 8(radius.md),内 padding 2 |
| 项 | 内容宽(非平分);minHeight / 水平 padding / 字号随 size:md 44 / 16 / 13(fixed.hitTarget·space[7]·type.xs,默认、触控达标)· sm 28 / 12 / 12(高 28pt 物理常量·space[5]·type.xxs,紧凑、触控 < 44px) |
| 激活 | 白底 thumb(暗色 surfaceContainerHighest),圆角 6(radius.sm),亮色态柔阴影 |
用法
import { Tabs, Segmented } from '@unif/react-native-design';
{/* 页面级 */}
<Tabs
value={tab}
onChange={setTab}
items={[
{ id: 'all', label: '全部' },
{ id: 'pending', label: '待跟进' },
{ id: 'done', label: '已完成' },
]}
/>
{/* 局部分段 */}
<Segmented
value={range}
onChange={setRange}
items={[
{ id: 'day', label: '日' },
{ id: 'week', label: '周' },
{ id: 'month', label: '月' },
]}
/>
API
来源:src/components/ui/Tabs/types.ts、src/components/ui/Segmented/types.ts。Tabs 与 Segmented props 形状一致,共用 TabItem。
TabsProps / SegmentedProps:
| Prop | 类型 | 默认 | 说明 |
|---|---|---|---|
value | string | — | 当前选中项的 id(必填) |
onChange | (id: string) => void | — | 切换回调,回传点中项的 id(必填) |
items | TabItem[] | — | 列表项(Tabs ≥2 项才有意义;必填) |
size | 'sm' | 'md' | 'md' | 仅 Segmented;'md' 默认(高 44px 触控达标),'sm' 紧凑(高 28px / 字号 12,给模型下拉等局促位用,触控 < 44px) |
testID | string? | — | 容器 testID;item testID 自动派生为 ${testID}-${id} |
TabItem:
| 字段 | 类型 | 默认 | 说明 |
|---|---|---|---|
id | string | — | 唯一标识,用作 key 与选中判定 |
label | string | — | 显示文本(同时作 accessibilityLabel) |
testID | string? | — | 单 item testID(默认 ${tabsTestID}-${id}) |
无障碍(a11y)
来源:src/components/ui/Tabs/Tabs.tsx、src/components/ui/Segmented/Segmented.tsx、types.ts(两者 a11y 实现一致,共用 TabItem 形状)。
- 默认
accessibilityRole:Tabs与Segmented的每个项<Pressable>上都硬编码'tab'。外层容器是普通<View>,源码未设置tablistrole(仅作布局)。 - a11y props:每个项的
accessibilityLabel取自item.label,而label在TabItem中是必填的——每个 tab 默认都有朗读文案。 - 状态语义:
accessibilityState={{ selected: on }}——selected由item.id === value派生。无disabled语义(TabItem无disabled字段)。
// 每个 tab 自动 role=tab、label=item.label、selected 由 value 决定
<Tabs
value={tab}
onChange={setTab}
items={[
{ id: 'all', label: '全部' },
{ id: 'pending', label: '待跟进' },
]}
/>