关于 visant-refine
visant-refine 是用于完善界面元素绘制与视觉一致性的设计技能,适合已确定元素用途后进行精修。它涵盖图表、滑块、动画规则和代码扫描。
主要功能
- 01界面元素的统一视觉结构
- 02图表样式与状态规范
- 03滑块模拟设计约定
- 04按变量选择动画
- 05精修规则代码扫描
适用场景
- 01完善指标面板和图表
- 02设计区分事实与预测的情景滑块
- 03交付前检查界面精修规则
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ pedrojaques99/ visant-skills-public --skill visant-refine安装后在 Claude Code 中输入/visant-refine确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/charts.mdelements.mdsimulators.mdsmart-motion.mdtax-panel-case.mdscripts/refine-scan.mjs详细介绍
Visant 精修
收尾。本技能假定已经在其他地方决定并论证了纳入该元素,只回答如何绘制它。
层级,不容协商
| 技能 | 决定事项 |
|---|---|
visant-frontend | 该元素是否存在,以及它会推动哪个业务变量。删减测试在此进行。 |
dataviz | 图表是否正确:形式、按功能着色、调色板验证、反模式。 |
visant-motion | 缓动和时长的单一事实来源(SSoT),以及 React、Tailwind 和 Radix 的注意事项。 |
revenue-centric-design | 为什么要为这个元素而不是那个元素添加动画(即注意力指向何处)。 |
| 本技能 | 如何绘制该元素,以及如何让它看起来与相邻元素属于同一套设计。 |
**精修绝不会为某个元素提供存在的理由。**如果对“这会推动哪个变量”的回答是沉默,那就应该删除,而不是润色。一张没人使用的数据图表,即使收尾做得更漂亮,也仍是劣质产物,而且比丑陋的版本更耗费注意力。
工作顺序,必须严格遵循:
- 通过
visant-frontend的删减测试。为每个元素指出对应的变量。 - 清点现有内容。见下文“绘制之前”。
- 选择形式。在编写第一行图表代码之前,先加载
dataviz。 - 使用共享结构进行绘制(见下表)。
- 然后才决定动画,并参考 references/smart-motion.md。
- 按照
visant-frontend的要求进行验证(使用真实数据测试 390px、后端不可用时的情况以及键盘操作),并运行两道检查:
node ~/.claude/skills/visant-refine/scripts/refine-scan.mjs <target> # finishing layer
node ~/.claude/skills/visant-killer/scripts/killer-scan.mjs --report AUDIT.md <target>
--report 不是可选项:如果没有表面清单和 ## Screen seen 部分(## Tela vista 也可以),killer-scan 会拒绝打印 GATE OPEN(使用 --init-report AUDIT.md 生成模板)。而且,仅凭 refine-scan 返回零并不代表完整通过:干净的检测结果会让人觉得已经收尾,因为它最终会返回退出代码,而这恰恰是 visant-frontend 被彻底跳过的原因。
refine-scan 有六条规则,检查的都是能够编译、通过 lint、却仍会出问题的内容:图表属性中使用原始颜色(仅针对导入 recharts 的文件)、图表缺少状态包装器、未限定作用域的 defs id、缓动或时长不符合 SSoT、UI 中使用 transition-all 和 ease-in,以及宽度或高度动画。如果文件中提及 ChartState、isEmpty、noData、semDado 或 vazio,就视为具备状态包装器,因此适用于任何代码仓库。components/ui 中的检查结果会被抑制(上游基础组件),并在最后计数,绝不会隐藏。--self-test 会在你信任零结果之前,验证这六条规则的正反两种情况。
绘制之前:查明代码仓库中已有的内容
未经搜索,不得添加新的基础组件。几乎所有精修请求都是组合,而非构建;只有查看之后你才能确定。请在目标代码仓库根目录按以下顺序运行:
# 1. installed chart lib (recharts, visx, nivo, chart.js, echarts, d3)
grep -E '"(recharts|@visx/[a-z-]+|@nivo/[a-z-]+|chart\.js|react-chartjs-2|echarts|d3)"' package.json
# 2. existing chart state wrapper and tooltip
grep -rlE 'ChartState|ChartContainer|ChartTooltip|isEmpty' --include=*.tsx --exclude-dir=node_modules .
# 3. slider, ratio bar and skeleton primitives
find . -path ./node_modules -prune -o -type f \( -iname 'slider.tsx' -o -iname 'progress.tsx' -o -iname 'skeleton.tsx' \) -print
# 4. motion tokens (easing and duration SSoT)
grep -rnE -- '--(ease|dur|duration)-[a-z0-9-]+:' --include=*.css --exclude-dir=node_modules . | head
find . -path ./node_modules -prune -o -type f -iname 'motion.ts*' -print
# 5. color token format (bare HSL channels or full color)
grep -nE -- '--(primary|muted-foreground|destructive):' $(find . -path ./node_modules -prune -o -name 'globals.css' -print)
在编写第一行代码之前,先用“需求 | 所在位置”表记录你找到的内容。对于缺少的部分,按以下顺序搜索:
- 代码仓库本身(上面的命令)。
- Visant 库,ui.visantlabs.com,以及任何项目中已经精修过的组件:
gauge、sim-slider、measure-bar、activity-heatmap、streamgraph、count-up、elastic-slider、skeleton-rail。使用npx shadcn@latest add @visant/<name>安装,并在components.json中添加"@visant": "https://ui.visantlabs.com/r/{name}.json";每个组件的规格说明见/r/<name>.md。 - shadcn 官方基础组件(
npx shadcn@latest add slider progress skeleton)。
未经明确许可,不得创建或编辑设计系统组件。安装前先发出警告。基础组件的默认值覆盖应放在使用方中。
共同的结构
让界面看起来经过设计的,并不是每个元素都很美观,而是所有元素都以相同的顺序传达同一件事。每个收尾元素都包含以下四种角色,始终遵循相同的视觉顺序:
| 角色 | 含义 | 呈现方式 |
|---|---|---|
| 标签 | 被衡量对象的名称 | text-xs uppercase tracking-wider text-muted-foreground |
| 数值 | 起决定作用的数字 | 区块中最粗的字重,tabular-nums,中性色 |
| 限定信息 | 赋予数值含义的标尺(上限、目标、周期、基准) | text-xs text-muted-foreground,紧邻数值 |
| 依据 | 将数值与标尺进行对照的图形 | 条形、仪表、迷你折线图、色带 |
适用于任何元素的四项规则:
- 颜色是例外。 使用一种中性色,只有出现真正的例外时才使用颜色。文本使用文本令牌,绝不使用系列颜色。颜色跟随实体,而不是排名位置。
- 数值必须有标尺。 没有限定信息的数值只是琐事。“R$ 25.201,42”说明不了什么;“占毛收入的 11,3%”则有意义。
- 没有分母,就没有比率。 分母为零时应为
null,且该行不渲染。“0,0%”表达的是错误事实。 - 图形只能在其适用范围内有效。 比率条在数值未超出上限时有刻度;超出后,条形会达到饱和并失真,此时应以表示超出幅度的数字取代条形。这不是细节,而是最常体现的规则。
- 空、错误和加载是三种状态,并且都需要经过设计。
- 同类元素两端一致: 添加同类的第二个元素时,应提取第一个元素。同一事物出现两个变体,往往就是第三个变体的开端。
元素目录包含每种元素的结构、属性和常见错误: references/elements.md。
图表
加载 dataviz 并遵循其流程。此处与它不同的内容如下:
- 系列颜色来自令牌,并且会在绘制第一条线之前检查令牌格式(上文命令 5)。如果 CSS 中存储的是原始 HSL 通道(
--primary: 0 0% 9%,较旧的 shadcn 默认值),属性就需要加上包装:stroke="hsl(var(--primary))"。裸写var(--primary)会得到字符串0 0% 9%,这并不是颜色,描边会消失,而tsc、lint 或检测器都不会报错。JSX 中也不能使用原始 Tailwind 调色板颜色或十六进制颜色:像text-purple-400这样的类名会绕过通用检测器。 - 每张图表都要有状态包装器(仓库中的
ChartState,或通过命令 2 找到的等效组件)。带空轴框架的图表就是 dataviz 中的“0 项”状态。 clipPath和defs的 id 会因名称相同而冲突。 同一页面上的两张图表如果使用相同的id,就会互相覆盖;应为每个实例单独设定作用域。- 上限和目标应使用
ReferenceLine并加上标签,而不是用背景色表示。线条表达事实;颜色则会带有主观判断。 description和大型负载数据不应放入图表数据中。
可直接使用的 recharts 配方(使用 ReferenceLine 标示上限、穿过色带的累计值、无坐标轴迷你折线图、比率仪表)和令牌功能映射:
references/charts.md。
滑块模拟
如果设计没有将预测与事实区分开来,那么用于预测情景的滑块就是一台说谎的机器。最低限度的约定:
- 真实值始终显示在屏幕上,并标记在轨道本身上,同时标签要说明哪个值是什么。两个单位相同、类型不同的数字如果没有标签,就会误导读数。
- 在重要的界限处停止。 滑块应停在会改变决策的数字处(例如制度上限、税级),而不是整倍数的整数。
- 将区间绘制在轨道上,让用户在拖动前就能看到制度变化的位置。
- 一键恢复真实值,且仅在模拟处于活动状态时显示。
- 不保存任何内容。 模拟不会写入数据库,只有在需求包含分享功能时,URL 才会携带状态。
- 支持键盘操作,
aria-valuetext会读出格式化后的值。
完整约定,包括状态模式和常见错误: references/simulators.md。
智能动画
智能意味着由变量决定动画,而不是借机添加动画。由此可推导出其他规则:对承载决策的内容进行动画处理,并且只在决策发生变化时处理。
- 用户手动改变的值(拖动滑块)不应添加动画:它应跟随手指。这里的动画只是看似流畅的延迟。
- 随之变化的值(滑块重新计算出的总数,在用户松开滑块后)可以简短地递增到新数值,只播放一次。
- 越过界限是一种事件,事件值得被强调:应通过区间的状态变化来表现动画,而不是给卡片添加辉光。
- 如果用户在上一次导航中已经看到该数字,那么页面挂载时就不应为它添加动画。
- 每天发生一百次的变化不应添加动画。
每种情况的决策表,包含 SSoT 值: references/smart-motion.md。
实例:税务面板
税务模拟面板是将这三个主题结合起来的典型示例,按步骤写明了采用了什么、拒绝了什么以及原因,见 references/tax-panel-case.md。在改进任何数值面板之前,请先阅读,因为问题都一样:饱和条、将预测与事实混淆,以及对错误的数据添加动画。