新增 Segmented 组件 (WEB-1382)
版本: 0.10.0 · 类型: ✨ 新功能
问题
设计系统缺少一个「分段控制器」组件,用于在少量互斥选项间切换(如视图模式切换、筛选维度切换),语义上始终保持一项选中,不存在"全部未选中"的中间态。Tabs 会把选中状态绑定到内容面板,并不适合纯值选择场景。
改动文件
packages/design/src/components/Segmented/Segmented.tsxpackages/design/src/components/Segmented/styles.tspackages/design/src/components/Segmented/index.tspackages/design/src/components/Segmented/SegmentedDesignSpec.mdpackages/design/src/components/Segmented/__tests__/Segmented.test.tsxpackages/design/src/components/index.tspackages/design-site/docs/components/segmented.mdxpackages/design-site/i18n/zh-CN/docusaurus-plugin-content-docs/current/components/segmented.mdxpackages/design-site/src/theme/ReactLiveScope/index.tsx
改动内容
- 新增
Segmented组件,直接基于@radix-ui/react-toggle-group(type="single")封装,不经过ui/toggle-group——其默认toggleVariants视觉与 Segmented 冲突,复用前需先给整个 toggle 系列补齐unstyledVisual支持,不在本次范围。 - 声明式
optionsAPI,支持裸字符串简写('a'等价于{ value: 'a', label: 'a' }),通过getSegmentedItemTokenClass覆盖三种内容形态(纯文字 / 图标+文字 / 纯图标),图标 wrapper 采用居中布局(inline-flex items-center justify-center),使图标与 Item、同排文字保持垂直居中。纯图标选项在类型层面(判别联合)强制要求同时提供icon与aria-label,避免纯图标按钮上线后缺少可访问名。 - 同时支持受控(
value)与非受控(defaultValue,缺省取第一项)两种模式,并提供block(撑满父容器,选项通过flex-1等分空间)与整体 / 单项disabled。 - Radix
type="single"在点击已选中项时会以空字符串触发onValueChange(其原生「清空选中」行为);Segmented 在handleValueChange中拦截空值,既不更新内部状态,也不触发外部onChange。 - 选中态使用
Foregrounds-White/Foregrounds-Black,而非Backgrounds-Primary/Labels-Primary等语义 token——Foregrounds系列在明暗主题下均为纯白/纯黑,对应 Figma 中「选中药丸不随主题翻转」的设计意图。 - 未选中态文字使用
Labels/Secondary(light#3D3D3D/ dark#D6D6D6),而不用视觉上更浅的Labels/Tertiary(#6B6B6B):Tertiary实测未选中默认 4.47:1、hover 3.67:1,均低于 WCAG 2.1 AA 要求的 4.5:1;Secondary实测未选中默认 light 9.11:1 / dark 8.69:1,hover 明暗均 7.47:1,选中态(Foregrounds-BlackonForegrounds-White)明暗均 21:1。
未实现
- antd 的
size、shape、vertical均未实现——Figma 目前没有对应的变体。 - 容器
padding: 2px与radius: 7px是硬编码 fallback 值,design-tokens 中无匹配 token(只有Radius_5/Radius_12/Radius_20/Rounded)。