关于 tweaks
tweaks 是将 HTML 作品包装为带实时控制面板的设计技能,适用于需要调整和展示视觉变体的人。面板通过 CSS 自定义属性更新作品,并将设置保存到 localStorage。
主要功能
- 01将视觉参数绑定到 CSS 自定义属性
- 02提供颜色、字号、密度等控制项
- 03调整时实时更新页面
- 04将设置保存到 localStorage
- 05支持快捷键切换面板和重置
适用场景
- 01微调已生成的网页作品
- 02现场展示设计系统的不同变体
- 03制作可交互的独立演示页面
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ nexu-io/ open-design --skill tweaks安装后在 Claude Code 中输入/tweaks确认已加载。
附带文件assets/wrap.htmlexample.html
详细介绍
Tweaks Skill · 参数化变体面板
为任意 HTML 成品添加一个侧边面板,其中的实时控件可即时改写
CSS 自定义属性,并将设置保存到 localStorage。
灵感来自 huashu-design 的 tweak 模式。
你将产出什么
一个独立的 HTML 文件,包含两个层:
- 舞台 — 原始成品(落地页 / 演示文稿 / 仪表板),
经过重新调整,使所有视觉决策都读取 CSS 自定义属性:
--accent、--scale、--density、--mode、--motion。 - 面板 — 固定侧边栏(小视口下显示为抽屉),其中的表单控件通过一个小型
原生 JavaScript 桥接与这些自定义属性绑定。每次变更都会按成品标识符
保存到
localStorage。
用户可以:
- 打开成品,查看应用已保存偏好(或合理默认值)后的舞台。
- 在面板中调整强调色 / 字体缩放 / 布局密度 / 模式 / 动效,并即时查看舞台更新,无需重新渲染。
- 按 T 隐藏 / 显示面板;按 R 重置为默认值。
- 刷新页面 — 每项选择都会被保存。
适用场景
- 用户生成的内容有 80% 符合心意,希望亲自微调剩下的 20%。
- 你正在展示设计系统 / 品牌,希望观众能实时感受各种变体(而不是由你重新运行 Agent)。
- 你正在发布独立演示(例如作品集项目),希望观众可以亲自体验。
不适用场景
- 不会迭代修改的一次性成品(例如运行手册 — 参数无济于事)。
- 成品的价值在于固定比例时(例如数据可视化经过精心平衡的信息图 — 控件会破坏效果)。
5 个标准控件
根据成品选择合适的子集。如果只有 2 个控件有用,就不要加入全部 5 个 — 只会徒增杂乱。
1. --accent — 强调色
一个包含 5–8 个精选色样的选择控件(不要加入自由选色器 — 用户可能会选出难看的颜色,然后怪你)。
const ACCENT_PRESETS = [
{ id: 'rust', val: '#c96442', label: 'Rust' },
{ id: 'cobalt', val: '#2c4d8e', label: 'Cobalt' },
{ id: 'sage', val: '#4a7a3f', label: 'Sage' },
{ id: 'plum', val: '#7a3f6a', label: 'Plum' },
{ id: 'graphite',val: '#3a3a3a', label: 'Graphite' },
];
成品中原本写死强调色的所有位置,都改为使用 var(--accent)。
边框 / 链接 / 引言强调线 / CTA 会一起切换。
2. --scale — 字体缩放(0.85 / 1.0 / 1.15)
三个设置:紧凑(0.85)、标准(1.0)、宽松(1.15)。
所有 font-size 声明都通过
calc(... * var(--scale)) 乘以 var(--scale)。
不要超过 ±15% — 再大就会破坏布局(列流、断点、行数)。
3. --density — 布局密度(紧凑 / 标准 / 宽松)
三个设置会切换间距比例:紧凑(0.75)/
标准(1.0)/ 宽松(1.4)。所有 padding / gap / margin
声明都乘以 var(--density)。
这是影响最大的控件 — 也是最脆弱的控件,因此在添加面板之前, 所有布局关键容器都必须在自定义属性中声明基础间距。
4. --mode — 浅色 / 深色
一个双状态切换控件。它会在 <html> 元素上设置
data-mode="light" 或 "dark",成品的 :root 选择器则会应用
两套颜色之一。
如果成品已经有基于媒体查询的深色模式,请将其替换为 data 属性版本 — 应优先采用用户的选择,而不是操作系统设置。
5. --motion — 关闭 / 轻微 / 活跃
三个设置。映射到 CSS 变量 --motion-mult,用于缩放所有
transition-duration / animation-duration 声明:
- 关闭 —
0s(同时禁用 WebGL 画布 / 装饰性动画)。 - 轻微 —
1.0(成品中设定的动效时长)。 - 活跃 —
1.6(过渡更慢,动效更明显)。
遵循 prefers-reduced-motion:如果用户启用了该设置,则默认设为
关闭,无论保存的偏好是什么。
宿主集成约定(必需)
OpenDesign 查看器工具栏中的 Tweaks 切换控件会从 iframe 外部控制面板的 显示状态。要让该控件与面板绑定,成品必须支持以下两种协议之一 (二选一;不要混用)。工具栏一旦检测到任一信号,就会自动启用。
协议 A — postMessage(推荐用于由 Agent 生成的制品)
如果面板通过 JS 挂载(React、原生 JS 或任何动态方式),请使用此协议。
制品 → 宿主:
- 挂载时,向
window.parent发送{ type: '__edit_mode_available', visible?: boolean }。告知工具栏面板已存在;可选的visible用于报告面板的初始状态,让工具栏开关一开始就保持同步。对于常见的“面板已显示在屏幕上”情况,请省略visible(宿主会将缺失字段视为true,从而继续兼容旧的无参数消息)。传入visible: false表示面板默认关闭。 - 用户在本地关闭面板时(点击 × 按钮、按 Esc 等),发送
{ type: '__edit_mode_dismissed' }。工具栏会切换为“关闭”。
宿主 → 制品:
{ type: '__activate_edit_mode' }— 打开面板(setOpen(true))。{ type: '__deactivate_edit_mode' }— 关闭面板(setOpen(false))。
最简监听器:
window.addEventListener('message', (e) => {
const t = e?.data?.type;
if (t === '__activate_edit_mode') setOpen(true);
else if (t === '__deactivate_edit_mode') setOpen(false);
});
// Or, for a default-closed panel:
// window.parent.postMessage({ type: '__edit_mode_available', visible: open }, '*');
window.parent.postMessage({ type: '__edit_mode_available' }, '*');
// in your close handler:
const dismiss = () => {
setOpen(false);
window.parent.postMessage({ type: '__edit_mode_dismissed' }, '*');
};
面板可以默认打开或关闭——宿主会将开关同步到制品报告的状态。
协议 B — 基于类名(用于 assets/wrap.html)
仅当你原样封装模板时使用。制品包含一个 .tw-panel 元素,并通过切换 .tw-hidden 类控制可见性。查看器的 iframe 桥接程序(位于 apps/web/src/runtime/srcdoc.ts)会在初次绘制时隐藏面板,通过 MutationObserver 监听类名,并双向转发状态。除了模板已有的代码外,制品无需编写 JS。
选择器固定为 .tw-panel(面板根元素)和 .tw-hidden(隐藏状态)。如果重命名其中任意一个,桥接程序就无法找到它。
反模式
不要另创第三种协议,也不要重命名这两组标识符。工具栏开关只绑定到 A 或 B。使用自定义类名且不发送 postMessage 的自定义面板会导致工具栏显示为灰色且不可用。
实现基础组件
阅读 assets/wrap.html——其中提供了面板和桥接程序,作为惰性模板。你需要:
- 获取用户现有的制品 HTML。
- 将其中的强调色/模式/间距/缩放提取为自定义属性(搜索硬编码的
#hex/Npx/Nrem并进行转换)。 - 将内容粘贴到
wrap.html中标记的区域。 - 编辑
assets/wrap.html的KNOBS数组,仅保留你认为与此制品相关的旋钮。只需 2 个时,不要放 5 个。 - 将
STORAGE_KEY改为唯一的 slug(tweaks-<artifact-slug>)。
wrap.html 中的桥接程序:
- 在首次绘制时加载
localStorage[STORAGE_KEY]JSON。 - 将值应用为
document.documentElement.style.setProperty('--accent', ...)。 - 监听每个表单控件的
change事件并写回。 - 提供快捷键 T(切换面板)和 R(重置)。
工作流
步骤 1 — 获取制品
选项与 critique 技能相同:
- 项目文件(项目文件夹中的
index.html)。 - 在聊天中粘贴的 HTML。
- 由你在本轮中生成。
步骤 2 — 确定适用的旋钮
先阅读制品的 CSS。针对每个旋钮,判断“是/否”:
--accent— 如果制品有一种使用次数 ≥ 3 的强调色,选“是”。--scale— 如果制品由排版驱动(文章、演示文稿、定价页),选“是”。--density— 如果制品有一致的间距/内边距节奏(演示文稿、仪表盘、落地页),选“是”。操作手册选“否”(这类内容本就密集)。--mode— 如果制品定义了深色模式令牌,或你愿意派生这些令牌,选“是”。--motion— 如果制品有值得调整幅度的过渡/动画,选“是”。静态报告/评审报告选“否”。
默认情况下:3 个旋钮最合适。 5 个太繁杂,1 个不值得做成面板。
步骤 3 — 将硬编码值提取为自定义属性
打开 assets/wrap.html 的 <style> 块——复制其自定义属性
命名方案(--accent、--scale 等)。在用户的作品中,
找到所有涉及这些设置的位置并改写:
color: #c96442→color: var(--accent)font-size: 18px→font-size: calc(18px * var(--scale))padding: 24px 32px→padding: calc(24px * var(--density)) calc(32px * var(--density))transition: opacity 200ms→transition: opacity calc(200ms * var(--motion-mult))
如果作品已使用 clamp() 或 vw,将自定义属性乘到
外层值上——不要拆开 clamp(...)。
步骤 4 — 粘贴到 wrap 中
将作品的 <style> 和 <body> 复制到
wrap.html 中标记的区域。保留面板和桥接代码,不要改动。
步骤 5 — 测试整个流程
打开结果,至少点击每个旋钮一次,刷新页面, 确认所选项仍然保留。如果某个旋钮导致布局错乱—— 移除它,不要发布。
输出约定
<artifact identifier="tweaks-<artifact-slug>" type="text/html" title="<Artifact Title> · Tweaks">
<!doctype html>
<html>...</html>
</artifact>
在作品前写一句话(“已为 X 添加包含 3 个旋钮的调整面板——强调色 / 缩放 / 模式。”)。在 </artifact> 后停止。
硬性规则
- 不要提供自由选色器——只能使用精选色板。给予用户自由选择会让他们选出糟糕的颜色;避免这种情况正是关键所在。
- 按作品标识符保存——使用
tweaks-<slug>,而不是全局键。两个作品分别在两个标签页中打开时,不能共享状态。 - 遵循
prefers-reduced-motion——如果用户启用了该设置,动态效果默认设为关闭,只有在用户明确点击后才覆盖。 - 单文件——除作品现有导入项外,不使用外部 CSS / JS / 字体。将面板和桥接代码内联。
- 视口小于 720px 时默认隐藏面板——通过右上角的 “T” 按钮打开滑入式抽屉。
- 旋钮不要超过 5 个。 3 个最合适。