跳到主要内容

Chip 标签

胶囊形(pill)标签:圆角 999、可点击、可选中。Suggestion / 多选筛选 / 内联标记等场景的底层组件。

实时预览

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

单选 · selected 切换
leading icon · 建议气泡
trailing close · 多选 token
busy · 点了就转(请求在飞,二次点击被吞)
静态展示(无 onPress · 不响应按压)
VIP
拜访周期 7 天

状态

状态视觉
默认c.surface 白底 + 1px c.outline 细边框,c.foreground 文本
选中 (selected)c.primary 边框 + c.primaryContainerSubtle 浅橙底 + c.primary 文本
按下透明度 0.7(仅当传 onPress 时)
禁用 (disabled)透明度 0.5 + 不响应 onPress
处理中 (busy)leading 位换 spinner + 透明度 0.6 + 不响应二次点击(label 保留)
非交互(无 onPress不响应按压、不显示按压态

disabledbusy 的分工:disabled = 现在不能点(更暗、无动效);busy = 点过了,正在办(spinner 传达进行中)。两者同时为真按 disabled 的视觉走。

用法

import { Chip, Icon } from '@unif/react-native-design';

{/* 单个可选中 chip */}
<Chip
label="待跟进"
selected={filter === 'pending'}
onPress={() => setFilter('pending')}
/>

{/* 带 leading icon */}
<Chip
label="今天的安排"
leading={<Icon name="spark" size={12} />}
onPress={onSuggestion}
/>

{/* 静态展示(消息气泡里附带的 meta 标签等) */}
<Chip label="VIP" />

{/* 带 trailing 关闭按钮(多选 token 风格) */}
<Chip
label="王经理"
selected
trailing={<Icon name="close" size={12} />}
onPress={() => removeFilter('manager-wang')}
/>

{/* 点了就发请求的 chip:busy 顶住等待窗口,同时吞掉二次点击 */}
<Chip
label="今日拜访计划"
leading={<Icon name="spark" size={12} />}
busy={pending === 'plan'}
onPress={openTodayPlan}
/>

API

PropType默认说明
labelstring显示文本(单行 numberOfLines=1 截断)
selectedbooleanfalse选中态(主色边框 + 浅橙底 + 主色文本)
onPress() => void点击回调;不传时 chip 渲染为静态 <View>,不响应按压
disabledbooleanfalse禁用(透明度 0.5 + 不响应 onPress
busybooleanfalse处理中(leading 换 spinner + 透明度 0.6 + 吞掉二次点击)
leadingReactNode前置插槽(图标 / 小圆点等)
trailingReactNode后置插槽(关闭按钮等)
styleStyleProp<ViewStyle>附加样式
testIDstringE2E / 测试定位

主题键(Tokens)

Token来源作用
c.surfaceuseColors()默认背景色
c.outlineuseColors()默认边框色
c.primaryuseColors()选中边框 + 文本色
c.primaryContainerSubtleuseColors()选中浅橙底色
c.foregrounduseColors()默认文本色(busy spinner 也跟随它 / 选中时跟 c.primary
radius.pill@unif/react-native-design胶囊圆角
space['2'] / space['5'] / space['3']@unif/react-native-design内容 gap(6)/ 水平内边距(12)/ 垂直内边距(8)
type.xs@unif/react-native-design文本字号

无障碍(a11y)

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

a11y 语义是条件性的:仅当传了 onPress 时,Chip 才用 <Pressable> 包裹并声明语义;静态展示型(无 onPress)渲染为纯 <View>,无 a11y 角色(与「不响应按压」一致)。

  • 默认 accessibilityRole:可点时为 'button'onPress 缺省则无角色)。
  • a11y props(仅 onPress 时生效):accessibilityLabel 取自必填的 label
  • 状态语义:可点时上报 accessibilityState={{ selected, disabled, busy }} —— disableddisabled || busy(两者都不可点),busy 单独映射,读屏据此念出「忙碌」而不是「已停用」。
// 可点 + 可选中:role=button、label=label、state.selected 自动
<Chip label="待跟进" selected={filter === 'pending'} onPress={() => setFilter('pending')} />

// 处理中:state.busy=true、state.disabled=true(点击被吞,读屏念「忙碌」)
<Chip label="今日拜访计划" busy onPress={openTodayPlan} />

不要

  • ❌ 不要把 <Chip> 当成"按钮的小号版" —— 实际按钮(包括小号)走 Button size="sm"。Chip 的视觉重心在"可选状态",不在"主操作"。
  • ❌ 不要在 Chip 内嵌长文本 —— 单行 numberOfLines=1 截断;超过两个字的多选项考虑用 Cell 列表。
  • ❌ 不要用 Chip 表达状态语义(done/error)—— 那是 Tag 的领域。