micro-interaction
This skill should be used when the user asks to "add a hover/press effect", "animate a toggle or switch", "build an animated like button", "make a toast/snackbar slide in", "animate a drawer or modal", "animate list reordering or add/remove", "do a shared-element layout transition", or "polish UI feedback". Covers UI motion with Framer Motion (motion/react) and modern CSS.
1How It Works & Mechanism
Establish strict time windows and compositor constraints for micro-interactions (100–250ms, animate only transform/opacity, instantaneous 0.96 scale on press, asymmetric enter/exit), translating tactile feel into verifiable parameters.
Duration: UI micro-interactions live in **100–250ms**. Anything over ~400ms feels laggy for a click response.
Anchor the Framer Motion side on the core triad of gestures, springs, and AnimatePresence, tuning springs via two intuitive parameters: stiffness and damping.
whileTap={{ scale: 0.96 }}
Leverage layout animation as Framer Motion's killer feature: layout automatically converts position and size changes into transforms, while layoutId orchestrates shared-element (magic move) transitions between components.
{!open && <motion.div layoutId="card" onClick={() => setOpen(true)} />}
Implement enter and exit animations (including display toggling) using pure CSS: @starting-style supplies initial values for first render, and transition-behavior: allow-discrete enables transitions on discrete properties.
transition-behavior: allow-discrete;
Treat the progression from loading to success to failure as continuous states of the same entity (e.g., button morphing from spinner to checkmark) rather than sudden cutscenes, and enforce reduced-motion guards.
Loading → success → error should be one continuous motion (e.g. a button morphs spinner → checkmark), not a jump cut.
2Core Capabilities
3External Dependencies
| Kind | Dependency / Endpoint |
|---|---|
| package | motion(Framer Motion,v11+ 以 motion/react 导入) |
| network | 交付页从 CDN 取 React 与 motion(正文点名 esm.sh;产物期引用,不判级) |
| api | 现代 CSS 原语:@starting-style、transition-behavior: allow-discrete、@property、popover/dialog 的 overlay 离散属性 |
| cli | npx / Playwright(宿主侧截图工具)与仓库根 scripts/ 助手(seek-shot.sh、contact-sheet.sh 依赖 ffmpeg) |
4Recommended Governance & Evidence
- 网络端点: External network access declaration: Zero outbound network calls at execution time; delivery pages fetch React and motion from CDN (text explicitly references esm.sh; artifact-phase reference, not graded)
- 本地工作目录: File I/O and artifact outputs: Zero disk writes within the skill directory; artifact is 1 self-contained .html file (pure CSS or inline type=module via CDN) generated by the agent
5Second-Pass Verification
- [unlocatable] transition-behavior: allow-discrete 与 @starting-style 的支持面 — SKILL.md 写 Baseline in Chrome/Edge/Safari、references 写 Baseline-available in current Chrome/Edge/Safari/Firefox——两处描述不同(SKILL.md 未含 Firefox),且均无源码内依据。正文要求读者 verify @starting-style and allow-discrete for your support floor,即文档自己把核实责任交给使用者,故按文档声明记录并在 risks 提示。
- [ok] layout 造成圆角与文字变形的告诫是否与配方一致 — SKILL.md 的 Gotcha 段与 references 的 magic-move/layout 小节都提示需子元素反向缩放或改用 layout="position";references 另给 useMotionValue 加 useSpring 的免重渲染建议,互不矛盾。
- [ok] 验收方式与动效性质是否匹配(状态驱动 vs 时间驱动) — SKILL.md 明写 A micro-interaction's frames are its states (idle / hover / pressed / open) 并给 ?state= 方案,同时保留 CSS 循环动画的 animationDelay 加 paused 冻结写法,两路都对得上其讨论的动效类型。
- [discrepancy] Packaged helper 的路径基准与语义 — SKILL.md 写 scripts/seek-shot.sh anim.html 0 1.5 3(秒制、时间冻结),但本 skill 的验收是状态冻结(?state=open),helper 与之不匹配;且 scripts/ 在仓库根,单装形态下相对路径亦不成立。
6Verdict & Scenarios
17fbed1b9f12f5ad…