产品的外观改变时,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 里。
把命令行工具作为开发依赖添加到你的产品中;本页上的每一条 npx tanrei … 命令运行的都是它。它带有 tanrei studio 所提供的 Theme Studio。
npm install --save-dev @tanrei/cliMCP 服务器无需安装:代理启动它时,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。
-
创建一个层,可以从默认系统出发,也可以从某个预设出发。
npx tanrei init acme --extends tanrei这会写出
design/acme.system.json和tanrei.json。更喜欢用滑块?那就在 Theme Studio 里调整这个层,然后把它下载下来。 -
在
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" } } -
构建。
npx tanrei build提交生成的结果。把
npx tanrei build --check加入 CI:它不写任何文件,只要已提交的输出过时就会失败。 -
使用。 生成的文件包含的是你的系统的值;类型来自库本身,所以词汇一旦变化,构建就会失败,而不是悄悄地发生漂移。
平台 你得到 你要写 Web acme.css<html data-tanrei-system="acme">SwiftUI TanreiSystem+Acme.swift.tanreiTheme(TanreiTheme(system: .acme))Compose TanreiSystemAcme.ktTanreiTheme(system = TanreiSystem.Acme) { … }Flutter acme_system.g.dartTanreiTheme(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,或由片段拼成的标签名,是看不到的。
在 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 */-
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 的无障碍准则来衡量;它们的测量值只是参考信息。你在预设之上构建的层仍然是你的产品,它继承来的问题同样会收到警告。