mcpField
F
figure

figure

github.com/markomitranic设计与 UI040 次安装4 天前更新
代码仓库

关于 figure

figure 是用于在文档站点中选择和绘制说明性图形的技能。它指导作者挑选合适的图表形式,并规定 SVG 标记、主题配色和连接线约定,使图形符合站点的视觉规范。

主要功能

  1. 01选择图形形式的指引
  2. 02各类图表布局参考
  3. 03基于主题的 SVG 色彩令牌
  4. 04标签、节点和连接线规则
  5. 05Mermaid 与图表的适用场景说明

适用场景

  1. 01说明系统机制的运作方式
  2. 02为文档段落选择合适的图形
  3. 03制作适用于不同色彩模式的图形
  4. 04让图表遵循站点约定

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/markomitranic/jotdown --skill figure

安装后在 Claude Code 中输入/figure确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/forms/
bar.md
dependency.md
fishbone.md
flowchart.md
journey.md
layers.md
line.md
loop.md
nested.md
pyramid.md
quadrant.md
radar.md
sankey.md
scatter.md
sequence.md
state.md
story-map.md
swimlane.md
timeline.md
tree.md
treemap.md
venn.md
wardley.md
waterfall.md
what-talks-to-what.md
scripts/
render.ts

详细介绍

图示

此代码库中的文档页面用手绘图示来说明机制。默认形式是内嵌 SVG,直接放在 .mdx 中,并且只使用 --jd-fig-* CSS 变量绘制,因此无需额外处理,就能适用于两种颜色模式。本文末尾附近介绍了一种 HTML 图示,作为备用方案。

本文是索引:介绍如何选择图示形式,以及每种图示都必须遵循的规则。每种形式的布局语法都在 references/forms/ 中,每种形式各有一个文件;选定形式后再加载对应文件,而不是一次性全部加载。绘图技巧来自随 Claude Code 提供的技能,在绘制第一行 SVG 之前通过 Skill 工具加载。

调色板包含 13 个令牌,均根据项目主题精心设计:

令牌用途
--jd-fig-ink标签,取自 foreground
--jd-fig-muted次级标签和弱化文本,取自弱化前景色
--jd-fig-line方框轮廓和连接线
--jd-fig-line-soft细线、分隔线、最淡的轮廓
--jd-fig-surface方框填充色
--jd-fig-accent、--jd-fig-accent-soft图示重点涉及的一两个元素,取自 primary
--jd-fig-p-ink、--jd-fig-p-bg第一种色调,取自 chart-1
--jd-fig-d-ink、--jd-fig-d-bg第二种色调,取自 chart-2
--jd-fig-i-ink、--jd-fig-i-bg第三种色调,取自 chart-3

图示、图表还是编辑插画

此技能用于绘制图示:以标准形式和网站的图示调色板呈现机制的组成部分及其连接方式。除此之外,还有另外两种技能:

  • 用真实数据绘制的条形图、折线图、面积图、饼图或雷达图,应使用 <Chart /> 块。请使用 chart 技能。
  • 每个页面开头的配图,就像杂志文章开篇时的插画,是编辑插画。请使用 editorial-illustration 技能;它会以自身风格绘制到单独的 SVG 文件中,而不是页面内,并且不遵循以下规则。图示应放在章节中,用于解释内容。

应加载哪个内置技能

根据下文确定的形式,加载一个技能,而不是全部加载:

形式加载涵盖内容
任何机制:方框和箭头、流程、层级结构、时间线artifact-diagramming图示何时值得绘制、如何呈现真实机制、如何标注箭头
任何图表dataviz选择图表类型、控制标记数量、坐标轴和标签规则、配色公式
使用真实排版的 HTML 图示frontend-design(一个并非始终安装的插件)不显得像套用模板的字体、间距和布局选择

跳过 artifact-design、artifact-capabilities 和 design,它们针对的是完整的 Artifact 页面。你能使用的其他任何视觉技能都可以加载。它们的机制面向独立页面,因此请忽略其中关于 data-theme、currentColor、CDN 和页面布局的说明。只有绘图建议适用;标记和颜色由本文决定。

先选择形式

阅读图示所在段落,并判断它讨论的内容类型。然后在表格中查找对应内容。在查看任何表格行之前,先做一个更简单的判断:如果一句话或一个三列表格能同样快速地说明问题,就直接写出来。

表格中的一行只是候选项,并非最终结论。放置矩形之前,请打开对应文件并阅读开头的适用条件;如果某种形式不符合自身条件,那它就是错误的选择,无论表格中的描述看起来多么合适。机制表格的最后一行是一个真正可选的去处,并非无奈之选;归入这一项并不表示分类失败。多种形式共用一个文件,因此应打开参考列中指定的文件。

Mermaid 或图

在这里绘图的另一种方式是使用 ```mermaid 围栏,而且仓库规则已经设定好:对于由人维护的确定性参考图,使用 Mermaid;对于配在正文旁的插图,使用图。四种形式几乎总是属于第一类,因为它们的内容是之后会有人编辑的数据集:甘特图、看板、ER 图或数据库架构图、类图。它们的行指向围栏,不需要对应的表单文件。其他情况则要判断适合哪一种。用于说明 API 规范的时序图应使用围栏;用于解释缓存为何存在的三方时序图则应使用图。

机制
正文内容形式参考
系统的组成部分,以及哪些部分彼此相连谁与谁通信forms/what-talks-to-what.md
软件的运行位置:主机、区域、副本、版本部署forms/what-talks-to-what.md
端到端的数据平台:来源、核心、使用者平台集成forms/what-talks-to-what.md
遗留系统全貌,即迁移前的状态当前状态forms/what-talks-to-what.md
带有分支的决策,即“我是否应该……”流程图forms/flowchart.md
按时间顺序排列的参与者间消息、请求跟踪时序图forms/sequence.md
状态,以及事物如何在状态间转换状态机forms/state.md
按时间排列的事件:发布、里程碑、事故时间线forms/timeline.md
团队或角色之间交接的流程泳道图forms/swimlane.md
同上,并注明每个步骤的输入和产出流程图forms/swimlane.md
分层的抽象级别、技术栈、级联结构层级堆栈forms/layers.md
按质量级别划分的单个数据集存储层奖章架构forms/layers.md
按包含关系划定的范围、信任区域、影响范围嵌套图forms/nested.md
从父项到子项:分类体系、文件树树形图forms/tree.md
所有权归属、路由、升级处理组织结构图forms/tree.md
依赖关系,以及共享依赖或循环依赖依赖关系图forms/dependency.md
首尾相接的循环,且由一个中心节点保存状态循环图forms/loop.md
实体、字段、基数,或实际表和外键ER 图、架构图一个 ```mermaid 围栏,erDiagram
类、继承、组合、操作UML 类图一个 ```mermaid 围栏,classDiagram
提交、分支和合并Git 图一个 ```mermaid 围栏,gitGraph
不属于上述名称的机制绘制正文所描述的内容无对应文件,见下方规则
比较和位置
正文内容形式参考
两个坐标轴、优先级排序、2x2 矩阵象限图forms/quadrant.md
两个或三个概念的交集维恩图forms/venn.md
排名层级,或转换过程中的流失情况金字塔图或漏斗图forms/pyramid.md
价值链与各环节的商品化程度Wardley 地图forms/wardley.md
按角色、按组件划分的权限访问矩阵markdown 表格
工作和人员
正文内容形式参考
人员在各阶段的任务及其感受用户旅程图forms/journey.md
按发布版本切分的叙事主线故事地图forms/story-map.md
按类别归纳的某种结果成因鱼骨图forms/fishbone.md
按阶段划分的任务及其开始和结束日期甘特图一个 ```mermaid 围栏,gantt
按状态划分的进行中工作、WIP 限额、阻塞项看板一个 ```mermaid 围栏,kanban
数字

加载 dataviz 来绘制图表本身。段落中三句都在讲数字的话, 就应该用以下形式之一。普通的条形图、折线图、面积图、饼图或雷达图是 chart 技能中的 <Chart /> 块;只有当这里需要该块不支持的形式,或它无法承载的注释时,才自行绘制。

文本内容形式参考
变化的数值、各类别的数量或排名条形图forms/bar.md
每项恰好有两个数值,且差值是重点哑铃图forms/bar.md
通过带符号的步骤,从起始总量过渡到结束总量瀑布图forms/waterfall.md
随时间变化的趋势折线图forms/line.md
每项在两个时间点之间的变化斜率图forms/line.md
多个快照之间的排名变化排名变化图forms/line.md
每个系列各自的分布山峦图forms/line.md
两个变量:相关性、聚类、离群值散点图forms/scatter.md
三个变量:x、y 和一个量级气泡图forms/scatter.md
一个变量,每项对应一个点蜂群图forms/scatter.md
数量在不同阶段之间拆分并合并桑基图forms/sankey.md
整体中的一部分,且相对大小是重点矩形树图forms/treemap.md
按三到五项标准为多个事物评分雷达图forms/radar.md
一个系列跨多个类别,且类别的循环顺序很重要极坐标图forms/radar.md

标记

<figure className="jd-fig">
  <div className="jd-fig-frame">
    <svg viewBox="0 0 960 240" role="img" aria-label="One sentence describing what the figure shows">
      ...
    </svg>
  </div>
  <figcaption>The takeaway.</figcaption>
</figure>

框架的 jd-fig 类负责边框、宽度、窄屏缩放,以及 <text> 的等宽字体,因此图形本身无需处理这些内容。

SVG 图形的标题不会显示在页面上。屏幕阅读器和搜索引擎会读取它;读者展开图形时,标题会显示在绘图下方。因此,图形周围的文本负责阐明重点,而标题则为只看图形的读者复述重点。HTML 图形无法展开,标题会始终显示。

规则

  • 所有颜色都必须使用 var(--jd-fig-*),填充和描边都不例外。每个令牌都源自项目主题:中性色来自外壳,强调色来自 primary,p、d 和 i 色调来自 chart-1 到 chart-3。图形不得自行指定颜色。
  • 这是 JSX。 属性使用驼峰命名:fontSize、strokeWidth、strokeDasharray、textAnchor、markerEnd、letterSpacing。将 & 转义为 &amp;。注释写作 {/* ... */}。
  • 标签仍然会按 Markdown 解析。 <text> 中的 _category_.json 会在 SVG 内渲染为 <em>;浏览器会将其移出,React 会发现树与自己发送的不一致,于是丢弃页面并在客户端重新绘制。标签中的强调格式要进行转义(\_category\_、\*),或者直接去掉格式。单词前的冒号(11:04:07)也会导致同样的问题;不过框架会将这种情况恢复为文本。
  • 标记 ID 在整个页面范围内唯一。 页面上的所有图形共用一个 DOM,因此每个图形中的 <marker> ID 都要加上图形专属前缀(lk-arrow、lk-arrow-accent),且不要在多个图形中重复使用 arrow。
  • 4px 网格。 每个 x、y、宽度、高度、半径和间距都必须是 4 的倍数。坐标以 1、2、3、5、6、7 或 9 结尾就是错误。描边宽度和字号不受此限制。
  • viewBox 宽度为 960。 高度按绘图内容设置,不要留空。
  • 字号层级。 节点标签用 12(名称用 fontWeight="600"),注释和箭头标签用 10,副标签用 9.5,并设置 opacity="0.75"。全大写的眉题和区段标题使用 fontSize="10" letterSpacing="1.5"。不要使用 writing-mode 设置垂直文字;应将单词拆成多行排列。
  • 强调色最多突出一项,最多两项。 --jd-fig-accent 用来标示图形的重点:新增的跳转、读者应注意的状态,或正在讨论的路径。如果有四项都需要它,说明你还没决定图形的重点。其他内容使用墨色、柔和色和图层色调。
节点角色

角色由形状和描边体现。除非角色另有说明,填充保持低调。

角色填充描边
图示重点描述的一个或两个节点accent-softaccent,strokeWidth="1.5"
一个步骤、一项服务、一个组件surfaceline;如果图示有分层,则使用该层的墨色(p-ink、d-ink、i-ink)
一个存储、静止状态、文件、记录分层时使用该层的背景色(p-bg、d-bg、i-bg),未分层时使用 line-soft与组件相同
不受我们控制的对象:供应商、浏览器、第三方surfaceline-soft,标签使用 muted
可选、异步、不总是存在的对象surfaceline,strokeDasharray="4 3"
区域、边界、分组无line-soft,rx="8",眉题标签置于左上角内侧

节点使用 <rect rx="4">。

区域

区域用于归类共享同一层级、所有者、环境或信任边界的节点。任何形式的图示都可以使用区域,且通常会使用多个区域。

  • 使用无填充、描边为 line-soft 的 <rect rx="8">,并在绘制其他所有内容之前绘制,这样箭头和标签就会显示在其上方。如果边界表示网络边界或信任边界,而非分组(如 VPC、安全组、环境),则使用虚线(strokeDasharray="4 4")。
  • 在区域左上角内侧放置眉题标签,使用 fontSize="10" letterSpacing="1.5" 和 muted,标签与下方第一个节点之间留出 16px 的间距。
  • 区域最多三个。超过三个就会显得像泳道,此时应改用泳道。
  • 区域不是节点,也不拥有任何箭头。连接其中的节点,并由区域标签说明这些节点的共同点。
连接线

先绘制区域,再绘制箭头,然后绘制箭头标签,接着绘制节点,最后绘制节点文本。 在箭头之后绘制的方框会遮住箭头超出的部分;在节点之前绘制的标签必须放在画布的空白处,否则会被节点遮住。

每种描边颜色只定义一个标记,每个图中的标记 ID 添加对应前缀:

<marker id="lk-arrow" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
  <path d="M0,0 L10,5 L0,10 z" fill="var(--jd-fig-line)" />
</marker>
线条含义
实线 line,strokeWidth="1.5",实心箭头主要流程、调用、数据流动
实线 accent,strokeWidth="1.5",accent 箭头图中重点路径
虚线 muted,strokeDasharray="4 3",strokeWidth="1",实心箭头返回流、次要流程、可选内容
虚线 muted,空心箭头(fill="none",标记中的路径带描边)异步、事件、单向通知
普通 line,无箭头无方向的关系、细线

除文件中列明的例外(数据曲线、桑基图带、环形结构的圆环和辐条、鱼骨图的骨架、Wardley 链接)外,所有图形形式都遵循以下六条规则:

  1. 采用圆角直角连接线。 只有当两个点的 x 或 y 坐标相同时,才使用直线 <line>。其他情况都使用带半径为 8 的四分之一圆角的折线。从 (200,120) 到 (400,200),先向右再向下,在 x 300 处转弯:
    <path d="M 200,120 H 292 Q 300,120 300,128 V 192 Q 300,200 308,200 H 400"
      fill="none" stroke="var(--jd-fig-line)" strokeWidth="1.5" markerEnd="url(#lk-arrow)" />
    
    虚线路径也采用相同的走线方式;虚线表示线条的含义,而非走线方式。
  2. 标签与描边之间留出 6 到 10px 的间距,绝不压在线上。 标签居中放在线段上方(水平线)或旁边(垂直线),最多三个词。不要使用遮挡矩形:标签应放在画布空白处;如果找不到合适的位置,说明图形超出了预算。
  3. 连接线之间不得共用路径。 平行线段从头到尾保持 12px 的间距。两条线必须交叉时,较不重要的一条用小弧线跨越,且只能有一条跨越。如果需要堆叠连接线,说明两个节点距离太近。
  4. 共用方框边缘的连接线要使用各自的连接点,第 k 个连接点在长度为 L 的边上位于 L · k / (N + 1) 处,彼此间距不得小于 12px。
  5. 连接线不得从非起点或终点的方框后方穿过。 应重新规划走线。唯一例外是方框恰好位于唯一的直线路径上,例如页脚栏:此时线条必须使用虚线,标签放在可见端,箭头不得落在被穿过的方框上。
  6. 标签不得放在稍后绘制的方框会遮住的位置。 放在所属节点内部的徽标没有问题;放在区域上的标签也没有问题,因为区域会先绘制。
图表
  • 绘图区位于 viewBox="0 0 960 480" 内,x 坐标范围为 80 到 920,y 坐标范围为 40 到 420,为左侧的坐标轴数值和下方的类别名称留出空间。
  • 使用 4 到 6 条 line-soft 网格线,strokeWidth="0.8";坐标轴线使用 line;坐标轴数值使用 fontSize="10" 和 muted,并在 x 72 处右对齐;类别名称使用 fontSize="12" fontWeight="600"。
  • 仅一个焦点标记使用 accent。其他标记均使用 line-soft 填充和 muted 描边。
  • 标记上的数值使用 fontSize="10"。只有在相同编码重复出现时才添加图例;此时在绘图区下方放置图例条,并在上方加一条细线。
  • 数量轴从零开始。图注说明标记所编码的内容,正文说明数字的来源。

HTML 图示

优先使用 SVG。只有当 SVG 不适合某类特定图示时,才考虑使用 HTML:例如需要真实的文本换行、长列表,或装饰成图示的对比表。交互内容不适合放在页面上,因为页面无法运行代码。

HTML 图示使用相同的 jd-fig / jd-fig-frame 包装器,并通过图示内部的 <style> 标签设置样式。MDX 会将 { ... } 解析为 JSX 表达式,因此 CSS 必须是模板字符串子项,否则构建会失败:

<figure className="jd-fig fig-checkout">
  <style>{`
    .fig-checkout .step { background: var(--jd-fig-surface); border: 1px solid var(--jd-fig-line); }
    .fig-checkout .step.active { background: var(--jd-fig-d-bg); color: var(--jd-fig-d-ink); }
  `}</style>
  <div className="jd-fig-frame">
    ...
  </div>
  <figcaption>...</figcaption>
</figure>
  • 将每个选择器嵌套在图示上唯一的 fig-* 类下。像 .step 这样的裸类名在页面挂载期间是全局的,会重新设置主题元素的样式。
  • 颜色仍然只能来自 --jd-fig-* 令牌。和仓库中的其他地方一样,不要使用内联 style 属性。
  • 这是页面中唯一允许使用局部 <style> 标签的地方。绝不要将图示样式提升为新的正文块类;文章正文应使用纯 Markdown。

品味

图示应配合特定的正文内容,展示正文正在解释的事物,就像优秀的教育者在白板上作图一样。可以在图示形式上发挥创意,但不要在比喻上发挥创意:要说明段落所说的内容,以及正在发生的变化。

  • 章节中的段落、代码和图示交织在一起。图示应指向周围段落中的概念。
  • 每个图示只表达一个想法。通常需要图例的图示应拆成两个。
  • 画出实际机制。方框代表真实组件,箭头代表真实调用或数据,并且每条箭头都要标注其传递的内容。
  • 最好的做法通常是删减。两个总是同时出现的节点应合并为一个节点。布局已能清楚表达的关系不需要连线。节点超过九个时,很可能应该拆成两个图示。
  • 图示中的文字少于 20 个词。细节应放在正文中;图示的作用是让人一眼看懂。

绘制前先说明计划

在回复中、SVG 的第一行之前,先用一两句话说明你选择的形式、图示的主题(需要强调的内容),以及受预算限制而无法纳入的内容。如果有人要阅读图示,他们可以用一句话的代价调整方向,而不用等到图示完成后再付出修改代价。

这样做的原因是:此时发现形式不合适,修改成本很低;等二十分钟后坐标都已排好,沉没成本会让人倾向于保留它,修改成本就很高了。只有当请求已经明确指定形式和内容时,才跳过这一步。

渲染并查看

不能仅凭 SVG 源码判断效果。渲染页面上的图示,查看图像,修正问题后再次渲染:

export AGENT_BROWSER_SESSION="$(agent-browser session id --scope worktree --prefix task)"
bun .agents/skills/figure/scripts/render.ts docs/index.mdx

它会使用项目主题渲染页面上的每个 jd-fig,分别生成深色和浅色版本,并打印 PNG 文件的路径。在页面后加上数字即可只渲染对应的图示。请在仓库根目录运行;需安装 agent-browser。使用 bun 或 node 均可运行。

完成前检查

  • 图示是否包含其形式文件要求的所有内容?
  • 绘制前是否说明了形式和主张?最终绘制的内容是否仍与之相符?
  • 是否可以删掉某个节点、箭头或标签,而不影响图示的理解?
  • 强调色是否最多用于两个元素?这些元素是否正是图示的主题?
  • 每种颜色是否都使用令牌?每个属性是否都使用驼峰命名法?每个 marker 的 id 是否都有前缀?
  • 每个坐标是否都落在 4px 网格上?每个连接线是否都是折线或直线?每个标签是否都避开了线条和方框?
  • 是否已在两种模式下渲染并查看图像?
  • aria-label 是否用一句话说明图示展示的内容,而没有描述图形形状?

评论

支持 Markdown