ByteNoteByteNote
DeepSeek Harness 的样式令牌分层设计
字

字节笔记本

2026年10月6日 · 约 4 分钟读完

DeepSeek Harness 的样式令牌分层设计

API中转
¥120

DeepSeek Harness 是 DeepSeek 开源的 agent 框架,走一切皆插件的路线,底层由 Cordis 框架驱动。除了核心运行时,它还带一套完整的 Web 界面,把会话、终端、代码 diff 都搬进浏览器。界面代码养到一定规模,最先失控的往往不是功能,而是样式:颜色散落在各个组件里,改一个主题色要翻十几个文件。这个项目用一份很短的样式参考文档把边界划死了,本文拆解它的做法。

三个角色,一条链

规范把浏览器端的样式职责切成三层,每一层只有一个所有者。

最底层是 ui-theme 包。它持有以 --dsw- 为前缀的静态色阶,以及语义别名、排版、动效、渐变、阴影、滚动条样式和明暗主题偏好。值得一提的是,这些 token 的当前值由源码生成,统一放在 ui-theme 的 styles 目录里,文档刻意不重复这份清单,避免同一份事实在两处维护。

中间层是 ui-layout 包。它不做任何视觉决策,唯一的职责是把解析完成的主题快照应用到文档上。功能代码看到的永远是应用完成之后的结果,不需要自己判断当前处于哪套主题。

最外层是各个功能包。它们只允许消费语义别名,例如 --dsw-alias-* 这样的变量,不得另起炉灶定义第二个全局主题。

DeepSeek Harness 样式职责分层:ui-theme 持有令牌,ui-layout 应用快照,功能包消费别名

全局与组件的分界

全局样式表统一归 ui-theme 所有,组件样式则用 CSS Modules 跟组件文件放在一起,不设集中的组件样式仓库。

这条边界上留了一个口子:当某个值只属于单个组件的布局或呈现约定时,组件可以定义局部自定义属性,比如只影响自身的间距与尺寸。但共享的颜色、排版、层级和动效,一律归主题包所有,组件不得私藏。

写组件的七条硬规则

规范给功能组件列了七条规则,条条指向同一个目标:不让视觉决策渗进组件层。

一,用 CSS Modules 和 clsx 组合类名,不引入组件库,也不用 Tailwind,依赖面收得非常窄。

二,功能组件只用 --dsw-alias-* 语义 token,禁止复制静态色板值,禁止直接写颜色字面量。组件样式里出现十六进制色值,就是越界。

三,功能组件的 CSS 里不得出现主题选择器。明暗两套覆盖全部归主题所有方,组件不掺和。

四,字号必须与行高配对使用;已有排版角色匹配时,直接用主题排版变量,不自己拍数字。

五,源码文本、终端输出和 diff 行这类内容,组件约定要求保留列结构时不得换行;滚动条一律用共享样式,不写组件专属的滚动条选择器。

六,呈现规则写在 CSS 里。React 内联样式只允许传递组件局部的自定义属性值,不得用内联样式编码主题分支,比如按明暗模式写死两套颜色。

七,新增过渡动画或仅悬停可见的控件时,必须保留清晰可见的键盘焦点,以及减少动态效果下的行为,可用性不让步。

DeepSeek Harness 的令牌变更流程与组件红线清单

改一个 token 要走哪几步

变更也有固定路径。要新增或修改共享 token,先动所属的 ui-theme 样式表,然后让功能包改用它的语义别名。公共样式约定发生变化时,同步更新所属包的参考文档;视觉行为的验证遵循仓库的测试策略,设计依据记录在仓库的过程文档里,方便后来人追溯。

整条链路里,功能的变更永远不直接碰色值,主题的变更永远不触碰组件,所有改动都发生在自己那一层。

值得抄的三个思路

第一,静态刻度与语义别名分离。色阶是原料,别名是语义,功能代码只认语义,主题换肤时组件零改动。

第二,应用与决策分离。ui-layout 只负责把解析结果落到文档上,这个中间层让主题快照成了唯一的事实来源。

第三,用红线而不是倡议。规范里全是「不得」「禁止」级别的硬规则,没有「建议」「尽量」。样式治理靠模糊的倡议守不住,能守住的是可检查的禁令。

对任何在做多主题界面的团队来说,这份文档都是一份可以直接抄的作业。

相关文章

分享: