TUI 设计系统(Ratatui) 是做什么的?
用于新建或重构 Ratatui TUI 视觉效果,同时不破坏交互模型的规则。适用于本用户的 Rust 终端仪表盘;需与仓库内的应用说明配合使用。
使用时机
- 新建 Ratatui 仪表盘视觉层(主题、面板、徽章、仪表、标签页)。
- 重新设计/重构现有 Ratatui TUI,尤其涉及多主题、实时主题选择器、鼠标命中测试或 CI 中的确定性截图检查。
令牌架构
- 保持调色板扁平化、常量、数量少:每个主题一个语义角色结构体,通过指针进行切换。所有分层或混合的颜色都应从这些角色中派生出令牌,使用一个 RGB
blend()函数:surface和surface_hi(面板、覆盖层填充)、track(空条末端)、fade(颜色向背景方向变暗)、gradient(强调色运行)、on_color(可读徽章文字,根据亮度选择)。新调色板将一次性地重新设置所有组件的样式,满足实时主题选择器的需求。 - 组件绝不直接使用字面量
Color,只能使用主题令牌。 - 保护
blend()函数免受非 RGB 端点的干扰:ANSI 颜色没有通道,因此应快照到最近的端点,而不是凭空发明一个。
无背景主题
- 使用
Color::Reset背景的主题(单色/TTY 调色板)必须降级所有填充:表面退化为Reset,徽章变为带括号的彩色文本,空条末端使用边框颜色而不是派生的 track(因为该颜色是Reset,会渲染为终端默认前景色)。测试时确保它只绘制Reset和选中高亮。
背景完整性
- 使用单元格缓冲区测试扫描每个视图 x 覆盖层:每个单元格的背景必须位于主题提供的白名单中(
is_background令牌列表),而不是硬编码的颜色列表。硬编码列表在添加新令牌时需要手动编辑,很容易被遗忘。 Clear会重置单元格而不重新绘制;在其之后绘制的任何内容都必须重新设置背景样式。使用抬升的表面填充覆盖层,使其浮现在面板之上。- Ratatui 的
Chart通过Canvas绘制绘图区域,其背景默认为Color::Reset。在带色调的面板中,将图表背景设置为面板的填充,而不是页面的:在表面颜色的卡片内部,页面颜色会导致同样的空洞,只是层级提升了一层。
布局耦合的命中测试
- 如果鼠标命中测试镜像了绘制布局(标签页条、分段条、状态字段),则应在同一编辑中更改绘制代码和镜像数学计算。优先使用渲染驱动的测试,通过绘制列定位每个标签;手写的矩形断言可能会通过测试,而实际布局却将组件放到了其他地方。
- 添加或加宽列表高亮符号会偏移每一行的文本。可点击的行区域必须设置为全宽,或者重新计算以匹配。
字形
- 子单元格的仪表精度使用八分之一块(U+258F..U+2589),属于区块元素:仅支持 Unicode 路径;ASCII 回退则填充整个单元格。盲文字表和火花线也是如此:提供 ASCII 替代方案,不要在
--ascii模式下泄露制图符号。 - 对齐列的图标必须是单宽 BMP 符号。Emoji 是双宽的,会静默地偏移行中后续的所有列。
验证
- 重新设计:先修改样式,后修改文本。渲染测试断言文本内容,因此未改动的字符串能使测试套件保持绿色通过,同时视觉外观发生变化。
- 视觉关口:项目的确定性截图生成器(固定帧计数器,没有真实时钟,没有随机数生成)。文本转储模式是最快的布局审查方式。将重新生成的图片与源代码更改一起提交,以确保 CI 的无漂移检查能够通过。
- 在单元格缓冲区上检查背景,而不是在渲染后的图片上检查:图片渲染器将
Color::Reset解析为主题背景,恰恰隐藏了缓冲区扫描能够捕获的漏洞。 - 保持基于帧计数器的动画(脉冲、闪烁)的确定性,以实现可重现的截图。