组件

每个可交互元素支持同一套封闭的状态集:默认、hover、按下、focus-visible、禁用、加载中、选中、错误。没有第九种;看起来需要第九种状态的控件,需要的是重新思考。

高度是骨架:输入族 28,按钮、分段控件、图标按钮 32,唯一的大号主操作 40,图标底板与色块 24。下面每个组件在模板<style> 块里都有同名的类——直接套用是最省的路径,用自己的框架实现出同样的尺寸与状态也一样成立。

按钮

上排是六种 32px 外壳(含禁用与加载中),下排是 40px 的大号主操作、纯图标按钮和 Tips 胶囊。

  • button-primary——近黑、32px,回答大多数问题。平台自己渲染的 Export 就是这个形状
  • button-primary-large——40px 满宽,只给前置栏里唯一的主操作
  • button-secondary——白底描边,hover 时边框加深
  • button-ghost——透明,hover 才出底色

破坏性操作用次级外壳配 red-default 文字加二次确认,绝不用实心红。加载中保持按钮宽度、换成 spinner 并设 aria-busy

文字是动词(Generate、Export、Reset),不是 OK 或 Submit。纯图标按钮是 8px 圆角的 32px 方块,在画布上为白色。画布顶部末端角的 Tips 按钮是系统里第二个、也是最后一个胶囊:32px、白底、stroke-default 边框、20px 灯泡加文字——它要读作「帮助」,而不是又一个操作。

输入族:灰底,无边框

mm
mm
mm
mm
mm
mm
宽度不能大于 300 mm。

input-field:28px 高、92px 宽、bg-control 底、无边框、6px 圆角,文字 text-secondary 加等宽数字。错误消息放在字段旁边,不只在 toast 里。

单位固定在字段末端,不跟在数值里:10px、text-tertiary、独立元素。这样数字在起始端成行、单位在末端成行,切换 mm 与 inch 时两者各自改写。单位写在值里会随数字变长而移动,在 RTL 双向重排里还会跑到数字前面。

数值字段的初值写在 value 里,并带 inputmode="decimal"。数值字段支持横向拖拽:按住拖动改值,Shift 十倍步进,Alt 微调,位移小于 3px 算点击。用 setPointerCapture 让拖出面板不丢手势,RTL 下方向反转,并保留 Shift + ↑/↓ 作为键盘等价。不要显示原生上下箭头:目标太小,语域也不对。

生成栏里的提示词框是长大了的同一族:8px 圆角、10/12 内边距,底部末端一枚 text-disabled 的字数计数。

下拉

触发器就是 110px 的输入框,末端一枚 text-tertiary 箭头,列表展开时箭头翻转。列表是浮起的表面,所以与停靠面板不同,它带描边、8px 圆角和 shadow-200

圆形
方形
六边形
星形
点触发器可以收起再展开,点选项即选中。展开时触发器变白底加 1px `stroke-active` 边框——和聚焦是同一个状态——箭头同时翻转。

两个互不干扰的信号,每个都能单独读出来。 底色说的是你在哪:指针和键盘共用它,所以永远只有一行有底色。brand-default 的对勾加 500 字重说的是选了哪个,没有底色时它照样成立。上图里圆形是已选项,方形是指针所在。

行高亮单独占一档 12%,因为面板上的 6% 与 8% 放到浮层白底上都会消失。

行高 32px、4px 圆角、左右 10px 内边距、12px 文字用 text-primary。列表内边距 6px,不窄于触发器,超过七行开始滚动并用细滚动条。超过三个选项,下拉胜过分段控件;不到三个,分段控件胜过下拉。

它欠着的那份契约

原生 <select> 把键盘、读屏和平台选择器白送给你。给弹出层定样式,意味着这些要全部自己写一遍。模板的脚本块里已经写好了,叫 upgradeSelects移植它,不要自己重新推导。

它按渐进增强写,脚本没跑起来时控件同样可用:HTML 里是一个真实的 <select>,包在 <span class="select-field" data-select> 里。脚本把它隐藏、建出触发器与列表,并让原生元素继续作为取值的唯一真源——表单提交和你自己的 change 监听照旧生效。

1焦点永不离开触发器。aria-activedescendant 指向当前高亮项——把焦点移进列表,正是列表关闭时焦点被丢在 body 上的原因。
2触发器 role="combobox"aria-expanded,列表 role="listbox",每行 role="option"aria-selected
3收起时:↓ ↑ Enter Space Home End 或任意字符都能打开。
4展开时:↓↑ 移动,Home/End 跳到两端,Enter 或 Space 提交,Escape 不改值关闭,Tab 关闭,外部点击关闭,首字母跳转可用。
5关闭时焦点回到触发器;高亮行在列表自己的滚动盒里滚动,而不是让整页滚动。
6列表挂到 bodyposition: fixed——留在原地会被滚动的参数栏裁掉——并在滚动与窗口尺寸变化时重新定位。
7下方空间不够时翻到触发器上方;RTL 下对齐触发器的末端边。
8窄触屏退回原生 <select>:否则丢掉系统选择器,而 32px 的行在拇指下太小。

以上每一条都实现在模板脚本块的 upgradeSelects 里。它是模板里唯一要留着的部分:其余都是演示接线,你要换成自己的状态。

开关

36 × 20 轨道 · 14px 圆钮 · 位移 16px

关闭 stroke-default,开启 brand-default。轨道低于 24px 目标下限,靠字段行的 <label for> 提供那个够大的目标——五份模板都是这么接的。

轨道和圆钮是画在真实 <input type="checkbox"> 上的装饰,每一层都要 pointer-events: nonearia-hidden

滑块

6 mm
40%
40%

绝不单独出现:当前值始终以数字显示在行末,需要精度时再配一个输入框。3px 轨道用 track-off,已填充段用 brand-default,12px 圆钮白心加 2px 品牌色环。步长与范围来自模型的真实约束,被悄悄截断的值是用户看不见的 bug。

分段控件

32px 的 bg-hover 轨道、2px 内边距、6px 圆角;选项 12-medium text-secondary,选中项白底、4px 圆角、shadow-100;相邻的未选中项之间有一条 1px stroke-divider 分隔线。容器 role="group" 带名字,每个选项是 <button aria-pressed>。用于两到三个互斥视图;超过三项改用下拉。它不是页签条,不承担页面导航。

缩略图与工具栏

模板缩略图是 140px 白卡片:8px 圆角、stroke-divider 边框、shadow-100。内联 SVG 内缩 14px,照片铺满到边。风格块是同一张卡片做到 90px、不带阴影(SVG 内缩 10px);圆形主体仍用方卡片,只把里面的图裁圆。选中是 2px brand-default,叠在卡片上画,内容不会因选中而缩放;hover 是 stroke-default

工具栏 64px 宽,配 40px 底板。选中的工具是 brand-default 底、白图标。

由平台供数的两块

有两块界面的数据来自平台而不是你的生成器:预览所渲染的材质、用户的历史记录。模板把它们做成带占位数据的可用 UI,让它们从第一天就在正确的位置上;能力对你开放后再接数据。

Surface 是卡片堆底部的一张属性卡片:57px 方块一行四个,选中的那个在方块外 2px 处有一圈 2px 的 text-primary 描边。它只改变预览的渲染,绝不改变导出物。历史是前置栏里的二级页:一行返回、一行三个的 90px 方块、下面 Load more。方块沿用缩略图规则:内联 SVG 内缩 10px,照片铺满。

对话框

Fabrication Tips1 / 3
插图

Real-world units

All dimensions are physical (mm / inch) and match the exported file 1:1 — what you set is what gets cut.

原生 <dialog>showModal():480px 宽、12px 圆角、shadow-300、遮罩 bg-overlay(70% 黑)。视口不够高时正文内部滚动,头部与底部不动。头部 16/24:标题用 16-semibold,旁边一枚 20px text-tertiary 的 info 图标,末端 24px 关闭按钮,下有发丝线。往下是可选的媒体带(bg-control),再往下是底部:起始端分页点,末端按钮。放进对话框的大多数东西其实不该在里面:错误去控件旁,进度去预览区,设置去参数栏。加工 Tips 是对话框的标准用例。

Antique bronze1:1Transparent background
Reference image

生成对话框(布局 4)。深色 bg-inverse 头部复述这次选择:66px 缩略图、用 16-semibold 写的名字,以及每条已定死的事实一枚 tag。正文摞的是表单字段——这是全套规范里唯一让 form-label 站在控件上方而不是旁边的地方,因为 480px 的对话框放得下整宽的拖放区,320px 的侧栏放不下。点一个风格块就打开它,所以块本身绝不发起调用。

提示条、链接、说明文字

提示条把浅色放在消息后面、实色放在图标上,文字用 text-primary,紧挨它描述的对象(见色彩)。链接用 blue-default 并保留下划线——颜色本身不是链接的暗示。字段下的说明文字是 text-tertiary12-regular,解释一个约束而不是复述标签。

要吝啬。 能放进单位后缀的东西不要写成一句话——20 % 胜过「单块边长的百分比」。结果面板里读得到的东西不要在参数栏重复。理想的终态是参数栏里只剩两三条真正起约束作用的说明。

Esc
输入关键词搜索全部文档 · 切换 · 打开