5.8 KiB
DESIGN.md · 插件视觉一致性规范
读者是写 UI 的 Agent/开发者。目标:任何来源的插件,界面观感与宿主完全一致。 规则分两类:强制(可机器校验/一眼可辨)与默认(无充分理由不得偏离)。 契约问题看 ../plugins.md;本文件只管"长什么样"。
0. 两条铁律
- 色值只允许来自 token。任何
#hex/rgb()硬编码(规范中列出的除外)都算违规;语义永远用 token 名表达(text-ink-3而不是text-gray-400)。 - 不发明新组件形态。先查本文 §4 标准模式;确需新形态时,用 §1 的 token 组合拼装,不引入新色/新圆角/新阴影。
1. Token 表(单一事实源:peer://assets/tokens.css = 宿主 beautifului.css)
表面(背景)
| token | 意图 |
|---|---|
--page |
页面最底层背景 |
--surface |
卡片/面板表面 |
--inset |
内嵌区域(输入框底、预览底、代码块底) |
--hover / --hover-2 |
悬停态一级/二级 |
文字
| token | 意图 |
|---|---|
--ink |
主文字(标题、关键值) |
--ink-2 |
次级文字(正文说明) |
--ink-3 |
弱化文字(占位、提示、元信息、路径) |
边线
| token | 意图 |
|---|---|
--line |
常规边框(卡片、列表分隔) |
--line-strong |
强边框(输入框、可点击描边按钮) |
--line-soft |
极弱分隔 |
强调与语义
| token | 意图 |
|---|---|
--accent / --accent-ink / --accent-tint |
品牌强调(主按钮、选中、链接) |
--green / --green-tint |
成功/正常 |
--orange / --orange-tint |
警示 |
--red / --red-tint |
错误/危险 |
阴影(全部是描边式,禁止投影类阴影)
--shadow-hairline(发丝线)· --shadow-btn(按钮)· --shadow-card(卡片)· --shadow-raised(浮起)· --shadow-overlay(弹层)· --shadow-inset-field(内嵌输入)
动效
--duration-fast/base/slow(统一 400ms)+ --ease-standard。悬停/切换用 transition-colors 即可。
2. 类名词汇(宿主 Tailwind 映射,renderer 组件直接用)
背景 bg-page / bg-surface / bg-inset / bg-hover / bg-accent / bg-accent/10 ·
文字 text-ink / text-ink-2 / text-ink-3 / text-accent / text-red ·
边框 border-line / border-line-strong / border-dashed border-line ·
圆角 rounded-card(卡片/输入块)rounded-control(按钮/输入框/徽标)。
3. 字号与间距(默认)
- 字号阶:
10px(徽标)/11px(辅助按钮)/11.5px(次要按钮、说明)/12px(正文说明) /12.5px(行标题/正文)/16px(页面标题)。不使用其他字号;行高leading-4/5。 - 间距基数为 4px:卡片内边距
px-3 py-2.5,区块间space-y-1.5,小节间pt-3。 - 图标 12–16px,线条风格,
currentColor。
4. 标准模式(复制即用)
renderer 组件优先用组件库:本节模式已在
@aso/plugin-sdk/ui代码化 (Button/SettingRow/EmptyState/LoadingState/ErrorState/Badge…, 见 L6),直接 import,不要手写。 下面的 HTML 形态留给 iframe 插件页作者。
设置行(label 左 / 控件右)
<div class="flex items-center justify-between gap-3 rounded-card border border-line px-3 py-2.5">
<div class="min-w-0">
<div class="text-[12.5px] text-ink">标题</div>
<div class="mt-0.5 text-[11px] leading-4 text-ink-3">说明文字</div>
</div>
<!-- 控件 -->
</div>
按钮
<!-- primary -->
<button class="rounded-control bg-accent px-3 py-1.5 text-[11.5px] font-medium text-white hover:opacity-90">主操作</button>
<!-- ghost -->
<button class="rounded-control border border-line-strong px-3 py-1.5 text-[11.5px] text-ink hover:bg-hover">次要操作</button>
徽标
<span class="rounded-control bg-hover px-1.5 py-0.5 text-[10px] text-ink-3">全局 v0.1.0</span>
空态
<div class="flex flex-col items-center justify-center gap-1 rounded-card border border-dashed border-line py-12 text-center">
<div class="text-[13px] font-medium text-ink-2">暂无数据</div>
<div class="text-[11.5px] text-ink-3">怎么产生的提示</div>
</div>
开关(switch)
宿主规格:h-5 w-9(行内)/ h-6 w-10(表单级),滑块 size-4/5 rounded-full bg-white shadow,开 bg-accent、关 bg-line-strong。
5. iframe 插件页附加规则
<head>必须引入<link rel="stylesheet" href="peer://assets/tokens.css" />,并用同名 token 编译自己的 Tailwind(token 名 → 变量:page/ink/ink-2/ink-3/line/line-strong/accent…)- 主题跟随宿主推送(
useHarnessTheme),禁止prefers-color-scheme自测 - 与宿主的视觉差异应趋近于零:同 token + 同类名词汇 + 同字号阶
6. renderer 组件附加规则
- 类名直接用宿主词汇(§2),无需引样式;优先 import 公共组件库(L6),不要手写标准模式
- React 必须来自
ctx.react(见 L4),否则 hooks 失效 - 禁止操作宿主 DOM(document 全局查询/改样式),一切交互限制在自己的组件子树
- 机器关卡:
pnpm plugin:check <插件目录>(hex 色值 / React 副本 / 三态缺失等,见 L7)
7. 自检清单(提发布前)
pnpm plugin:check <插件目录>0 error(机器关卡,见 L7)- 无硬编码色值/阴影/圆角(铁律 1)
- 字号都在 §3 的阶上
- 深浅色都检查过(切主题看一眼;token 正确时自动成立)
- 复用了 §4 模式(renderer 直接用组件库)而非新造形态
- iframe 页引了 tokens.css 且无
prefers-color-scheme