展示
Diagram - 示意图
一张流程图或架构图,用系统自己的零件画出来。
用法
什么时候用它
import { Diagram } from '@misoto22/folio'说明
一张流程图或架构图,用系统自己的零件画出来。
它取代的第一种做法,是用制表符画的代码块——┌──────┬──────┐——那是一张用“为代码挑的字体”渲染出来的画。它会继承代码块的边框和滚动条,于是一张图读起来像终端输出;它没法折行,所以在手机上要么溢出要么缩到看不清;框线是文字,读屏软件会把那些线一根根念出来;而且这一切都不跟随主题。
第二种做法是引一个绘图库:几百 KB 的布局引擎,水合之后才渲染,而且用它自己那套配色画。这两者都不是:细线框走圆角刻度、等宽标签、辅助信息用弱一档的墨色——所以一张图属于它所在的页面。它是标记,所以服务端就能渲染。
嵌套即包含,这也正是大多数架构图真正在描述的事:这个在那个里面,这两个并排。箭头表示相邻兄弟节点之间的顺序,而不是任意连线——需要任意连线的图想要的是一张画,这个组件不会假装自己能画。
它接受一份 spec 而不是标记,所以文章里的 ```diagram 代码块和页面上手写的图是同一个渲染器、同一种样子——画错了,改数据就行。
结构
| 部件 | 说明 |
|---|---|
| 外框必填 | 那个 <figure role="group"> 和它里面的面板:--paper-2 之上、--radius-lg 圆角上的一条 --rule 细线,配上流体内边距和挂着细线滚动条的 overflow-x-auto——所以一张很宽的图是在自己的盒子里滚动,而不是把页面撑宽。 |
| 叶子板 | 没有子节点的节点:--paper 上一张带边框的卡片,设了 accent 时则用 --accent 填充。它的标签会在自己内部断行,因为像 TenantMainMiddleware 这样的标识符没有任何断行机会,否则就会撞上板子的边。 |
| 容器带 | 有子节点的节点:一条带标签的细线——最上一层用墨色,往下用 --rule-2——子节点排在它下面,它自己没有框。整个设计就是这一点:把容器也画成一个盒子,任何嵌到第二层的东西外面就会围上三条边框。 |
| 节点注解 | node.note,一行等宽字,落在带的标签旁边,或者板子的标签下面。一行短句,比名字退后一档。 |
| 连线记号 | 一条 edge 所指的那两个相邻兄弟节点之间的箭头,下面是这条 edge 的标签。它是 aria-hidden 的,并且在 sm 断点以下转四分之一圈——那时一排节点会堆成一列,箭头必须指向布局实际走的方向。 |
| 图注 | spec.caption,印在外框下面——用的是 <div> 而不是 <figcaption>,因为文章样式表会在 layer 之外给 figcaption 上样式,而一条不在 layer 里的规则不管特异性如何都压得过工具类。 |
实践建议
推荐
- edge 要从一个节点写到同一层里紧跟着它的那个节点,而且就按这个顺序写。一条连在不相邻节点之间的 edge、或者一条按 to→from 写反的 edge,画不出箭头——而现在它会在控制台说出来,不再把「在一张看上去已经画完的图里找出缺掉的那个箭头」丢给作者。
- id 要在整份 spec 里唯一。每条 edge 现在在第一对匹配上的节点那里就被用掉了,所以复用的一对 id 不会再把箭头画两遍——但这个箭头会落在先出现的那一对上,那是一张在断言没人写过的东西的图。
- 给 spec 一个 caption 或者一个 label。这个 figure 的 role="group" 由两者中在场的那个来命名,两个都没有,读者就只被告知这里有一个组,却从来没被告知是关于什么的组。
避免
- accent 只在叶子板那一支里被读取,所以把它设在一个有子节点的节点上,能编译、能过类型检查,什么也画不出来——容器是一条带,而带没有可以填的底。开发环境下会把这件事说出来,生产构建不会。
- direction 只从有子节点的节点上读。设在叶子上会被忽略,因为一个叶子所在的那条轴属于它的父节点——而且和带上的 accent 一样,这件事会在开发环境下被报出来,而不是被悄悄丢掉。
- 别在最上一层横着排六个节点。一行在 sm 以下是 flex-col,只有在它之上才是 flex-row,所以一张在桌面上读起来像一条流水线的图,在手机上是六块堆起来的板子和五个箭头。
示例
default
一次请求,画成三个层级,活儿嵌在中间那一层里面。只有被某条边点到名的节点才带 id,而每条边都是按数组的行进顺序写的:一条边是拿它紧挨着的前一个节点去匹配的,所以一条写成「到-从」的边,或者一条连接两个并不相邻的节点的边,什么都画不出来——但它会在开发环境里说出来,报 DIAGRAM_EDGE_NOT_ADJACENT;如果那个 id 根本不属于任何节点,报的就是 DIAGRAM_EDGE_UNKNOWN_NODE。另有三种 spec 写法会以同样的方式发出警告:DIAGRAM_DUPLICATE_ID;DIAGRAM_ACCENT_ON_CONTAINER,对应把 accent 加在一个带子节点的节点上,那个节点会被画成一条带子,根本没有可以上色的填充;以及 DIAGRAM_DIRECTION_ON_LEAF,对应把 direction 加在一个没有子节点的节点上。caption 既为读屏软件、也为读者命名这张图。
containment not wiring
只有结构、没有流向:不画边,只做嵌套。一个有子节点的节点会被画成一条带标签的细线带,没有子节点的则是一块板,正是这一点让一张三层深的图不至于在里面每样东西外面都套一圈边框。这同时也意味着 accent 只在板上上色——设在容器上它能编译、能过类型检查,然后什么都不显示,因为一条带没有可以承接颜色的填充。
a column of ranks
同一套机器,侧过来一下。spec.direction 会把顶层那一排堆起来,箭头也跟着转向,而这也正是一排在 sm 断点以下自己会做的事——所以桌面上读起来像一条流水线的六块板,到手机上就是六个堆叠的盒子加五个箭头。子层级各守各的轴:direction 是从那个有子节点的节点上读的,从不继承上一层,这也是下面那三个存储仍然并排坐着的原因。
the node it is about
一块带 accent 的板,这就是全部预算:accent 是这套系统唯一的填充,所以一张有三块的图,是一张什么都没在讲的图。footnote 印在盒子下面、盒子外面,留给那种一条注记装不下的句子。这份 spec 没有 caption,所以命名这张图那一组的是 label——两个都没有的话,读屏软件会播报出一个组,然后永远不说那是什么的组。
无障碍
- 一个 role="group" 的 <figure>,由 caption 命名,所以整张图对读者是一个可以整体跳过的东西。
- 箭头是 aria-hidden:辅助技术本来就按文档顺序读节点,用不上一个指向下一个的字形。
- 服务端渲染出来的标记,不是 canvas——每一个标签都是读屏和搜索引擎读得到的真文字。
- 一份渲染器兑现不了的 spec——一条对不上的 edge、一个重复的 id、带上的 accent、叶子上的 direction——会在开发环境下打印一条具名的警告,因为另一种结局是一张信誓旦旦地画着别的东西的图。