让 Codex 做出一版像样的 UI 并不难,麻烦的是每次换一个新任务,很多设计要求又得重新写一遍。
动画时长、按钮反馈、浮层展开、键盘交互,这些规则并不会因为页面换了就消失。反复把它们写进 Prompt,不仅麻烦,也很难保证每次都覆盖完整。
本期「Skill 安利实践」就测试一个具体问题:能不能把这套重复使用的 UI 规则交给 Skill,让 Agent 在不同任务里直接复用?
这次使用的是 Emil Kowalski 开源的 emil-design-eng。
emil-design-eng 封装了一套设计工程规则
emil-design-eng 来自 emilkowalski/skills,是仓库中的主 Skill。它主要覆盖动画,同时包含 UI 打磨、组件设计和交互细节等设计工程经验,帮助 Agent 在做 UI 时复用这套判断规则。
例如,按钮按下时缩放到 scale(0.97) 提供即时反馈;浮层进入时避免使用迟缓的 ease-in,优先采用 ease-out 缓出曲线;下拉浮层从触发控件对应的位置展开,模态框则保持中心变换原点。
常规 UI 动画通常控制在 300ms 内,高频键盘操作则优先即时反馈。这些都是实际做 UI 时经常重复使用的规则。
官方 README 提供的整个仓库安装命令是 npx skills@latest add emilkowalski/skills。这次只测试 emil-design-eng,所以我们采用了定向安装:
npx skills add https://github.com/emilkowalski/skills --skill "emil-design-eng"
安装后,emil-design-eng 位于当前项目的 .agents/skills/emil-design-eng/ 目录。重新打开项目,Codex 已能够正常识别和调用 $emil-design-eng。为了减少其他 Skill 干扰,测试前我们关闭了已有的 81 个 Skill,实验过程中也没有额外指定其他 Plugin、App 或 MCP。
图 1:emil-design-eng 项目级安装并成功识别
Codex 默认版已经具备完整交互
我们先关闭其他 Skill,让 Codex 单独完成一个 AI Prompt Playground,作为后面的对照版本。页面包含模型选择、Prompt 输入、生成、结果切换、复制、工具提示、通知、设置、加载状态和浅色 / 深色模式。
第一轮不调用 emil-design-eng,只让 Codex 根据默认判断实现,Prompt 内容如下:
请在当前项目的 00-default 目录中,创建一个可以直接在本地运行的 AI Prompt Playground 单页前端。
页面需要包含 Model Selector、Prompt 输入框、Generate、Output / JSON Tabs、Copy、Tooltip、Toast、Settings Modal、Loading,以及 Light / Dark Mode。
所有功能只使用本地 Mock Data,不调用真实 API;页面必须可以实际交互。根据你自己的默认设计判断完成 UI 和交互,不调用任何第三方自定义 Skill,也不参考额外设计规范。
图 2:00-default 完整页面
Codex 默认版已经具备完整的双栏工作台,下拉菜单、模态框、通知、标签页、加载状态和主题切换都能正常使用,页面还加入了主视觉区、网格背景、渐变光晕和两张独立卡片。
这个默认版本已经具备不错的完成度,后面的实验主要观察 emil-design-eng 会继续调整哪些交互细节。
Skill 审查补上了交互细节
我们把 00-default 原样复制为 01-emil,再调用 $emil-design-eng 做一次只读审查。这一轮没有提供按钮缩放比例、缓动曲线或标签页动画等具体规则,让 Skill 自己检查现有实现。
| 默认实现 | Skill 修改建议 |
| 过渡没有明确指定属性 | 只对需要变化的属性做动画,并统一缓动曲线 |
| 按钮按压反馈不一致 | 可按压控件增加 scale(0.97–0.98) 反馈 |
| 模态框关闭直接隐藏 | 增加可中断退场,结束后再隐藏 |
| 空状态 / 加载状态 / 结果状态硬切 | 使用短暂交叉淡化与轻微模糊衔接 |
| 鼠标与键盘切换标签页共用动画 | 鼠标保留短过渡,键盘立即反馈 |
审查建议没有全部执行。比如 Skill 建议工具提示第一次悬停时加入延迟,连续查看相邻提示时则直接显示,但当前页面只有一个主要工具提示,没有必要额外实现整套连续浏览逻辑。
焦点约束、设置项与实际行为的一致性等建议也更偏通用前端工程检查。本轮最终只保留与当前页面直接相关的 5 项,再让 Codex 修改:
基于刚才的 emil-design-eng Review,请进入第一轮优化。
本轮只修改 01-emil,不得修改 00-default。
只处理 5 项:明确 Transition 属性与 Easing、统一 Press Feedback、改善 Settings Modal 退场、改善 Empty → Loading → Result 状态切换,以及让 Output / JSON Tabs 对鼠标和键盘采用不同的动画策略。
不新增产品功能,不重新设计页面,也不要为了执行 Skill 而增加当前页面并不存在的使用场景。
第一轮优化集中在动效时序
第一轮优化只修改了 styles.css 和 app.js,页面结构、HTML 和 README 均保持不变。静态截图差异不大,主要变化集中在按压反馈、状态切换和动画时序。
默认版已经有悬停反馈,但按下时的反馈并不统一。修改后,主要可按压控件统一加入 scale(0.97–0.98) 的短促反馈,禁用态不再执行缩放。
模态框原本只有入场动画,关闭时直接隐藏。修改后改用可中断的 CSS 过渡,约 140ms 退场完成后再隐藏,快速反向操作也能正确响应。
生成状态也根据输入方式采用不同策略。鼠标点击时,空状态 → 加载状态 → 结果状态会通过约 160ms 的透明度和轻微模糊做交叉淡化;使用 Ctrl/Cmd + Enter 时则直接切换。
标签页同样区分输入方式:鼠标点击保留 120ms 短过渡,键盘方向键切换则立即反馈。
图 3:01-emil Button / Modal / Tabs 交互
人工测试发现了状态回归
Codex 完成第一轮修改后,报告主要交互均已检查正常。但实际打开页面测试时,我们发现结果内容已经出现,原来的空状态仍然叠在结果区域中。
进一步排查后发现,状态机已经执行了 emptyState.hidden = true,但原有样式 .empty-state { display: flex; } 覆盖了 hidden 的默认隐藏效果,导致旧状态没有退出页面。
最终补充下面这条样式,确保带有 hidden 属性的旧状态彻底隐藏:
.result-area > [hidden] {
display: none;
}
修复后重新测试,空状态 → 加载状态 → 结果状态可以正常切换,旧状态不会继续残留。随后,Codex 又针对前面确定的 5 项优化做了一次定点验证,过渡动画、按压反馈、设置模态框、生成状态切换和标签页交互均为 PASS。
这次回归也提醒我们,Agent 完成代码修改后的自动检查仍需要结合实际页面操作验证。
Skill 从零生成了另一套界面
第一轮优化主要集中在 120~200ms 的交互时序,静态截图中的差异并不明显。为了进一步观察 emil-design-eng 对完整 UI 设计的影响,我们增加了一轮从零生成测试。功能需求保持一致,同时要求它不参考 00-default 和 01-emil,直接重新创建一套 Prompt Playground。
默认版使用了更明显的主视觉区、网格背景、渐变光晕和独立卡片;Skill 从零生成版减少了这些装饰元素,把 Prompt 与输出集中到统一的双栏工作台中,整体视觉更加克制。
图 4:02-emil-from-scratch
两次从零生成存在模型随机性,因此这一轮不作为严格的基准测试,只用于观察 emil-design-eng 在独立生成时会主动采用哪些设计规则。
从交互实现看,这一版只在承担反馈、状态变化或空间关系的组件上加入动效,普通文本输入和键盘焦点移动没有额外动画。主要可按压控件使用 scale(0.97) 提供即时反馈,多数日常 UI 动画控制在 300ms 内。
不同组件也采用了不同的空间逻辑。下拉菜单从触发控件对应的位置展开,模态框保持中心变换原点;浮层入场不会直接从 scale(0) 开始。生成、加载和结果状态则通过轻微位移、透明度和模糊效果衔接,减少内容切换时的跳变。
输入方式也分别处理。悬停效果只在支持精确指针的设备上启用,同时保留键盘交互,并支持系统的“减少动态效果”偏好(prefers-reduced-motion)。
从这版实现可以看到,emil-design-eng 主要影响 UI 的交互方式、动效节奏和组件反馈,并没有限定一套固定的视觉风格。
这套 Skill 省下了重复解释规则的成本
Codex 默认版已经能完成一套质量不错的 UI,emil-design-eng 补充的是动画节奏、按压反馈、浮层展开和键盘交互等设计规则,省掉了每次重新写一遍这些要求的麻烦。
这些规则仍需要结合具体页面筛选,Agent 修改后的代码也要实际验收。Skill 可以复用专业经验,但不能替代最后的工程判断。
附录:emilkowalski/skills 里还有哪些 Skill?
除了本文实测的 emil-design-eng,仓库里还提供了一组围绕 UI、动效和设计工程的 Skill:
animate:从零设计一段动画,帮助选择合适的缓动曲线、时长和动画属性。review-animations:按照 Emil 的动效规则审查已有动画实现。improve-animations:扫描代码中的动画问题,并整理成可执行的优化方案。find-animation-opportunities:寻找真正值得加入动效的位置,同时指出哪些地方不应该加动画。animation-vocabulary:补充动画相关术语,方便更准确地告诉 Agent 想要什么效果。apple-design:将 Apple 在 WWDC 中介绍的界面设计与流畅动效原则整理成适用于 Web 的规则。pick-ui-library:根据任务选择合适的 UI 库,减少 Agent 自己重复造组件。prototype:针对一个 UI 需求生成多个不同方案,并通过切换器快速比较。ask-sonner:围绕 Emil 的 Toast 库 Sonner,提供安装、样式、使用方案和常见问题处理。
如果这一期读完之后还想继续折腾,review-animations**、**improve-animations 和 find-animation-opportunities 与本文的实践衔接最直接。它们分别对应“审查现有动效”“系统优化动效”和“寻找值得加入动效的位置”。