跳到主要内容
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 的默认图标是 Material Symbols 的 Rounded 样式,字重 300。和文本字体一样,这款字体只按名称引用,不随包分发:由产品自行加载。

图标怎样绘制,由一小组令牌决定。图标框有三种尺寸:sys.icon.small、medium 和 large(默认为 16、20 和 24px),字体的光学尺寸跟随图标框。

ref.typeface.icon
The icon font. Material Symbols Rounded: a variable font whose weight and fill are set from sys.icon.
sys.icon.family
The icon font by selection. A variable icon font (Material Symbols) is one family and tells selected from unselected with its FILL axis; a static icon font tells them apart with two families (Material Icons Outlined / Material Icons). Both default to ref.typeface.icon.
sys.icon.weight
The stroke weight of every icon (the `wght` axis of the icon font).
sys.icon.fill
The fill of an icon by selection (the `FILL` axis of the icon font): 0 is outlined, 1 is filled.

生成自 tokens/ref/typeface.tokens.json, tokens/sys/measure.tokens.json

填充规则

未选中用线框,选中用填充,没有例外。 导航项、标签页、切换按钮、纸片、收藏:图标始终是同一个字形,只有填充随状态变化。填充图标和线框图标从不为了装饰而混用,也从不手动挑选——在 Web 上,填充跟随图标所在控件的状态。

填充跟随选中状态

添加
import '@tanrei/web/icons.css';
<button aria-pressed="true"><span class="tanrei-icon" aria-hidden="true">favorite</span> 收藏</button>

.tanrei-icon 会读取任意祖先元素上的 aria-pressed、aria-selected、aria-checked 和 aria-current(Tanrei 控件会把它们移到 data-aria-*,在这类控件上读取的是 data-aria-pressed、data-aria-selected、data-aria-checked 和 data-aria-current),或者图标自身及其祖先上的 data-selected(data-selected="false" 可以让单个图标不参与)。图标旁边的文本已经表达了同样的意思时,给图标加上 aria-hidden="true";没有这样的文本时,给控件一个无障碍名称。

名称也可以写在 data-icon 里,元素本身留空:

<span class="tanrei-icon" data-icon="folder"></span>

绘制出的字形相同,但名称不再是页面上的文本:它不会出现在 textContent 或 innerText 中,不会出现在用户复制的内容里,也不会进入外层控件的无障碍名称。凡是名称会被当作文本读取的地方,都可以用这种写法,例如菜单或列表的一行、表格的单元格,或测试要比对的文本。尺寸、选中状态以及从右到左布局中的镜像,都与把名称写成文本时完全一样。如果图标旁边的文本已经表达了同样的意思,仍然要加上 aria-hidden="true":Firefox 128 之前的版本会把这个名称读进无障碍名称。

在原生平台上,同样的取值随设计系统一起提供(system.icon),另有一个小的辅助函数,把“是否选中”和尺寸转换成字体所需的参数。Tanrei 目前还不提供图标组件。

每个设计系统一套图标集

图标集属于设计系统,所以层可以更换它。各内置系统解析出的结果如下:

设计系统 family.unselected family.selected weight fill.unselected fill.selected
tanrei Material Symbols Rounded Material Symbols Rounded 300 0 1
cupertino Material Symbols Rounded Material Symbols Rounded 300 0 1
m3-expressive-like Material Symbols Outlined Material Symbols Outlined 400 0 1
m3-like Material Symbols Outlined Material Symbols Outlined 400 0 1

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

图标字体区分选中与未选中的图标,有两种办法,这组令牌两种都能覆盖。选中的图标总是同时取 family.selected 和 fill.selected;两者之中究竟哪一个改变了画出来的结果,取决于图标集。

一个可变字体族

可变图标字体(例如 Material Symbols)是带有 FILL 轴的单个字体族。两个字体族令牌默认都指向 ref.typeface.icon,所以只要重新指向这一个令牌就能更换图标集,再由 fill.unselected / fill.selected 区分两种状态。m3-like 写的全部内容就是这些:

"tokens": {
  "tanrei.ref.typeface.icon": { "$value": ["Material Symbols Outlined"], "reason": "Material Design 3 以 Outlined 样式绘制 Material Symbols。" },
  "tanrei.sys.icon.weight":   { "$value": 400, "reason": "Material Symbols 在 Material Design 3 中的默认字重。" }
}

两个静态字体族

静态图标字体没有轴。它把线框和填充两种画法作为两个独立的字体族提供,所以层要为每种状态各指定一个:

"tokens": {
  "tanrei.sys.icon.family.unselected": { "$value": ["Material Icons Outlined"], "reason": "Acme 使用静态的 Material Icons 图标集:未选中时用线框。" },
  "tanrei.sys.icon.family.selected":   { "$value": ["Material Icons"], "reason": "Acme 使用静态的 Material Icons 图标集:选中时用填充。" },
  "tanrei.sys.icon.weight":            { "$value": 400, "reason": "静态图标字体只有一种字重;Material Icons 按 400 绘制。" }
}

填充和字重令牌保持原样。静态字体会忽略这些轴,所以它们没有害处,组件也不需要知道当前启用的是哪一种图标集。这个层就是仓库自己的测试样例(packages/tokens-build/test/fixtures/acme.system.json)。

图标名称由产品负责

Tanrei 决定的是图标怎样绘制,而不是有哪些图标。各图标集对字形的命名不同,一套图标集也可能缺少另一套里有的字形。更换图标集的产品需要核对自己用到的名称。不是字体的符号集(例如 SF Symbols)无法用字体族令牌来指定;这一点已作为 platform-symbol-sets 记入模仿差距登记表。

React Native

React Native 的 <Text> 无法设置字体变体轴,所以使用可变图标字体时,FILL 到不了字形,图标在两种状态下看起来一样。要在那里守住这条规则,可以像上面那样使用两个静态字体族,或者用 SVG 绘制图标。

四个原生软件包的图标辅助函数正在迁移到“每种状态一个字体族”的模型;在某个软件包的 README 说明这一点之前,应当认为该软件包只读取单个字体族。