跳到主要内容
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 的组件从不改变。改变的是一个层:一个小型 JSON 文件,它为共享词汇设定值,并声明你的调色板。@tanrei/cli 把这一个文件变成各平台所需的一切。

预发布

0.1.0-next.0 已以 dist-tag next 发布到 npm:在 0.1.0 之前,请安装 @tanrei/cli@next和@tanrei/mcp@next。在 0.x 预发布期间不保持向后兼容:任何一个预发布都可能破坏任何东西,事先没有弃用期,破坏了什么写在它的 changeset 里。

安装

从 npm

把命令行工具作为开发依赖添加到你的产品中;本页上的每一条 npx tanrei … 命令运行的都是它。它带有 tanrei studio 所提供的 Theme Studio。

npm install --save-dev @tanrei/cli

MCP 服务器无需安装:代理启动它时,npx 会取来 @tanrei/mcp,注册方法见本页后文。

从源码

要使用 main 上的源码,请在仓库的克隆中构建这两个包,并把打包出的文件作为开发依赖安装到你的产品中:

git clone https://github.com/chnotchy/tanrei.git
cd tanrei
pnpm install
pnpm --filter @tanrei/studio build:app   # Theme Studio,由 `tanrei studio` 提供
pnpm --filter @tanrei/cli --filter @tanrei/mcp build
pnpm --filter @tanrei/cli --filter @tanrei/mcp pack --pack-destination ../tanrei-packages
# 在你的产品中:路径指向写入这些包的文件夹
npm install --save-dev path/to/tanrei-packages/tanrei-cli-*.tgz path/to/tanrei-packages/tanrei-mcp-*.tgz

至于 MCP 服务器,请改为注册已安装的副本:在你的产品文件夹中运行 claude mcp add tanrei -- npx tanrei-mcp。

从一个层到每个平台

  1. 创建一个层,可以从默认系统出发,也可以从某个预设出发。

    npx tanrei init acme --extends tanrei

    这会写出 design/acme.system.json 和 tanrei.json。更喜欢用滑块?那就在 Theme Studio 里调整这个层,然后把它下载下来。

  2. 在 tanrei.json 中指明每项输出写到哪里。 只列出你要发布的平台。

    {
      "system": "design/acme.system.json",
      "kotlinPackage": "com.acme.design",
      "outputs": {
        "tokens": "design/tokens/acme",
        "web": "apps/web/src/styles",
        "swiftui": "apps/ios/Acme/Design",
        "compose": "apps/android/app/src/main/kotlin/com/acme/design",
        "flutter": "apps/flutter/lib/design",
        "react-native": "apps/mobile/src/design"
      }
    }
  3. 构建。

    npx tanrei build

    提交生成的结果。把 npx tanrei build --check 加入 CI:它不写任何文件,只要已提交的输出过时就会失败。

  4. 使用。 生成的文件包含的是你的系统的值;类型来自库本身,所以词汇一旦变化,构建就会失败,而不是悄悄地发生漂移。

    平台 你得到 你要写
    Web acme.css <html data-tanrei-system="acme">
    SwiftUI TanreiSystem+Acme.swift .tanreiTheme(TanreiTheme(system: .acme))
    Compose TanreiSystemAcme.kt TanreiTheme(system = TanreiSystem.Acme) { … }
    Flutter acme_system.g.dart TanreiTheme(data: TanreiThemeData.platform(context, system: acmeSystem), …)
    React Native acme.ts <TanreiProvider system={acme}>

一处修改,一个拉取请求

在层中修改一个值,运行 tanrei build,每个平台的文件就在同一次提交中一起变化。把所有文字调大一点,只需要一行:

"tanrei.dial.type.base": { "$value": { "value": 17, "unit": "px" }, "reason": "在一臂之外阅读。" }

层可以对一个值做四件事:设定调节量、缩放令牌、重新指向别名、附带理由地固定一个值。关于这四件事,关于如何声明调色板(例如品牌色,或测验中的“正确”与“错误”),以及在仅靠取值不够时如何添加令牌,参见设计系统与定制。

想控制多深都可以,始终是同一个文件

定制是分层次的,每个层次编辑的都是同一个 <id>.system.json:

你想要 你使用
快速完成设置 Theme Studio → 左侧栏:外观的九行(品牌色、灰色、字体、尺寸、圆角、圆角平滑、图标、按下时的反馈、焦点样式),每一行点一下就能改,可以锁定,也可以随机搭配
按组调整 Studio → 左侧栏的“更多”:全部八个调节量、所有调色板、各个组件、所有行为
在图形界面中逐个调整令牌 Studio → 检查 → 令牌:搜索整个词汇;每个令牌只提供对它合法的编辑,并显示有哪些值跟随它
编辑源码 Studio → 检查 → 源码,或你自己的编辑器:JSON 会依照 schema 并由引擎进行校验
一个不存在的令牌 添加它(见设计系统与定制):序列中的一级、一行就能声明的 Button 尺寸或变体,或者你自己的令牌
npx tanrei studio

会针对你的层文件打开 Theme Studio:你所做的编辑会随时保存到该文件(可以像其他改动一样用 git 审阅),同时在编辑器中所做的修改绝不会被覆盖,“Build”则会运行 tanrei build。它只监听 127.0.0.1,打印出的链接带有一次性密钥。本站上的 Studio 是同一个工具,只是用导入和导出代替了文件。

用你的系统检查代码

npx tanrei audit src

会读取产品的代码——脚本(JS、TS、JSX)、标记(HTML、Vue、Svelte、Astro)和样式表(CSS、Sass、Less)——并报告你的系统没有的东西,每一处都给出文件、行和列,以及应改写成什么:

  • 系统没有的组件的元素——页面、模板、JSX 或字符串中的 <tanrei-fab-menu>、导入的 React 包装组件,或指向它的 CSS 选择器——并附上系统为同一用途提供的组件、拥有它的系统,以及把它纳入时要在你的层里写的那一行;
  • 从不适合该系统的入口导入——在默认系统的产品中导入 @tanrei/web/m3-like 或 @tanrei/react/all——并附上适合的入口;
  • 直接写出的、系统去掉了的 variant="…",并附上系统提供的取值。

检查依据的是产品的系统(tanrei.json),或 --system 指定的系统:m3-like 这样的内置系统,或一个层文件。可以传入文件、目录,或用引号括起的 glob('src/**/*.{ts,tsx,html,css}');读取目录时跳过 node_modules 和隐藏目录。--format json 以数据形式输出结果。发现问题时以退出码 1 结束,因此可以在 CI 中与 tanrei build --check 并列运行;无法运行时退出码为 2。MCP 服务器的 check_usage 做的是同一项检查。

它读的是文本,而不是运行中的页面:注释会被跳过,但放在变量里的 variant,或由片段拼成的标签名,是看不到的。

Tailwind CSS 与 shadcn/ui

在 outputs 中加入 "tailwind" 或 "shadcn"。这两个文件都只是把名称映射到 Tanrei 的自定义属性上,因此主题、对比度级别和实时调节量在底层照常工作。

@import "tailwindcss";
@import "@tanrei/web/tokens.css";
@import "./styles/acme.css";
@import "./styles/acme.tailwind.css"; /* bg-primary · text-on-primary · rounded-medium · p-200 · text-heading-4 */

分享一个系统:与人、与工具、与 AI 代理

  • tokens 输出是一个自包含的 DTCG 2025.10 打包文件,带有标准的解析器。任何设计令牌工具都能读取它;生成它的层文件随包一同携带,每个分组还在 $extensions["dev.tanrei.llm"] 中带有面向代理的使用指引。

  • 其中还有 components.json,即你的系统提供的组件:每个组件都写有它的元素(或类)、React 中的名称以及注册它的模块;系统没有的组件也列在其中,并注明是哪一层把它排除的、应改用什么。读取它的代理只会推荐你的产品能用的组件。Tanrei 自带的每个系统也各有一份:@tanrei/web/systems/<id>.components.json。

  • @tanrei/mcp 是一个 Model Context Protocol 服务器。在你的仓库中工作的代理可以搜索词汇、查看某个值的来历、比较不同的系统、提议一项扩展(新的 Button 尺寸、新的一级、你自己的令牌)并看到由此得到的值,还可以在写入之前校验对层的修改。它同时会被告知规则:通过层来修改值;扩展词汇只能添加,并且要附带理由;每个固定的值都要给出原因;绝不触碰阈值。至于界面本身,它根据系统的组件清单(components manifest)和规范作答:该系统有哪些组件(没有的组件该用什么代替)、一个组件的 props、事件和行为规则,以及你的代码里有哪些元素、导入和变体是该系统没有的,连同它们的位置——与 tanrei audit 做的是同一项检查。

    在你的产品文件夹中,从 npm 注册它(其他客户端的设置见与 AI 代理一起使用 Tanrei):

    claude mcp add tanrei -- npx -y @tanrei/mcp

无障碍

对比度阈值和结构性检查都是常量。在你的层中,违反是一条警告,但绝不会悄无声息:它由 tanrei build 打印出来,写入 a11y-report.json,并标注在每个生成文件的顶部。在中、高对比度下,请以零警告为目标:这些方案之所以存在,是因为有人明确要求了更高的对比度。内置预设本身在任何方案下都以对其所模仿系统的保真度来衡量,而不是以 Tanrei 的无障碍准则来衡量;它们的测量值只是参考信息。你在预设之上构建的层仍然是你的产品,它继承来的问题同样会收到警告。