2026-09-23·by Sijie Wang#standmeet#architecture#design

one-source-per-ui-primitive

每个界面原语只有一个源头

上级:structure

十二道闸门,一条学说:每一个视觉原语只有一份定义,再由一道构建期闸门让第二份不可能存在。 这个产品的视觉一致性真正来自这里 —— 不来自风格指南,也不来自评审。

每一道闸门都写在同一个发现之后,而那个发现的形状总是同一个:这不是"某几处漏改",而是没有这一层,于是每个面各自决定它长什么样。

闸门规矩当初发现了什么
check-one-select全 app 一个下拉,在 SelectField19 个 <select>五种互不知道的写法 —— 盒子边框 / 小盒子 / 下划线 / sm-field-input / gate 那个近黑实心(全页最重的色块)
check-one-text-input一种长相,源头是 .sm-field-input同一种控件长了两张脸:连接器凭据 / op 参数 / SEO 是整框;codes 新建弹窗、简历 composer、gate、AI provider 面板是下划线。owner 隔一屏就换一套标准
check-one-time-format时间三种写法,全在 lib/ui/format-time.ts一次会话里出现三种 —— 8/8/2026, 10:16:07 AM(美式 locale + 秒 + AM/PM)、2026-08-07T01:09:14Z(ISO+Z,给机器看的)、同一页上的 last refresh · now
check-one-scrim模态遮罩只有一个来源四条 *-overlay 规则各写一份 color-mix(…) 字面量。四份谁也不知道彼此存在:调其中一处,另外三处悄悄分叉——而分叉不会报错,只会让某些模态压得住底层、某些压不住
check-one-layer-scale层级只在一处声明"谁在谁上面"这件事读不出来:19 处层级散在两种语言里 —— CSS 九个魔数、TSX 十个工具类,没有任何一处声明这些数字的顺序含义。而"模态遮罩"这一件事本身就有三个不同的 z
check-one-empty-stateadmin 的列表空态只从 ListPane 出来每个 section 自己写 list.length === 0 ? <空态/> : <列表/> —— 这句话只有两种结局,而真实世界有三种:拉失败之后列表也是空数组,于是失败穿上了空态的衣服
check-one-section-heading一节的标题只从 AdminSectionHead 出来——
check-one-corpus-href一条语料的公开地址只有一个来源15 处各自现拼且互相不一致;体裁名被当成了路由名,于是一条 writing 的引用在生产上 404(corpus
check-sm-class-defined写进 TSX 的每个 sm-*,CSS 里必须真有一个"看起来很像"的类名渲染不出任何东西,也不报任何错
check-no-computed-classTailwind 任意值方括号里不许插值w-[${n}px] 生成零 CSS,没人报错。有四处"名字说它在表达某个量、实际是常量"
check-no-native-file-input选文件的按钮必须是这个产品画的<input type="file"> 自己画一个 Choose File / No file chosen,长相由操作系统决定 —— 跟奶油纸 + 朱红 + mono 那套语言毫无关系。在连接器弹窗里它是整扇窗唯一没被设计过的控件,就贴在被设计过的按钮旁边
check-peek-signals-more会被切的预览卡,切口处必须有续读信号summarize 的报告卡是有意的 sneak-peek(内层 iframe 写死 280px),但切口原本没有任何信号:正文断在句子中间撞上卡片边框,读起来像"坏了"而不是"还有"

为什么是闸门,不是风格指南

风格指南是建议,由"还记得它存在"的那个人去查。上面每一条都是在分叉已经上线之后才写的,而且多数分叉在评审里是看不见的 —— 五种下拉,一次看一个文件,每一个都挺好。真正要紧的性质不是"我们对齐了一种长相",而是第二种长相没有地方可住

也要说清这些闸门不是什么:它们不评判一个设计好不好。它们只强制"一个决定一旦做出,就只有一个家"(mechanical-guardrails,跟后端 convergence-inbound-and-outbound 是同一个动作)。品味仍然是人的问题;多份拷贝不再是

代价,如实说

粒度不对的闸门会挡掉能工作的行为:修"提供了一个做不到的动作"时,如果规则比那个动作更粗,就会造出"连做得到的那个动作也一起拿掉了"—— 而 CI 全程绿着,因为闸门被满足了。所以每加一道闸门要问的不只是它禁了什么,还有它禁掉的东西里有没有我还想要的

about this entry

One of sijie's wiki entries. The AI on this site is grounded in the same corpus and answers in sijie's voice, with citations back to entries like this one — answering costs sijie money, so it waits behind a code: enter an access code →