跳到主要内容

Cell · List 列表行

每行独立白卡,行间 8px gap。不用 border-bottom 分隔——这是 Unif 列表的核心规则(与 iOS 17 / 微信新版一致)。

实时预览

下方渲染的就是 src/components/ui/Cell/Cell.tsx 本体,通过 react-native-web 翻译成浏览器节点。

设置
客户
disabled · 不可点击 / 视觉变灰
云同步
未登录
通知(开发中)
即将开放

视觉规范

元素规则
整组容器(grouped)c.background 浅灰底(视觉分组),padding: 8space[3]),borderRadius: 12radius.xl),gap: 8
单行c.surface 白底,borderRadius: 10radius.lg),min-height: 56padding: 14space[6],水平 + 垂直同值)
行内布局左 icon (grouped 22 / flush 28 盒) + 中 (title 15/500 + desc 13/subtle) + 右 extra (13/subtle) + arrow (grouped 20 / flush 18)
绝不(grouped)border-bottomhairline 分隔(flush 模式才用 inset hairline)

用法

import { Cell, List } from '@unif/react-native-design';

<List>
<Cell title="主题" extra="跟随系统" arrow leading="settings" onPress={...} />
<Cell title="通知" arrow leading="bell" />
<Cell title="拜访提醒" desc="按计划自动推送" extra={<Switch value={...} onChange={...} />} />
</List>

{/* 平铺式(无浅灰背景容器,用于嵌套在其它白卡内)*/}
<List flush>
<Cell title="客户名" desc="地址" extra="¥1,200" arrow />
</List>

API

<Cell>

PropType默认说明
titleReactNode主标题(必填);string 自动套 <Text> + numberOfLines=titleLines,传 ReactNode 完全自定义
titleLinesnumber1title 为 string 时的 numberOfLines(如新闻标题传 2)
descReactNode副标题 / 描述;string 自动 numberOfLines=2
extraReactNode右侧 slot — 文字、Tag、Switch、Stepper 等
arrowbooleanfalse显示右侧 chevron-right(danger 时不渲染)
leadingIconName | ReactNode左侧 icon 名(grouped 渲染 22px 裸 icon / flush 渲染 28×28 橙盒 + 16px icon)或自定义节点(如 Avatar)
onPress() => void点击回调(提供时启用按压态;不传则为纯展示 <View>
disabledbooleanfalse仅对带 onPress 的 cell 有效,true 时 onPress 不触发 + 整体半透明 + a11y disabled
dangerbooleanfalse危险态:icon 盒子 + 标题用 error 红,且不渲染 arrow(常用于退出登录 / 删除等)
styleStyleProp<ViewStyle>额外样式覆盖(合并到 cell 容器的 style 数组)
testIDstringE2E / 测试定位
accessibilityLabelstringtitle(string 时)显式 SR 朗读文案;title 传 ReactNode 时务必显式传
accessibilityHintstringSR 行为说明 hint(≤8 字,如「查看详情」);onPress 缺省时无意义

<List>

PropType默认说明
childrenReactNode一组 <Cell>
flushbooleanfalse透明背景(嵌套用);省略则白卡 + 8px gap + 浅灰底容器
divider'full' | 'none''full'flush 模式下行间分隔线:'full' 铺满全宽 hairline / 'none' 不画
styleStyleProp<ViewStyle>额外样式覆盖
testIDstringE2E / 测试定位

无障碍(a11y)

来源:src/components/ui/Cell/Cell.tsxtypes.ts

a11y 语义是条件性的:仅当传了 onPress 时,Cell 才用 <Pressable> 包裹并声明语义;不可点的纯展示 Cell 渲染为 <View>,无 a11y 角色。

  • 默认 accessibilityRole:可点时为 'button'onPress 缺省则无角色)。
  • a11y props(仅 onPress 时生效):accessibilityLabelaccessibilityLabel ?? (typeof title === 'string' ? title : undefined) —— 即 title 为字符串时自动作 label;title 传 ReactNode(自定义渲染)时务必显式传 accessibilityLabel,否则 SR 用户听不到内容accessibilityHint 可选,说明 tap 后行为(短句,如「查看详情」)。
  • 状态语义:disabled=true 时上报 accessibilityState={{ disabled: true }}(仅对带 onPress 的 cell 有效)。
// string title 自动作 label
<Cell title="主题" extra="跟随系统" arrow onPress={...} />

// ReactNode title 必须显式给 label
<Cell
title={<CustomTitle />}
accessibilityLabel="客户:东方便利店"
accessibilityHint="查看详情"
onPress={...}
/>

与 Form 的区别

用途选哪个
数据展示 / 跳转Cell · List — 白卡 + gap
数据录入 / 表单Form — 白卡 + 行间 hairline

主题键(Tokens)

读取来源:src/components/ui/Cell/styles.ts

Token来源作用
c.surfaceuseColors()grouped 模式下单行白卡背景色
c.foregrounduseColors()主标题文字色(title / titleFlush
c.foregroundSubtleuseColors()副标题 / extra 文字色(grouped 模式)
c.foregroundMuteduseColors()副标题 / extra 文字色(flush 模式,另加 opacity: 0.55
c.backgrounduseColors()<List> grouped 模式外容器背景色(浅灰底)
c.outlineuseColors()flush 模式行间 hairline 分隔线颜色
radius.lg静态 tokengrouped 模式单行卡片圆角
radius.xl静态 token<List> grouped 模式外容器圆角
space[5] / space[6] / space[3]静态 token行内 leading↔body↔extra gap(12)/ 行内水平+垂直内边距(14)/ List 行间 gap + 容器 padding(8)
space[4]静态 tokenflush 模式行内元素间 gap(cellFlush.gap
type.body / type.xs静态 token主标题 / 副标题字号(grouped 模式)
fw.medium静态 token主标题字重
StyleSheet.hairlineWidthReact Nativeflush 模式分隔线物理宽度(不参与 token 缩放)