跳到主要内容
menumenu tanreiexpand_morecontrasttranslate
tanreiexpand_more
开始使用WebReactSwiftUIJetpack ComposeFlutterReact Native预设你自己的设计系统与 AI 代理一起使用 Tanrei品牌设计令牌设计系统与定制Theme Studio颜色字体排印图标形状层级动效交互状态行为布局无障碍文字颜色令牌字阶令牌形状令牌层级令牌动效令牌状态令牌间距与度量令牌组件按钮主操作按钮分段按钮按钮组带菜单的按钮工具栏复制按钮复选框单选按钮开关纸片(Chip)菜单滑块滑块字段日历DateTimePicker字段组单选组复选框组下拉选择框下拉选择字段菜单栏文件上传文件选择器 进阶放置区文本输入框 进阶文本字段纸片字段字段组合框 进阶组合框字段数字输入框 进阶数字字段颜色输入框 进阶颜色字段一次性验证码输入框 进阶一次性验证码字段嵌入式文本输入框 进阶聊天输入栏卡片分隔线模态层 进阶对话框列表列表行底部面板侧边面板轮播代码块表格弹出框步骤折叠面板描述列表图示应用外壳页头树视图时间线图片预览调整手柄可调整大小的框滚动区域徽标进度指示器计量条数字滚动器加载指示器消息条(Snackbar)工具提示键盘快捷键标签(Tag)行内代码提示块(Callout)头像空状态标签组(Tag group)骨架屏文件项色块跑马灯文本标签页标签页视图应用栏导航栏导航抽屉搜索链接分页上一页/下一页链接步骤条面包屑目录链接卡片FAB 菜单状态Tanrei 是如何构建的参与贡献许可与致谢
首页基础行为

行为

两个种类选择——按下如何得到反馈、键盘焦点长什么样——设计系统像设置其他令牌一样设置它们。

content_copy以 Markdown 格式查看

一个设计系统与另一个设计系统的区别,几乎都是量上的:半径、色调、时长。量就是取值,由层来改变。

少数区别不是量。有的系统用涟漪回应按下,有的把控件变暗;有的在聚焦的控件外画一圈硬边的圆环,有的画一圈柔和的光晕。现有令牌上的任何数值,都没法把其中一种变成另一种。Tanrei 把这类区别称为种类选择,并把它们保存为 sys.behavior 下的两个令牌。每个令牌列出一份简短而封闭的行为方式清单,由设计系统从中选一个。

设计系统 pressed-feedback focus-style
tanrei overlay ring
cupertino dim ring
m3-expressive-like ripple ring
m3-like ripple ring

生成自 tokens/systems/*.system.json, design/tokens/<system>/tanrei.light.tokens.json

组件读取这些令牌。它们从不查看当前启用的是哪个设计系统。

按下反馈

tanrei.sys.behavior.pressed-feedback

How a press is answered. overlay: the pressed tokens apply to the whole container at once. ripple: the pressed state layer grows from the point of contact. dim: the pressed opacity applies to the whole control and no state layer is drawn. none: no visual answer to a press (focus and hover still apply).

— 默认值,也是无法绘制该选择的平台所采用的回退

生成自 tokens/sys/behavior.tokens.json

取值 按下期间组件画什么
overlay 按下状态的令牌一次性应用到整个容器。
ripple 按下状态层从接触点向外扩展(由键盘按下时从中心开始),并按容器的形状裁剪。
dim 组件的按下不透明度应用到整个控件。不绘制状态层。
none 什么也不画。悬停和聚焦仍然显示。

这个选择只决定按下层怎样出现。它的颜色和不透明度仍然来自组件各状态的令牌,层照旧为这些令牌取值。

无论选哪一种,按下状态都会立即出现,并至少保持 sys.motion.duration.press-hold 这么久(默认 100ms,随动效调节量变化)。一次轻点或一次按键在一帧之内就结束了;没有这个下限,反馈根本来不及被看见。Button 把它写成了需求 BTN-8 和 BTN-9。

不属于种类选择的:圆角如何弯曲

圆角怎样过渡到直边,看上去像一个种类选择——圆形或连续——但它其实是一个量:Figma 的 corner smoothing,取 0 到 1,其中 0.6 是 iOS 圆角。它和它所塑造的半径放在一起,名为 sys.shape.corner-smoothing,在形状页面上说明。

焦点样式

tanrei.sys.behavior.focus-style

How keyboard focus is shown. ring: the two-tone focus ring at sys.focus offset and width. glow: the same colors as a soft halo (blurred by the ring width) instead of a hard line. Both must meet the focus contrast invariants.

— 默认值,也是无法绘制该选择的平台所采用的回退

生成自 tokens/sys/behavior.tokens.json

glow 使用与圆环相同的两种焦点颜色、偏移和宽度来绘制,所以焦点对比度不变式原样适用于它。它改变的是指示的边缘,而不是有没有指示。

内置系统

同一个 Button 在每个系统下的样子,由已安装的 Web 构建绘制。先逐个按下,再用 Tab 聚焦到它们。

先按下,再按 Tab

tanrei overlay · ring

FilledOutlined

cupertino dim · ring

FilledOutlined

m3-expressive-like ripple · ring

FilledOutlined

m3-like ripple · ring

FilledOutlined

在层中设置选择

改变一个选择和改变任何取值一样:写在 tokens 下,并附上 reason。

{
  "id": "acme",
  "extends": "tanrei",
  "tokens": {
    "tanrei.sys.behavior.pressed-feedback": { "$value": 1, "reason": "Acme 用涟漪回应按下。" },
    "tanrei.sys.behavior.focus-style":      { "$value": 1, "reason": "Acme 用光晕显示键盘焦点。" }
  }
}

$value 是一个数:该名称在令牌清单中的位置,从 0 数起。pressed-feedback 的清单是 overlay、ripple、dim、none,所以 1 就是 ripple。Tanrei 的令牌文件所用的格式(DTCG 2025.10)没有字符串类型,因此文件里存的是索引。超出清单范围的索引会被构建拒绝。

这个数只留在层文件里。生成的 CSS 带的是名称(--tanrei-sys-behavior-pressed-feedback: ripple),SwiftUI、Compose、Flutter 和 React Native 则在系统实例上拿到一个有类型的枚举。

清单本身属于核心词汇。层在这些名称中挑选,不能新增。一种新的行为方式需要每个平台都画出来,所以它和其他词汇变更一样,要向核心提出提案。

平台画不出某个选择时

每份清单的第一个名称是默认值,同时也是回退值。画不出某个选择的平台改画第一个取值,并在自己软件包的 README 中说明。

注意

索引不便手写,所以 Theme Studio(Behaviour 分组)、tanrei explain 和 MCP 服务器显示并接受的都是名称。