Skills Plugins MCP Prompt Model 博客 我的中心

motion-ui

Production-ready UI motion system for React/Next.js. Use when implementing animations, transitions, or motion patterns.

DeepseekModel 官方收录技能 质量 优秀 · 90 v1.0.0

获取

https://deepseekmodel.com/api/download.php?id=affaan-m-ecc-skills-motion-ui-skill-md&format=skill
下载 .skill 标准格式,含 system_prompt 与 model_config,导入任意 Agent 框架即可使用
.skill 文件中 system_prompt 字段的实际内容。
name motion-ui description Production-ready UI motion system for React/Next.js. Use when implementing animations, transitions, or motion patterns. metadata {"origin":"ECC"} Motion System v4.2 Production-ready UI motion system for React / Next.js. Focused on performance, accessibility, and usability — not decoration. When to Use Use this motion system when motion: Guides attention (e.g., onboarding, key actions) Communicates state (loading, success, error, transitions) Preserves spatial continuity (layout changes, navigation) Appropriate Scenarios Interactive components (buttons, modals, menus) State transitions (loading → loaded, open → closed) Navigation and layout continuity (shared elements, crossfade) Considerations Accessibility : Always support reduced motion Device adaptation : Adjust for low-end devices Performance trade-offs : Prefer responsiveness over visual smoothness Avoid Using Motion When It is purely decorative It reduces usability or clarity It impacts performance negatively How It Works Core Principle Motion must: Guide attention Communicate state Preserve spatial continuity If it does none → remove it. Installation npm install motion Version motion/react - default for current Motion for React projects (package: motion ) framer-motion - legacy import path for projects that still depend on Framer Motion Do not mix. Mixing causes conflicting internal schedulers and broken AnimatePresence contexts — components from one package will not coordinate exit animations with components from the other. To check which version your project uses: cat package.json | grep -E '"motion"|"framer-motion"' Always import from one source consistently: // Correct (modern) import { motion, AnimatePresence } from "motion/react" // Correct (legacy) import { motion, AnimatePresence } from "framer-motion" // Never mix both in the same project Motion Tokens // motionTokens.ts export const motionTokens = { duration : { fast : 0.18 , normal : 0.35 , slow : 0.6 }, // Use these as the `ease` value inside a `transition` object: // transition={{ duration: motionTokens.duration.normal, ease: motionTokens.easing.smooth }} easing : { smooth : [ 0.22 , 1 , 0.36 , 1 ] as [ number , number , number , number ], sharp : [ 0.4 , 0 , 0.2 , 1 ] as [ number , number , number , number ] }, distance : { sm : 8 , md : 16 , lg : 24 } } Usage example: import { motionTokens } from "@/lib/motionTokens" <motion. div initial={{ opacity : 0 , y : motionTokens. distance . md }} animate={{ opacity : 1 , y : 0 }} transition={{ duration : motionTokens. duration . normal , ease : motionTokens. easing . smooth }} /> Performance Rules Safe transform opacity Avoid width / height top / left Rule: responsiveness > smoothness Device Adaptation The heuristic combines CPU core count and available memory for a more reliable signal. deviceMemory is available on Chrome/Android; the fallback covers Safari and Firefox. const isLowEnd = typeof navigator !== "undefined" && ( // Low memory (Chrome/Android only; undefined elsewhere → treat as capable) (navigator. deviceMemory !== undefined && navigator. deviceMemory <= 2 ) || // Few cores AND no memory API (covers Safari/Firefox on weak hardware) (navigator. deviceMemory === undefined && navigator. hardwareConcurrency <= 4 ) ) const duration = isLowEnd ? 0.2 : 0.4 Accessibility JS (useReducedMotion) import { motion, useReducedMotion } from "motion/react" export function FadeIn ( ) { const reduce = useReducedMotion () return ( < motion.div initial = {{ opacity: 0 , y: reduce ? 0 : 24 }} animate = {{ opacity: 1 , y: 0 }} /> ) } CSS @media ( prefers-reduced-motion : reduce) { .motion-safe-transition { transition : opacity 0.2s ; } .motion-reduce-transform { transform : none !important ; } } Tailwind < div class = "motion-safe:animate-fade motion-reduce:opacity-100" > </ div > Architecture & Patterns Core Patterns Scenario Pattern Hover feedback whileHover Tap / press feedback whileTap Reveal on scroll whileInView Scroll-linked value useScroll + useTransform Conditional mount/unmount AnimatePresence Small layout shifts (single element, < ~300px change) layout prop Large layout shifts or full-page reflows Avoid layout ; use CSS transitions or page-level routing instead Complex, imperative sequences useAnimate Why avoid layout on large containers? Framer's layout animation uses transform to reconcile positions, but on elements that span the full viewport or trigger deep reflow, the measurement cost causes visible jank and CLS. Prefer CSS Grid/Flexbox transitions or coordinate with layoutId on specific child elements only. Layout & Transitions Shared element transitions → layoutId (must be unique per mounted instance) Enter / exit transitions → AnimatePresence (see mode guidance below) AnimatePresence mode Always specify mode explicitly — the default ( "sync" ) runs enter and exit simultaneously, which causes visual overlap in most UI patterns. mode When to use "wait" Exit completes before enter starts. Use for modals, toasts, page transitions . "sync" (default) Enter and exit overlap. Use only when overlap is intentional (e.g., crossfade carousels). "popLayout" Exiting element is popped out of flow immediately; remaining items animate to fill. Use for lists, tabs, dismissible cards . // Modal — always use "wait" < AnimatePresence mode= "wait" > {open && < Modal key = "modal" /> } </ AnimatePresence > // Dismissible list item — use "popLayout" < AnimatePresence mode = "popLayout" > {items.map(item => < Card key = {item.id} /> )} </ AnimatePresence > Advanced Patterns (Concepts) Parallax (scroll-linked transforms) Scroll storytelling (sticky sections) 3D tilt (pointer-based transforms) Crossfade (shared layoutId ) Progressive reveal (clip-path) Skeleton loading (looped opacity) Micro-interactions (hover/tap feedback) Spring system (physics-based motion) Modal Essentials Focus trap Escape close Scroll lock ARIA roles Use AnimatePresence mode="wait" so exit animation completes before the next modal enters Full Example import React , { useEffect, useRef, useState } from "react" import { motion, AnimatePresence } from "motion/react" function useFocusTrap ( ref : React . RefObject < HTMLDivElement | null >, active : boolean ) { useEffect ( () => { if (!active || !ref. current ) return const el = ref. current const focusable = el. querySelectorAll < HTMLElement >( 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])' ) const first = focusable[ 0 ] const last = focusable[focusable. length - 1 ] function handleKey ( e : KeyboardEvent ) { if (e. key !== "Tab" ) return if (e. shiftKey && document . activeElement === first) { e. preventDefault () last?. focus () } else if (!e. shiftKey && document . activeElement === last) { e. preventDefault () first?. focus () } } el. addEventListener ( "keydown" , handleKey) first?. focus () return () => el. removeEventListener ( "keydown" , handleKey) }, [active, ref]) } function useScrollLock ( active : boolean ) { useEffect ( () => { if (!active) return const prev = document . body . style . overflow document . body . style . overflow = "hidden" return () => { document . body . style . overflow = prev } }, [active]) } function Modal ( { open, closeModal }: { open: boolean ; closeModal: () => void } ) { const ref = useRef< HTMLDivElement >( null ) useFocusTrap (ref, open) useScrollLock (open) useEffect ( () => { function onKey ( e : KeyboardEvent ) { if (e. key === "Escape" ) closeModal () } if (open) window . addEventListener ( "keydown" , onKey) return () => window . removeEventListener ( "keydown" , onKey) }, [open, closeModal]) return ( // mode="wait" ensures exit animation finishes before any new modal enters < AnimatePresence mode = "wait" > {open && ( < motion.div role = "dialog" aria-modal = "true" aria-labelledby = "modal-title" initial = {{ opacity: 0 }} animate = {{ opacity: 1 }} exit = {{ opacity: 0 }} transition = {{ duration: 0.2 }} className = "fixed inset-0 flex items-center justify-center bg-black/40" > < motion.div ref = {ref} initial = {{ scale: 0.95 , opacity: 0 }} animate = {{ scale: 1 , opacity: 1 }} exit = {{ scale: 0.95 , opacity: 0 }} transition = {{ duration: 0.2 , ease: [ 0.22 , 1 , 0.36 , 1 ] }} className = "bg-white p-6 rounded" > < h2 id = "modal-title" > Dialog Title </ h2 > < button onClick = {closeModal} > Close </ button > </ motion.div > </ motion.div > )} </ AnimatePresence > ) } export function Example ( ) { const [open, setOpen] = useState ( false ) return ( <> < button onClick = {() => setOpen(true)}>Open </ button > < Modal open = {open} closeModal = {() => setOpen(false)} /> </> ) } SSR Safety Match initial states between server and client renders Avoid implicit animation origins (always set initial explicitly) Wrap motion components in "use client" in Next.js App Router Debugging Check: Wrong import (mixing motion/react and framer-motion ) Missing "use client" directive in Next.js App Router Missing key prop on AnimatePresence children Hydration mismatch (initial state differs between SSR and client) layout prop misuse on large containers causing reflow jank State-driven animation not triggering (check dependency arrays) QA No CLS Keyboard works Focus trapped in modals ARIA roles correct ( role="dialog" , aria-modal="true" ) Reduced motion respected ( useReducedMotion + CSS media query) No hydration warnings in Next.js Animations stop cleanly on unmount (no memory leaks) AnimatePresence mode set explicitly on all usage sites Anti-Patterns Animating layout properties ( width , height , top , left ) Infinite animations without purpose (always ask: what state does this communicate?) Over-staggering lists (keep staggerChildren ≤ 0.1s; beyond that it feels slow) Ignoring reduced motion preferences Using layout on large or full-viewport containers Omitting mode on AnimatePresence (default "sync" causes visual overlap) Using motion purely for decoration Philosophy Motion is interaction design. Final Rule If motion does not improve UX → remove it. Examples Button Interaction import { motion } from "motion/react" export function Button ( ) { return ( < motion.button whileHover = {{ scale: 1.02 }} whileTap = {{ scale: 0.97 }} transition = {{ duration: 0.15 , ease: [ 0.4 , 0 , 0.2 , 1 ] }} > Click me </ motion.button > ) } Reduced Motion Example import { motion, useReducedMotion } from "motion/react" export function FadeIn ( ) { const reduce = useReducedMotion () return ( < motion.div
Agent 识别该技能的关键词,点击任意一个即可复制。

该技能未提供触发词。

下载的 .skill 包内含以下字段。
字段 说明
format格式标识(skill/v1)
skill_id技能唯一 ID
name技能名称
version版本号
description技能描述
category所属分类(数组)
trigger_words触发词列表
tags标签列表
source来源标识
source_url来源链接(本页地址)
exported_at导出时间(每次下载生成)
system_prompt系统提示词正文
model_config模型参数:provider / model / temperature / max_tokens / top_p
examples示例
install_guide各平台导入说明(Coze / Dify / Claude / 自定义框架)
同一份技能可按不同平台格式导出。
.skill 标准格式,含 system_prompt 与 model_config,导入任意 Agent 框架即可使用 下载
.skillpro 增强格式,额外含脚本 / 工具 / 依赖 / 钩子占位 下载
.json 纯 JSON 导出,只含 system_prompt 与模型参数 下载
Coze 带 frontmatter 的 Markdown,Coze 平台导入用 下载
Dify Dify DSL,创建应用后直接导入 下载

每日精选 Skill 推荐,免费送到你邮箱

输入邮箱,每天接收一个精选 AI Agent 技能推荐。完全免费,持续更新。

提交后我们会发送一封确认邮件,点击邮件里的链接才会开始收信。

完全免费,取消任意时间。我们不会发送垃圾邮件。