设计 token
src/styles/tokens.css 是颜色和尺寸(间距、大小、圆角、字重)的唯一来源。:root 是深色主题,[data-theme="light"] 和 [data-theme="dark-hc"](高对比度)在其上覆盖。插件主题和配色设置在运行时改写的也是这些变量。
- 组件里只用 token。 组件的 CSS 或内联样式中不出现十六进制、
rgb()或颜色名字面量:写color: var(--fg-muted),不写color: #8c8c8c。 - 需要新的颜色或尺寸? 在
tokens.css里为每个主题变体都加上 token,名字说明用途,而不是描述外观。 - token 是主题 API 的一部分。
plugins/themes.md里的 token 参考由tokens.css生成(pnpm gen:theme-docs),过期时scripts/theme/theme.test.ts会失败。新增或重命名 token 后要运行生成脚本。
CSS Modules
组件用 CSS Modules 写样式:Thing.module.css 放在 Thing.tsx 旁边,以 styles 导入,配合 clsx 组合。src/styles/global.css 只放文档级规则,不要在功能里添加全局 class。
图标
- 图标是来自
src/ui/icons.tsx的内联 SVG:<Icon name="folder" />,或者Button、action 的icon属性。 - 永远不要用 emoji 充当图标或装饰,UI 和用户可见的文本里都不行。
- 不带
label的Icon是装饰性的,渲染为aria-hidden。只靠图标本身传达含义时,要给它label。 - SVG 文件位于
src/ui/expui/<group>/(引入的新 UI 图标,带_dark和@20x20变体)和src/ui/openidea/<group>/(项目自绘、风格一致的图标),在icons.tsx中按名字注册。名字是Action.icon和各 contribution 使用的契约。新图标加在那里,不要在功能里内联临时的 SVG。单色图标以currentColor绘制,会随主题变化。
UI 基础组件
先用src/ui/ 里的基础组件,再考虑自己写:Button、BarButton、Input、Checkbox、Select、Dialog、Popup、Menu、Tooltip、List、Tree、Tabs、Splitter、Scrollbar、Spinner、Kbd,以及用于翻译文本的 T。它们已经处理好焦点、键盘导航、主题和标签翻译。工作台级别的部件(工具窗口、状态栏项、浮层)来自 contribution,不要自己写布局。
无障碍
- 使用真正的
<button>和<input>元素(或渲染它们的基础组件),不要用可点击的<div>。 - 每个只有图标的按钮都要有
aria-label。aria-label是文本目录会翻译的属性之一,所以和其他标签一样用英文写。 - 用户能做的每件事都是带稳定 id 的 action,因此可以通过键盘和 Find Action 访问,而不只是鼠标。
- 焦点要可见、可预期:对话框和弹出框关闭后把焦点还给原来的位置。
文本
用户可见的文本在调用处用英文书写,经过文本目录翻译;每条字符串都必须有中文。见本地化。WebKit 兼容性
在 macOS 和 Linux 上应用运行于 WebKit,最低支持 Safari 16(macOS 11 可以升级到这个版本)。pnpm build 会对产物运行 scripts/check-webkit.ts,src/platform/webkitCompatibility.test.ts 会检查应用中的正则。请避免:
- 正则后行断言(
(?<=…)、(?<!…),需要 Safari 16.4)和正则v标志; - import attributes;
- 在启动代码中使用较新的运行时 API,如
Promise.withResolvers、Object.groupBy、Map.groupBy、Array.fromAsync、String.prototype.isWellFormed。
验证 UI 改动
启动应用(pnpm tauri dev),在深色和浅色主题下都检查一遍。改变用户所见内容的 PR 需要前后对比截图,多步交互需要录屏;见贡献流程。