Communitygithub.com

nkurunziza-saddy/动画

为网页产品UI构建动画。它决定元素是否应该动、为何而动、使用何种工具(CSS过渡、WAAPI、Motion、弹簧)、哪些属性、曲线、时长、中断、退出以及无障碍动效路径,并生成代码。还包括编排与错开、手势(拖拽、轻划、面板)、动效标记和动画性能。

动画 是什么?

该技能为AI代理提供了一套系统化的Web UI动画构建工作流程。它基于一套决策框架(频率门控、目的命名、工具选择等),旨在打造高精度、高性能且对无障碍友好的动画。技能覆盖了从简单状态变化到复杂手势交互的完整场景,避免了在频繁出现的元素上使用无意义动效导致界面卡顿。其内置的“已坏/已修”对照表和最终检查清单,能帮助代理主动规避常见陷阱,适用于需要生成或审查动画代码的开发者,尤其在React生态中与Motion库协同良好。

兼容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/nkurunziza-saddy/hmm-interfaces/tree/HEAD/motion

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

动画 是做什么的?

本技能构建动画。它扩展了 product-ui/references/values.md 中动画部分的内容,该文件包含了已确定的数值(缓动曲线、按下缩放、弹跳、错开、时长表、弹窗和布局时长、移动距离、退出与进入比例)。此处不重复这些数值;本技能增加了决策顺序、标记、方案和故障模式。

在任何决策之前,应用 product-ui §1(品味日志和优先级)和 §5(哪个技能负责什么)。

决策顺序

按从上到下的顺序执行。每一步都可以结束任务。零行动画是一个有效的结果,需要明确说明。

1. 应该动吗?频率门控

询问一个用户每天看到这个元素多少次。等级划分在 values.md 中。实践中:

  • 由键盘触发,或每天看到 100 次以上:无动效。原因:重复动效会变成延迟。
  • 每天看到数十次(悬停、标签切换、行选择):无动效,或瞬间颜色变化。
  • 用户正在阅读或操作的数据(表格中的数字、实时仪表盘中的图表)绝不为样式而移动。原因:动效会将视线从正在阅读的内容上移开。
  • 如果门控判定为否,则编写无动画代码。说明命中了哪个等级,并提供静态替代方案(瞬间状态变化)。

2. 命名目的

选择一个词:空间(它从哪里来或到哪里去)、状态(发生了变化)、反馈(我听到了)、连续性(防止跳跃)、解释(仅限罕见场景)。无法命名:停止。原因:频繁元素上“看起来不错”是导致界面感觉缓慢的主要原因。

3. 选择工具:最廉价且有效的方法

需求工具
通过类、属性、悬停或按压切换的状态CSS 过渡
从 display: none、弹出框或对话框进入@starting-style + transition-behavior: allow-discrete
一次性序列、错开,或必须在页面繁忙时运行的动效CSS @keyframes
JS 决定何时开始;需要取消、反转、finished 或 FLIPWAAPI el.animate()
弹簧、速度传递、卸载 React 节点的退出、共享布局Motion (motion/react)

如果是一个完整的组件(菜单、弹窗、抽屉),使用自带焦点处理功能的库,并询问 pick-library。切勿为了一个淡入效果而安装 Motion。原因:CSS 在主线程外运行,且不增加包体积。

4. 属性

  • 对 transform 和 opacity 进行动画;仅当模糊值 ≤ 2px 时使用 filter。命名每个属性;绝不用 transition: all。
  • 高度和布局变化:参见 references/recipes.md(网格行、FLIP)。绝不用 width、top、left 或 margin 来移动元素。原因:每个都会在每一帧强制重排布局。
  • 绝不对 box-shadow 进行动画。改为淡入伪元素的 opacity。
  • translate 百分比相对于元素自身尺寸,因此 translateY(100%) 适用于任何高度的抽屉和弹窗。

5. 曲线和时长,与用途匹配

永远不要选择最接近你猜测的数值。说明用途(“菜单关闭”、“图标切换”),然后从 references/tokens.md 中取对应的行。如果没有与用途匹配的行,则以该用途命名添加一个新的标记;不要扭曲现有标记。原因:标记是对动效用途的声明,因此一个近似值但用途错误就是错误的标记。

  • 进入或退出:--ease-out。在屏幕上移动:--ease-in-out。抽屉:--ease-drawer。颜色:ease。加载图标:linear。绝不用 ease-in。
  • 任何可拖拽或可在中途中断的元素使用弹簧,而不是曲线。原因:曲线无法接受用户手部带来的速度。
  • 感觉慢:先缩短时长,再缩短距离,最后才调整曲线。

6. 中断

  • 任何用户在一秒内能触发两次的元素使用过渡或弹簧,绝不用 @keyframes。原因:过渡从当前值重新定向;关键帧会重启并跳跃。
  • WAAPI:在读取当前值后取消旧的动画,并基于该值开始新的动画(references/recipes.md)。
  • 一个开关被连续快速触发 10 次必须最终处于正确状态且没有跳跃。测试它。

7. 退出

  • 默认退出是淡出,比进入更短(标记文件中有每对设置)。
  • 任何有方向的元素(抽屉、面板、被滑动的弹窗)按其来路退出。
  • 退出的元素立即停止占据空间,因此兄弟元素在其淡出时填补空隙。
  • 退出是同时进行且绝不交错。原因:用户已经决定离开。

8. 减少动效,与动画一起提供

不透明度和颜色保持。滑动、缩放、模糊和弹跳消失;滑动变为淡出,弹跳变为 0。绝不用动效作为唯一提示。模式见 references/recipes.md。

编排

在设定时间之前,为每个移动元素分配角色:

角色处理方式
主角(最值得注意的元素)先动,移动距离最大
配角跟随,移动距离较小
装饰原地淡入,或不动
静态(容器、框架)从不移动
  • 每个容器一次进入。如果面板滑入,其内容已经就位。原因:两次分层进入会让用户等待两次。
  • 按重要性顺序排列,而非 DOM 顺序。延迟保持在 values.md 的步骤(项目之间 40ms,标题、文本和操作之间 100ms)。通过角色而不是延迟来变化距离和时长。
  • 列表错开限制在索引 6(最长 240ms 延迟);之后的项目共享该延迟。播放期间输入仍可工作。
  • 绝不对菜单、命令面板、标签内容或任何重复打开的内容进行错开。
  • 保持静止:用户即将点击的任何内容、页面再次加载时已显示在屏幕上的任何内容,以及在最后一次更新后 150ms 内到达的更新(跳转到结束状态)。
  • 方向遵循含义:下一个从右侧进入,上一个从左侧进入;用户触发的内容从其触发器向外生长。

需要时加载

  • references/tokens.md:当需要精确的时长、距离、缩放、模糊、缓动或弹簧值,以及需要对现有代码库进行标记化时加载。
  • references/recipes.md:构建菜单、弹出框、对话框、抽屉、弹窗、列表进入、图标切换、高度变化、标签指示器或数字变化时加载。
  • references/gestures.md:处理拖拽、滑动、轻划、面板,或任何跟随指针的操作时加载。
  • references/performance.md:当动效掉帧时,在尝试使用 will-change 之前,以及当更新快速到达时加载。

对照表

已坏已修原因
.menu { transition: all 300ms ease-in }transition: opacity 200ms, transform 200ms var(--ease-out)命名属性;ease-in 感觉迟缓;菜单 ≤ 200ms
scale(0) 到 scale(1)scale(0.95) 和 opacity: 0 到 1没有元素从无到有
弹出框从其中心缩放transform-origin: var(--transform-origin)它应该从其触发器处向外生长
.open { animation: slide-in 300ms }transition: transform 作用于切换状态关键帧在中断时闪烁
每行 animation-delay: i * 120msmin(i, 6) * 40ms最后一行在 300ms 内到达
抽屉滑入后淡出它按来路滑回退出方向就是解释
拖拽释放使用固定的 ease-out使用带有释放速度的弹簧手部动量继续
在 pointermove 中使用 setY(y)el.style.transform = ...避免每帧重新渲染

结束前

搜索差异,然后验证。

搜索内容修复
transition: all、* 上的 will-change、ease-in命名属性、移除、--ease-out
弹出框上的 scale(0)、transform-origin: center0.95、触发起源点(对话框保持居中)
在切换的类上使用 @keyframes使用过渡
时长超过 tokens.md 中对应行,或数字不在 tokens.md 中使用该用途的标记
keydown 处理程序或面板上的动效移除它
过渡中的 width、height、top、left、box-shadow使用 transform、opacity 或方案
没有 prefers-reduced-motion 路径添加它

在运行的应用中验证:以 4 倍速播放(DevTools 动画面板,或乘以时长),连续快速触发任何开关,在开启减少动效的情况下测试,并将 CPU 降速 4 倍。说明哪些测试你无法运行。

Individual skills in this repo

This repo contains 4 individual skills — each has its own dedicated page.

nkurunziza-saddy/break

Stress-tests a piece of UI with worst-case data and every reachable state, then reports what broke with a numbered fix for each. Use it when the user types /break, or asks to "break this", "stress-test", "try the worst case", "what happens with long names", "check the empty and error states" or "find the edge cases" on a component or screen.

nkurunziza-saddy/layout

Structure and space in product UI on the web. It sets the spacing scale, grouping, alignment, density (compact or comfortable), hit areas, app shells (sidebar, toolbar, content, inspector), max widths, container-query responsiveness, dropdown and popover sizing, room for long and translated text, layout stability (no shift on load) and sticky elements that must not cover focus.

nkurunziza-saddy/pick-library

Picks the right library for a frontend task from a curated, status-checked list, instead of hand-rolling it or installing an abandoned package. Use it when the user asks "what should I use for…", "is there a library for…", or names a package, and when you are about to build a toast, command menu, drawer, date picker, table, virtual list, drag and drop, chart, OTP input, animated number, theme switch, form validation…

nkurunziza-saddy/surfaces

What product UI is made of on the web. It sets elevation levels with exact shadow recipes for light and dark mode, when to use a shadow and when a border, the transparent border for forced-colours mode, a small radius scale with concentric nesting, image outlines, every interactive state as a surface change (hover, pressed, selected, disabled, focus-visible), icons (one set, currentColor, outline and fill, stroke tha…

相关技能