[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6H8E1F0TVJSF79F46CF1V7E":3,"skill-same:01M6H8E1F0TVJSF79F46CF1V7E":72},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":23,"publishedAt":30,"linkOnly":31,"markdownContent":32,"markdownBody":33,"frontMatter":34,"refName":35,"commitSha":36,"skillDirectory":37,"forksCount":38,"repositoryHtmlUrl":39,"repositoryHomepageUrl":6,"ownerHtmlUrl":40,"ownerBlogUrl":41,"ownerDescription":42,"updatedAt":43,"install":44,"resources":57},"01M6H8E1F0TVJSF79F46CF1V7E","ux-patterns",null,"参数化UX交互模式库，根据emotionalTone和motionIntensity参数动态生成文案和动效。当用户提到\"动效\"\"状态反馈\"\"文案\"\"交互\"\"微交互\"\"用户体验\"时使用。","rotifer-protocol\u002Frotifer-playground","rotifer-protocol","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F262854335?v=4","01M6H88XQBWNQXVGHBCGZZCQVX","Rotifer Protocol","01M6H88XVXE7GHR06H8E1SP311",6,"Apache-2.0","https:\u002F\u002Fgithub.com\u002Frotifer-protocol\u002Frotifer-playground\u002Fblob\u002Fmain\u002Fgenes\u002Fux-patterns\u002FSKILL.md",[18],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000032","设计师","PROFESSION","适用职业",[24,25,26,27,28,29],"ux","patterns","ux patterns","生成","交互","文案","2026-11-10 10:12:30",false,"---\nname: ux-patterns\ndescription: 参数化UX交互模式库，根据emotionalTone和motionIntensity参数动态生成文案和动效。当用户提到\"动效\"\"状态反馈\"\"文案\"\"交互\"\"微交互\"\"用户体验\"时使用。\n---\n\n# UX Patterns (参数化交互模式库)\n\n**定位**: 确保交互体验有温度、有个性。\n\n**核心目标**: 根据风格参数生成匹配的文案和动效，而非从预设中选择。\n\n**依赖**: 接收 [brand-personality](..\u002Fbrand-personality\u002FSKILL.md) 输出的 `emotionalTone` 和 `motionIntensity` 参数。\n\n---\n\n## Pre-Polish Checklist\n\n应用 UX 模式前，逐项检查：\n\n```\n功能完整性：\n- [ ] Loading: 有 Spinner\u002FSkeleton\u002F趣味加载?\n- [ ] Success: 有 Toast\u002F确认\u002F庆祝动效?\n- [ ] Error: 有温暖的错误提示?\n- [ ] Empty: 有有趣的空状态?\n- [ ] Animations: 状态切换有过渡?\n- [ ] Hover: 可交互元素有悬停状态?\n- [ ] Focus: 焦点状态清晰可见?\n\n情感化检查（消除AI味）：\n- [ ] 文案是否像真人说的话？\n- [ ] 有没有至少一个惊喜时刻？\n- [ ] 动效是否有个性（不只是 ease-out）？\n- [ ] 空状态\u002F错误状态是否让人感到被关心？\n```\n\n---\n\n## 状态反馈模式\n\n### 加载状态\n\n| 场景 | 反馈方式 | 示例 |\n|------|----------|------|\n| 按钮提交 | 按钮内 Spinner + 文字 | \"保存中...\" |\n| 页面加载 | 骨架屏 (Skeleton) | 灰色占位块 |\n| 数据刷新 | 顶部进度条 \u002F Spinner | NProgress 风格 |\n| 后台操作 | Toast 提示 | \"正在处理...\" |\n\n### 成功状态\n\n| 场景 | 反馈方式 | 持续时间 |\n|------|----------|---------|\n| 表单提交 | Toast 成功提示 | 3秒自动消失 |\n| 重要操作 | 弹窗确认 + 对勾动画 | 用户点击关闭 |\n| 保存操作 | 轻量提示（顶部闪现） | 2秒自动消失 |\n\n### 错误状态\n\n| 场景 | 反馈方式 | 要求 |\n|------|----------|------|\n| 表单验证 | 输入框下方红色提示 | 即时反馈 |\n| 网络错误 | Toast 错误提示 + 重试按钮 | 可操作 |\n| 权限错误 | 弹窗说明 + 引导操作 | 说人话 |\n| 严重错误 | 全屏错误页 + 联系方式 | 提供解决路径 |\n\n### 空状态\n\n| 场景 | 内容要素 |\n|------|----------|\n| 无数据 | 图标 + 说明文字 + 操作按钮 |\n| 无搜索结果 | 提示词 + 搜索建议 |\n| 无权限 | 说明 + 申请入口 |\n\n---\n\n## 参数化惊喜动效 (Delight Moments)\n\n### 惊喜强度与参数关系\n\n> 根据 `emotionalTone` 参数决定惊喜动效的强度\n\n```typescript\ntype DelightLevel = 'none' | 'subtle' | 'moderate' | 'expressive';\n\nfunction getDelightLevel(emotionalTone: number): DelightLevel {\n  if (emotionalTone \u003C 30) return 'none';       \u002F\u002F 极简风格不使用惊喜动效\n  if (emotionalTone \u003C 55) return 'subtle';     \u002F\u002F 轻微：对勾动画\n  if (emotionalTone \u003C 80) return 'moderate';   \u002F\u002F 中等：弹性 + 高亮\n  return 'expressive';                          \u002F\u002F 强烈：撒花\u002Femoji\u002F庆祝\n}\n```\n\n### 惊喜动效对照表\n\n| emotionalTone | 级别 | 成功反馈 | 里程碑 | 首次完成 |\n|---------------|------|----------|--------|----------|\n| 0-29 | none | 无动效 | 无 | 无 |\n| 30-54 | subtle | 对勾淡入 | 微弹高亮 | 轻微光效 |\n| 55-79 | moderate | 对勾 + 弹性 | 徽章动画 | 光效 + 震动 |\n| 80-100 | expressive | 撒花 + 对勾 | 烟花 + 徽章 | 全屏庆祝 |\n\n### Delight 触发时机\n\n| 时机 | subtle | moderate | expressive |\n|------|--------|----------|------------|\n| 首次完成任务 | 轻微高亮 | 光效动画 | 撒花\u002F烟花 |\n| 达成里程碑 | 微弹提示 | 徽章动画 | 徽章 + 震动 + emoji |\n| 重要操作成功 | 对勾淡入 | 弹性对勾 | 对勾 + 撒花 |\n| 解锁成就 | 轻微脉冲 | 星星效果 | 全屏光效 |\n\n### Delight 动效代码\n\n```tsx\n\u002F\u002F 撒花庆祝\nfunction Confetti({ trigger }: { trigger: boolean }) {\n  if (!trigger) return null\n  return (\n    \u003Cdiv className=\"fixed inset-0 pointer-events-none z-50 overflow-hidden\">\n      {[...Array(50)].map((_, i) => (\n        \u003Cspan\n          key={i}\n          className=\"absolute w-3 h-3 animate-confetti\"\n          style={{\n            left: `${Math.random() * 100}%`,\n            top: '-20px',\n            backgroundColor: ['#FF6B6B', '#4ECDC4', '#FFE66D', '#A855F7', '#FF00FF'][i % 5],\n            animationDelay: `${Math.random() * 0.5}s`,\n            animationDuration: `${1.5 + Math.random()}s`,\n          }}\n        \u002F>\n      ))}\n    \u003C\u002Fdiv>\n  )\n}\n\n\u002F\u002F 成功对勾（带弹性）\nfunction SuccessCheck() {\n  return (\n    \u003Cdiv className=\"w-16 h-16 rounded-full bg-green-100 flex items-center justify-center animate-success-pop\">\n      \u003Csvg className=\"w-8 h-8 text-green-500\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"3\">\n        \u003Cpath className=\"animate-check-draw\" d=\"M5 13l4 4L19 7\" strokeLinecap=\"round\" strokeLinejoin=\"round\" \u002F>\n      \u003C\u002Fsvg>\n    \u003C\u002Fdiv>\n  )\n}\n\n\u002F\u002F 趣味加载（不同风格）\nfunction FunLoader({ style = 'warm' }: { style: 'minimal' | 'warm' | 'playful' }) {\n  const loaders = {\n    minimal: \u003Cdiv className=\"w-4 h-4 border-2 border-black border-t-transparent rounded-full animate-spin\" \u002F>,\n    warm: (\n      \u003Cdiv className=\"flex flex-col items-center gap-3\">\n        \u003Cdiv className=\"text-3xl animate-bounce\">☕\u003C\u002Fdiv>\n        \u003Cp className=\"text-sm text-gray-500\">马上就好...\u003C\u002Fp>\n      \u003C\u002Fdiv>\n    ),\n    playful: (\n      \u003Cdiv className=\"flex gap-1\">\n        {[0, 1, 2].map(i => (\n          \u003Cdiv\n            key={i}\n            className=\"w-3 h-3 bg-gradient-to-r from-pink-500 to-cyan-500 rounded-full animate-bounce\"\n            style={{ animationDelay: `${i * 0.15}s` }}\n          \u002F>\n        ))}\n      \u003C\u002Fdiv>\n    ),\n  }\n  return loaders[style]\n}\n```\n\n### Delight 动画 CSS\n\n```css\n\u002F* 撒花下落 *\u002F\n@keyframes confetti {\n  0% { transform: translateY(0) rotate(0deg); opacity: 1; }\n  100% { transform: translateY(100vh) rotate(720deg); opacity: 0; }\n}\n.animate-confetti { animation: confetti 2s ease-out forwards; }\n\n\u002F* 成功弹出 *\u002F\n@keyframes success-pop {\n  0% { transform: scale(0); opacity: 0; }\n  50% { transform: scale(1.2); }\n  100% { transform: scale(1); opacity: 1; }\n}\n.animate-success-pop { animation: success-pop 0.4s cubic-bezier(0.34, 1.56, 0.64, 1); }\n\n\u002F* 对勾绘制 *\u002F\n@keyframes check-draw {\n  0% { stroke-dashoffset: 24; }\n  100% { stroke-dashoffset: 0; }\n}\n.animate-check-draw {\n  stroke-dasharray: 24;\n  stroke-dashoffset: 24;\n  animation: check-draw 0.4s ease-out 0.2s forwards;\n}\n\n\u002F* 星星闪烁 *\u002F\n@keyframes twinkle {\n  0%, 100% { opacity: 1; transform: scale(1); }\n  50% { opacity: 0.5; transform: scale(0.8); }\n}\n.animate-twinkle { animation: twinkle 1s ease-in-out infinite; }\n\n\u002F* 脉冲光环 *\u002F\n@keyframes pulse-ring {\n  0% { transform: scale(1); opacity: 0.8; }\n  100% { transform: scale(1.5); opacity: 0; }\n}\n.animate-pulse-ring { animation: pulse-ring 1s ease-out infinite; }\n```\n\n---\n\n## 参数化动效系统\n\n> 根据 `motionIntensity` 参数（0-100）生成匹配的动效参数\n\n### 动效生成函数\n\n```typescript\ninterface MotionParams {\n  duration: number;      \u002F\u002F 毫秒\n  easing: string;        \u002F\u002F CSS缓动函数\n  staggerDelay: number;  \u002F\u002F 错开延迟（毫秒）\n  hoverScale: number;    \u002F\u002F 悬停缩放比例\n  clickScale: number;    \u002F\u002F 点击缩放比例\n}\n\nfunction getMotionParams(motionIntensity: number): MotionParams {\n  \u002F\u002F 时长：80ms (克制) → 500ms (夸张)\n  const duration = 80 + motionIntensity * 4.2;\n  \n  \u002F\u002F 缓动函数随强度变化\n  let easing: string;\n  if (motionIntensity \u003C 25) {\n    easing = 'cubic-bezier(0.2, 0, 0, 1)';           \u002F\u002F 快速线性\n  } else if (motionIntensity \u003C 50) {\n    easing = 'cubic-bezier(0.16, 1, 0.3, 1)';        \u002F\u002F 标准ease-out\n  } else if (motionIntensity \u003C 75) {\n    easing = 'cubic-bezier(0.34, 1.56, 0.64, 1)';    \u002F\u002F 轻微弹性\n  } else {\n    easing = 'cubic-bezier(0.175, 0.885, 0.32, 1.275)'; \u002F\u002F 明显弹性\n  }\n  \n  \u002F\u002F 错开延迟：30ms (克制) → 80ms (夸张)\n  const staggerDelay = 30 + motionIntensity * 0.5;\n  \n  \u002F\u002F 悬停缩放：1.0 (无) → 1.05 (明显)\n  const hoverScale = 1 + (motionIntensity > 40 ? motionIntensity * 0.0005 : 0);\n  \n  \u002F\u002F 点击缩放：0.98 (轻微) → 0.92 (明显)\n  const clickScale = 0.98 - (motionIntensity * 0.0006);\n  \n  return { duration, easing, staggerDelay, hoverScale, clickScale };\n}\n```\n\n### 动效参数对照表\n\n| motionIntensity | 时长 | 缓动类型 | 特点 |\n|-----------------|------|----------|------|\n| 0-24 | 80-180ms | linear\u002Fsnap | 瞬间响应，无多余 |\n| 25-49 | 185-285ms | ease-out | 稳定，可预测 |\n| 50-74 | 290-395ms | spring轻弹 | 柔和，让人放松 |\n| 75-100 | 395-500ms | spring强弹 | 弹跳，有活力 |\n\n### 缓动函数库\n\n```css\n:root {\n  \u002F* 根据 motionIntensity 选择 *\u002F\n  \n  \u002F* 0-24: 快速响应 *\u002F\n  --easing-snap: cubic-bezier(0.2, 0, 0, 1);\n  \n  \u002F* 25-49: 标准流畅 *\u002F\n  --easing-smooth: cubic-bezier(0.16, 1, 0.3, 1);\n  \n  \u002F* 50-74: 轻微弹性 *\u002F\n  --easing-spring-soft: cubic-bezier(0.34, 1.56, 0.64, 1);\n  \n  \u002F* 75-100: 明显弹性 *\u002F\n  --easing-spring-hard: cubic-bezier(0.175, 0.885, 0.32, 1.275);\n}\n```\n\n### 动效应用示例\n\n```tsx\n\u002F\u002F 根据参数生成组件样式\nfunction AnimatedButton({ motionIntensity }: { motionIntensity: number }) {\n  const params = getMotionParams(motionIntensity);\n  \n  return (\n    \u003Cbutton\n      style={{\n        transition: `all ${params.duration}ms ${params.easing}`,\n      }}\n      className={`\n        hover:scale-[${params.hoverScale}]\n        active:scale-[${params.clickScale}]\n      `}\n    >\n      Click me\n    \u003C\u002Fbutton>\n  );\n}\n\n\u002F\u002F 列表错开动画\nfunction StaggerList({ items, motionIntensity }: Props) {\n  const params = getMotionParams(motionIntensity);\n  \n  return (\n    \u003Cul>\n      {items.map((item, i) => (\n        \u003Cli\n          key={item.id}\n          style={{\n            animation: `slide-up ${params.duration}ms ${params.easing}`,\n            animationDelay: `${i * params.staggerDelay}ms`,\n          }}\n        >\n          {item.content}\n        \u003C\u002Fli>\n      ))}\n    \u003C\u002Ful>\n  );\n}\n```\n\n### 动效场景适配\n\n| 场景 | 低参数 (0-40) | 高参数 (60-100) |\n|------|---------------|-----------------|\n| 元素出现 | 快速淡入 | 淡入 + 弹性上移 |\n| 弹窗出现 | 快速缩放 | 弹性缩放 + overshoot |\n| 悬停 | 仅背景色变化 | 背景色 + 上浮 + 阴影 |\n| 点击 | 轻微缩小(0.98) | 明显缩小(0.92) + 回弹 |\n| 列表加载 | 快速全部出现 | 错开出现(stagger) |\n\n### 错开延迟 (Stagger)\n\n```tsx\n\u002F\u002F 列表项依次出现\nfunction StaggerList({ items }: { items: any[] }) {\n  return (\n    \u003Cul>\n      {items.map((item, i) => (\n        \u003Cli\n          key={item.id}\n          className=\"animate-slide-up\"\n          style={{ animationDelay: `${i * 50}ms` }}\n        >\n          {item.content}\n        \u003C\u002Fli>\n      ))}\n    \u003C\u002Ful>\n  )\n}\n```\n\n### 基础动画代码\n\n```css\n@keyframes slide-up {\n  from { opacity: 0; transform: translateY(10px); }\n  to { opacity: 1; transform: translateY(0); }\n}\n\n@keyframes fade-in {\n  from { opacity: 0; }\n  to { opacity: 1; }\n}\n\n@keyframes scale-in {\n  from { opacity: 0; transform: scale(0.95); }\n  to { opacity: 1; transform: scale(1); }\n}\n\n\u002F* 弹性缩放（温暖\u002F活泼风格） *\u002F\n@keyframes pop-in {\n  0% { opacity: 0; transform: scale(0.8); }\n  70% { transform: scale(1.05); }\n  100% { opacity: 1; transform: scale(1); }\n}\n\n\u002F* 抖动（错误反馈） *\u002F\n@keyframes shake {\n  0%, 100% { transform: translateX(0); }\n  25% { transform: translateX(-5px); }\n  75% { transform: translateX(5px); }\n}\n\n.animate-slide-up { animation: slide-up 0.3s var(--ease-out); }\n.animate-fade-in { animation: fade-in 0.2s var(--ease-out); }\n.animate-scale-in { animation: scale-in 0.2s var(--ease-out); }\n.animate-pop-in { animation: pop-in 0.4s var(--spring-soft); }\n.animate-shake { animation: shake 0.3s ease-in-out; }\n```\n\n---\n\n## 微交互设计\n\n### 按钮交互\n\n```html\n\u003C!-- 完整交互状态 -->\n\u003Cbutton class=\"px-4 py-2.5 bg-primary-500 text-white rounded-xl\n               hover:bg-primary-600 \n               active:bg-primary-700 active:scale-[0.98]\n               focus:outline-none focus:ring-2 focus:ring-primary-500\u002F20\n               disabled:opacity-50 disabled:cursor-not-allowed\n               transition-all duration-200\">\n  按钮\n\u003C\u002Fbutton>\n```\n\n### 输入框交互\n\n```html\n\u003C!-- 完整输入框状态 -->\n\u003Cinput class=\"w-full px-4 py-2.5 bg-gray-50 border border-gray-200 rounded-xl\n              text-gray-900 text-sm placeholder-gray-400\n              hover:border-gray-300\n              focus:outline-none focus:ring-2 focus:ring-primary-500\u002F20 focus:border-primary-500\n              disabled:bg-gray-100 disabled:cursor-not-allowed\n              transition-all duration-200\"\n       placeholder=\"请输入...\">\n```\n\n### 卡片交互\n\n```html\n\u003C!-- 可点击卡片 -->\n\u003Cdiv class=\"bg-white rounded-2xl border border-gray-100 p-6\n            cursor-pointer\n            hover:border-gray-200 hover:shadow-md\n            active:scale-[0.99]\n            transition-all duration-200\">\n  卡片内容\n\u003C\u002Fdiv>\n```\n\n### 列表项交互\n\n```html\n\u003C!-- 列表项悬停 -->\n\u003Cdiv class=\"px-4 py-3 rounded-xl\n            hover:bg-gray-50\n            active:bg-gray-100\n            transition-colors duration-150 cursor-pointer\">\n  列表项\n\u003C\u002Fdiv>\n```\n\n---\n\n## 参数化文案系统\n\n> 根据 `emotionalTone` 参数（0-100）生成匹配的文案风格\n\n### 文案生成函数\n\n```typescript\ntype CopyStyle = 'minimal' | 'neutral' | 'friendly' | 'enthusiastic';\n\nfunction getCopyStyle(emotionalTone: number): CopyStyle {\n  if (emotionalTone \u003C 25) return 'minimal';      \u002F\u002F 0-24: 极简\n  if (emotionalTone \u003C 50) return 'neutral';      \u002F\u002F 25-49: 中性\n  if (emotionalTone \u003C 75) return 'friendly';     \u002F\u002F 50-74: 友好\n  return 'enthusiastic';                          \u002F\u002F 75-100: 热情\n}\n\n\u002F\u002F 文案库：每个场景4个级别\nconst COPY_LIBRARY = {\n  loading: {\n    minimal: 'Loading',\n    neutral: '加载中...',\n    friendly: '马上就好...',\n    enthusiastic: '稍等一下下~ ✨'\n  },\n  saveSuccess: {\n    minimal: 'Saved',\n    neutral: '已保存',\n    friendly: '保存成功！',\n    enthusiastic: '太棒了，搞定！?'\n  },\n  error: {\n    minimal: 'Failed',\n    neutral: '操作失败',\n    friendly: '哎呀，出了点问题',\n    enthusiastic: 'Oops！再试试？?'\n  },\n  empty: {\n    minimal: 'No items',\n    neutral: '暂无数据',\n    friendly: '这里空空如也，创建第一个吧',\n    enthusiastic: '还没有内容呢，要不创建一个？✨'\n  }\n};\n\n\u002F\u002F 使用\nfunction getCopy(scene: string, emotionalTone: number): string {\n  const style = getCopyStyle(emotionalTone);\n  return COPY_LIBRARY[scene][style];\n}\n\n\u002F\u002F 示例：\n\u002F\u002F emotionalTone: 30 → getCopy('loading', 30) → \"加载中...\"\n\u002F\u002F emotionalTone: 70 → getCopy('loading', 70) → \"马上就好...\"\n\u002F\u002F emotionalTone: 90 → getCopy('loading', 90) → \"稍等一下下~ ✨\"\n```\n\n### 文案参数对照表\n\n| emotionalTone | 风格 | 特点 | 示例(保存成功) |\n|---------------|------|------|---------------|\n| 0-24 | minimal | 极简、直接、无情绪 | \"Saved\" |\n| 25-49 | neutral | 清晰、友好、不过分 | \"已保存\" |\n| 50-74 | friendly | 亲切、鼓励、语气词 | \"保存成功！\" |\n| 75-100 | enthusiastic | 热情、emoji、感叹 | \"太棒了，搞定！?\" |\n\n### 完整文案库\n\n#### 状态文案\n\n| 场景 | minimal (0-24) | neutral (25-49) | friendly (50-74) | enthusiastic (75-100) |\n|------|----------------|-----------------|------------------|----------------------|\n| 加载中 | Loading | 加载中... | 马上就好... | 稍等一下下~ ✨ |\n| 保存成功 | Saved | 已保存 | 保存成功！ | 太棒了，搞定！? |\n| 操作失败 | Failed | 操作失败 | 哎呀，出了点问题 | Oops！再试试？? |\n| 空状态 | No items | 暂无数据 | 这里空空如也 | 还没有内容呢~ ✨ |\n| 网络错误 | Offline | 网络连接失败 | 网络不太稳定 | 网络开小差了~ ? |\n\n#### 确认弹窗文案\n\n| 场景 | minimal | neutral | friendly | enthusiastic |\n|------|---------|---------|----------|--------------|\n| 删除标题 | Delete? | 确认删除 | 确定要删除吗？ | 真的要删掉吗？? |\n| 删除描述 | Cannot undo | 此操作不可撤销 | 删除后无法恢复哦 | 删掉就找不回来啦！ |\n| 确认按钮 | Delete | 确认删除 | 确定删除 | 删掉它！ |\n| 取消按钮 | Cancel | 取消 | 再想想 | 我再想想 |\n\n#### 欢迎\u002F问候\n\n| 场景 | minimal | neutral | friendly | enthusiastic |\n|------|---------|---------|----------|--------------|\n| 首次欢迎 | Welcome | 欢迎使用 | 欢迎来到这里！ | Hey！欢迎加入！? |\n| 回访问候 | — | 您好 | 欢迎回来！ | 好久不见！? |\n| 完成引导 | Done | 设置完成 | 准备就绪！ | 搞定！准备起飞！? |\n\n### 文案通用原则\n\n| 原则 | 说明 | 好例子 | 坏例子 |\n|------|------|--------|--------|\n| 像人说话 | 避免机器腔 | \"哎呀，出了点问题\" | \"Error: Operation failed\" |\n| 避免责怪 | 不让用户感到愚蠢 | \"请输入邮箱地址\" | \"邮箱格式错误！\" |\n| 提供出路 | 告诉用户怎么办 | \"网络不稳定，点击重试\" | \"网络错误\" |\n| 适度幽默 | 根据参数调整程度 | emotionalTone > 70 时可用 | 低参数时避免 |\n\n### Emoji 使用规则\n\n```typescript\nfunction shouldUseEmoji(emotionalTone: number): boolean {\n  return emotionalTone >= 60;  \u002F\u002F 60以上才使用emoji\n}\n\nfunction getEmojiIntensity(emotionalTone: number): 'none' | 'sparse' | 'frequent' {\n  if (emotionalTone \u003C 60) return 'none';\n  if (emotionalTone \u003C 80) return 'sparse';  \u002F\u002F 偶尔使用\n  return 'frequent';  \u002F\u002F 大方使用\n}\n```\n\n---\n\n## 响应式交互\n\n### 触摸优化\n\n```css\n\u002F* 触摸设备优化 *\u002F\n@media (hover: none) {\n  \u002F* 移除 hover 效果，避免粘滞 *\u002F\n  .button:hover {\n    background-color: initial;\n  }\n  \n  \u002F* 增大点击区域 *\u002F\n  .touch-target {\n    min-height: 44px;\n    min-width: 44px;\n  }\n}\n```\n\n### 手势支持\n\n| 手势 | 操作 |\n|------|------|\n| 点击 | 主要交互 |\n| 长按 | 显示上下文菜单 |\n| 左滑 | 删除\u002F归档（列表项） |\n| 下拉 | 刷新 |\n\n---\n\n## 可访问性\n\n### 键盘导航\n\n```html\n\u003C!-- 确保可聚焦 -->\n\u003Cbutton tabindex=\"0\">可聚焦按钮\u003C\u002Fbutton>\n\n\u003C!-- 跳过链接 -->\n\u003Ca href=\"#main\" class=\"sr-only focus:not-sr-only\">跳到主内容\u003C\u002Fa>\n```\n\n### 焦点样式\n\n```css\n\u002F* 清晰的焦点指示 *\u002F\n:focus-visible {\n  outline: 2px solid var(--primary-500);\n  outline-offset: 2px;\n}\n\n\u002F* 移除默认 outline，使用自定义样式 *\u002F\n:focus {\n  outline: none;\n}\n```\n\n### 屏幕阅读器\n\n```html\n\u003C!-- 仅屏幕阅读器可见 -->\n\u003Cspan class=\"sr-only\">关闭弹窗\u003C\u002Fspan>\n\n\u003C!-- 实时区域 -->\n\u003Cdiv aria-live=\"polite\" aria-atomic=\"true\">\n  \u003C!-- 动态内容会被朗读 -->\n\u003C\u002Fdiv>\n```\n\n---\n\n## 必加 Classes\n\n```tsx\n\"transition-all duration-200\"  \u002F\u002F 所有交互元素\n\"tabular-nums\"                 \u002F\u002F 数字对齐\n\"font-mono\"                    \u002F\u002F 地址\u002F哈希\u002F代码\n\"truncate\"                     \u002F\u002F 文本截断\n\"select-none\"                  \u002F\u002F 禁止选中（按钮等）\n\"cursor-pointer\"               \u002F\u002F 可点击元素\n```\n\n---\n\n## 设计检查清单\n\n应用 UX 模式后，最终检查：\n\n```\n视觉一致性：\n- [ ] 圆角统一 (卡片 2xl，按钮 xl，输入框 xl)\n- [ ] 间距遵循 8px 基准系统\n- [ ] 字号阶梯清晰 (最多 3-4 种)\n- [ ] 颜色使用克制 (主色 + 灰度)\n\n交互体验：\n- [ ] 所有可交互元素有 hover 状态\n- [ ] 过渡动画平滑 (150-300ms)\n- [ ] 焦点状态清晰可见\n- [ ] 加载状态有反馈\n\n留白与层次：\n- [ ] 组件间有足够呼吸感\n- [ ] 视觉层次不超过 3 级\n- [ ] 使用边框代替重阴影\n- [ ] 背景色使用浅灰而非纯白\n\n文案：\n- [ ] 文案简洁明了\n- [ ] 错误提示说人话\n- [ ] 空状态有引导\n```\n\n---\n\n## 人性化反馈设计\n\n### 超越\"成功\u002F失败\"\n\n传统反馈只告诉用户结果，人性化反馈关心用户的感受：\n\n| 场景 | 传统反馈 | 人性化反馈 |\n|------|---------|-----------|\n| 保存成功 | \"保存成功\" | \"已保存。你今天效率真高！\" |\n| 删除成功 | \"删除成功\" | \"已删除。需要的话可以在回收站找回\" |\n| 上传完成 | \"上传完成\" | \"上传完成！文件看起来不错 ?\" |\n| 首次操作 | \"操作成功\" | \"太棒了，这是你的第一个项目！?\" |\n| 连续操作 | \"保存成功\" | \"又搞定一个！保持这个节奏 ?\" |\n\n### 错误反馈的温度\n\n```\n冷冰冰（❌ 避免）：\n- \"Error 500: Internal Server Error\"\n- \"操作失败\"\n- \"请求超时\"\n\n有温度（✅ 推荐）：\n- \"服务器开了个小差，我们正在修复，请稍后再试\"\n- \"哎呀，这个操作没成功，再试一次？\"\n- \"网络有点慢，要不换个信号好的地方？\"\n```\n\n### 空状态的温暖\n\n```html\n\u003C!-- 冷冰冰 ❌ -->\n\u003Cdiv class=\"text-center text-gray-500\">\n  暂无数据\n\u003C\u002Fdiv>\n\n\u003C!-- 有温度 ✅ -->\n\u003Cdiv class=\"text-center py-12\">\n  \u003Cdiv class=\"text-6xl mb-4\">?\u003C\u002Fdiv>\n  \u003Ch3 class=\"text-lg font-medium text-gray-900 mb-2\">还没有任何笔记\u003C\u002Fh3>\n  \u003Cp class=\"text-sm text-gray-500 mb-6\">\n    写下你的第一个想法吧，好记性不如烂笔头\n  \u003C\u002Fp>\n  \u003Cbutton class=\"px-4 py-2 bg-primary text-white rounded-xl\">\n    创建笔记\n  \u003C\u002Fbutton>\n\u003C\u002Fdiv>\n```\n\n### 加载状态的趣味\n\n```html\n\u003C!-- 无聊 ❌ -->\n\u003Cdiv class=\"animate-spin w-8 h-8 border-2 border-gray-300 border-t-primary rounded-full\">\u003C\u002Fdiv>\n\n\u003C!-- 有趣 ✅ -->\n\u003Cdiv class=\"flex flex-col items-center gap-3\">\n  \u003Cdiv class=\"text-4xl animate-bounce\">?\u003C\u002Fdiv>\n  \u003Cp class=\"text-sm text-gray-500\">正在准备精彩内容...\u003C\u002Fp>\n\u003C\u002Fdiv>\n\n\u003C!-- 或者：进度文案变化 -->\n\u003Cdiv class=\"text-center\">\n  \u003Cdiv class=\"animate-pulse text-sm text-gray-500\">\n    \u003C!-- 随时间变化的文案 -->\n    \u003C!-- 0-2s: \"加载中...\" -->\n    \u003C!-- 2-5s: \"快好了...\" -->\n    \u003C!-- 5s+:  \"稍微有点慢，再等等...\" -->\n  \u003C\u002Fdiv>\n\u003C\u002Fdiv>\n```\n\n### 进度反馈的鼓励\n\n```tsx\nfunction ProgressFeedback({ progress }: { progress: number }) {\n  const getMessage = () => {\n    if (progress \u003C 25) return \"开始了！继续加油 ?\"\n    if (progress \u003C 50) return \"进展不错！\"\n    if (progress \u003C 75) return \"已经过半了！\"\n    if (progress \u003C 100) return \"马上就完成了！\"\n    return \"太棒了，完成了！?\"\n  }\n  \n  return (\n    \u003Cdiv>\n      \u003Cdiv className=\"flex justify-between text-sm mb-2\">\n        \u003Cspan>{getMessage()}\u003C\u002Fspan>\n        \u003Cspan className=\"font-medium\">{progress}%\u003C\u002Fspan>\n      \u003C\u002Fdiv>\n      \u003Cdiv className=\"h-2 bg-gray-100 rounded-full overflow-hidden\">\n        \u003Cdiv \n          className=\"h-full bg-primary rounded-full transition-all duration-500\"\n          style={{ width: `${progress}%` }}\n        \u002F>\n      \u003C\u002Fdiv>\n    \u003C\u002Fdiv>\n  )\n}\n```\n\n---\n\n## 设计检查清单（消除AI味）\n\n最终检查，确保设计有灵魂：\n\n```\n文案检查：\n- [ ] 文案像真人说的话吗？\n- [ ] 错误提示是否让人感到被关心而非被责怪？\n- [ ] 空状态是否温暖\u002F有趣？\n- [ ] 有没有在适当的地方使用 emoji？\n\n动效检查：\n- [ ] 动效是否有个性（不只是 ease-out 200ms）？\n- [ ] 重要操作是否有惊喜反馈？\n- [ ] 列表是否有错开加载效果？\n- [ ] 成功状态是否有庆祝感？\n\n情感检查：\n- [ ] 首次用户有没有特别的欢迎？\n- [ ] 里程碑时刻有没有庆祝？\n- [ ] 等待时是否不无聊？\n- [ ] 用户离开时有没有温暖的告别？\n```\n\n---\n\n## 参数使用示例\n\n### 完整工作流\n\n```typescript\n\u002F\u002F 1. 从 brand-personality 获取参数\nconst styleParams = {\n  emotionalTone: 65,\n  motionIntensity: 55\n};\n\n\u002F\u002F 2. 生成文案\nconst loadingCopy = getCopy('loading', styleParams.emotionalTone);\n\u002F\u002F → \"马上就好...\"\n\n\u002F\u002F 3. 生成动效参数\nconst motion = getMotionParams(styleParams.motionIntensity);\n\u002F\u002F → { duration: 311, easing: 'cubic-bezier(0.34, 1.56, 0.64, 1)', ... }\n\n\u002F\u002F 4. 确定惊喜级别\nconst delightLevel = getDelightLevel(styleParams.emotionalTone);\n\u002F\u002F → 'moderate'\n\n\u002F\u002F 5. 应用到组件\n\u003CButton\n  style={{ transition: `all ${motion.duration}ms ${motion.easing}` }}\n  onClick={() => {\n    \u002F\u002F 操作成功后\n    showToast(getCopy('saveSuccess', styleParams.emotionalTone));\n    if (delightLevel !== 'none') showSuccessAnimation(delightLevel);\n  }}\n>\n  {getCopy('save', styleParams.emotionalTone)}\n\u003C\u002FButton>\n```\n\n---\n\n## 相关技能\n\n- **brand-personality**: 提供 emotionalTone 和 motionIntensity 参数\n- **design-tokens**: 提供圆角、颜色等视觉令牌\n- **ui-components**: 使用本技能的文案和动效参数\n- **uiux-designer**: 统一调度入口\n","# UX Patterns (参数化交互模式库)\n\n**定位**: 确保交互体验有温度、有个性。\n\n**核心目标**: 根据风格参数生成匹配的文案和动效，而非从预设中选择。\n\n**依赖**: 接收 [brand-personality](..\u002Fbrand-personality\u002FSKILL.md) 输出的 `emotionalTone` 和 `motionIntensity` 参数。\n\n---\n\n## Pre-Polish Checklist\n\n应用 UX 模式前，逐项检查：\n\n```\n功能完整性：\n- [ ] Loading: 有 Spinner\u002FSkeleton\u002F趣味加载?\n- [ ] Success: 有 Toast\u002F确认\u002F庆祝动效?\n- [ ] Error: 有温暖的错误提示?\n- [ ] Empty: 有有趣的空状态?\n- [ ] Animations: 状态切换有过渡?\n- [ ] Hover: 可交互元素有悬停状态?\n- [ ] Focus: 焦点状态清晰可见?\n\n情感化检查（消除AI味）：\n- [ ] 文案是否像真人说的话？\n- [ ] 有没有至少一个惊喜时刻？\n- [ ] 动效是否有个性（不只是 ease-out）？\n- [ ] 空状态\u002F错误状态是否让人感到被关心？\n```\n\n---\n\n## 状态反馈模式\n\n### 加载状态\n\n| 场景 | 反馈方式 | 示例 |\n|------|----------|------|\n| 按钮提交 | 按钮内 Spinner + 文字 | \"保存中...\" |\n| 页面加载 | 骨架屏 (Skeleton) | 灰色占位块 |\n| 数据刷新 | 顶部进度条 \u002F Spinner | NProgress 风格 |\n| 后台操作 | Toast 提示 | \"正在处理...\" |\n\n### 成功状态\n\n| 场景 | 反馈方式 | 持续时间 |\n|------|----------|---------|\n| 表单提交 | Toast 成功提示 | 3秒自动消失 |\n| 重要操作 | 弹窗确认 + 对勾动画 | 用户点击关闭 |\n| 保存操作 | 轻量提示（顶部闪现） | 2秒自动消失 |\n\n### 错误状态\n\n| 场景 | 反馈方式 | 要求 |\n|------|----------|------|\n| 表单验证 | 输入框下方红色提示 | 即时反馈 |\n| 网络错误 | Toast 错误提示 + 重试按钮 | 可操作 |\n| 权限错误 | 弹窗说明 + 引导操作 | 说人话 |\n| 严重错误 | 全屏错误页 + 联系方式 | 提供解决路径 |\n\n### 空状态\n\n| 场景 | 内容要素 |\n|------|----------|\n| 无数据 | 图标 + 说明文字 + 操作按钮 |\n| 无搜索结果 | 提示词 + 搜索建议 |\n| 无权限 | 说明 + 申请入口 |\n\n---\n\n## 参数化惊喜动效 (Delight Moments)\n\n### 惊喜强度与参数关系\n\n> 根据 `emotionalTone` 参数决定惊喜动效的强度\n\n```typescript\ntype DelightLevel = 'none' | 'subtle' | 'moderate' | 'expressive';\n\nfunction getDelightLevel(emotionalTone: number): DelightLevel {\n  if (emotionalTone \u003C 30) return 'none';       \u002F\u002F 极简风格不使用惊喜动效\n  if (emotionalTone \u003C 55) return 'subtle';     \u002F\u002F 轻微：对勾动画\n  if (emotionalTone \u003C 80) return 'moderate';   \u002F\u002F 中等：弹性 + 高亮\n  return 'expressive';                          \u002F\u002F 强烈：撒花\u002Femoji\u002F庆祝\n}\n```\n\n### 惊喜动效对照表\n\n| emotionalTone | 级别 | 成功反馈 | 里程碑 | 首次完成 |\n|---------------|------|----------|--------|----------|\n| 0-29 | none | 无动效 | 无 | 无 |\n| 30-54 | subtle | 对勾淡入 | 微弹高亮 | 轻微光效 |\n| 55-79 | moderate | 对勾 + 弹性 | 徽章动画 | 光效 + 震动 |\n| 80-100 | expressive | 撒花 + 对勾 | 烟花 + 徽章 | 全屏庆祝 |\n\n### Delight 触发时机\n\n| 时机 | subtle | moderate | expressive |\n|------|--------|----------|------------|\n| 首次完成任务 | 轻微高亮 | 光效动画 | 撒花\u002F烟花 |\n| 达成里程碑 | 微弹提示 | 徽章动画 | 徽章 + 震动 + emoji |\n| 重要操作成功 | 对勾淡入 | 弹性对勾 | 对勾 + 撒花 |\n| 解锁成就 | 轻微脉冲 | 星星效果 | 全屏光效 |\n\n### Delight 动效代码\n\n```tsx\n\u002F\u002F 撒花庆祝\nfunction Confetti({ trigger }: { trigger: boolean }) {\n  if (!trigger) return null\n  return (\n    \u003Cdiv className=\"fixed inset-0 pointer-events-none z-50 overflow-hidden\">\n      {[...Array(50)].map((_, i) => (\n        \u003Cspan\n          key={i}\n          className=\"absolute w-3 h-3 animate-confetti\"\n          style={{\n            left: `${Math.random() * 100}%`,\n            top: '-20px',\n            backgroundColor: ['#FF6B6B', '#4ECDC4', '#FFE66D', '#A855F7', '#FF00FF'][i % 5],\n            animationDelay: `${Math.random() * 0.5}s`,\n            animationDuration: `${1.5 + Math.random()}s`,\n          }}\n        \u002F>\n      ))}\n    \u003C\u002Fdiv>\n  )\n}\n\n\u002F\u002F 成功对勾（带弹性）\nfunction SuccessCheck() {\n  return (\n    \u003Cdiv className=\"w-16 h-16 rounded-full bg-green-100 flex items-center justify-center animate-success-pop\">\n      \u003Csvg className=\"w-8 h-8 text-green-500\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"3\">\n        \u003Cpath className=\"animate-check-draw\" d=\"M5 13l4 4L19 7\" strokeLinecap=\"round\" strokeLinejoin=\"round\" \u002F>\n      \u003C\u002Fsvg>\n    \u003C\u002Fdiv>\n  )\n}\n\n\u002F\u002F 趣味加载（不同风格）\nfunction FunLoader({ style = 'warm' }: { style: 'minimal' | 'warm' | 'playful' }) {\n  const loaders = {\n    minimal: \u003Cdiv className=\"w-4 h-4 border-2 border-black border-t-transparent rounded-full animate-spin\" \u002F>,\n    warm: (\n      \u003Cdiv className=\"flex flex-col items-center gap-3\">\n        \u003Cdiv className=\"text-3xl animate-bounce\">☕\u003C\u002Fdiv>\n        \u003Cp className=\"text-sm text-gray-500\">马上就好...\u003C\u002Fp>\n      \u003C\u002Fdiv>\n    ),\n    playful: (\n      \u003Cdiv className=\"flex gap-1\">\n        {[0, 1, 2].map(i => (\n          \u003Cdiv\n            key={i}\n            className=\"w-3 h-3 bg-gradient-to-r from-pink-500 to-cyan-500 rounded-full animate-bounce\"\n            style={{ animationDelay: `${i * 0.15}s` }}\n          \u002F>\n        ))}\n      \u003C\u002Fdiv>\n    ),\n  }\n  return loaders[style]\n}\n```\n\n### Delight 动画 CSS\n\n```css\n\u002F* 撒花下落 *\u002F\n@keyframes confetti {\n  0% { transform: translateY(0) rotate(0deg); opacity: 1; }\n  100% { transform: translateY(100vh) rotate(720deg); opacity: 0; }\n}\n.animate-confetti { animation: confetti 2s ease-out forwards; }\n\n\u002F* 成功弹出 *\u002F\n@keyframes success-pop {\n  0% { transform: scale(0); opacity: 0; }\n  50% { transform: scale(1.2); }\n  100% { transform: scale(1); opacity: 1; }\n}\n.animate-success-pop { animation: success-pop 0.4s cubic-bezier(0.34, 1.56, 0.64, 1); }\n\n\u002F* 对勾绘制 *\u002F\n@keyframes check-draw {\n  0% { stroke-dashoffset: 24; }\n  100% { stroke-dashoffset: 0; }\n}\n.animate-check-draw {\n  stroke-dasharray: 24;\n  stroke-dashoffset: 24;\n  animation: check-draw 0.4s ease-out 0.2s forwards;\n}\n\n\u002F* 星星闪烁 *\u002F\n@keyframes twinkle {\n  0%, 100% { opacity: 1; transform: scale(1); }\n  50% { opacity: 0.5; transform: scale(0.8); }\n}\n.animate-twinkle { animation: twinkle 1s ease-in-out infinite; }\n\n\u002F* 脉冲光环 *\u002F\n@keyframes pulse-ring {\n  0% { transform: scale(1); opacity: 0.8; }\n  100% { transform: scale(1.5); opacity: 0; }\n}\n.animate-pulse-ring { animation: pulse-ring 1s ease-out infinite; }\n```\n\n---\n\n## 参数化动效系统\n\n> 根据 `motionIntensity` 参数（0-100）生成匹配的动效参数\n\n### 动效生成函数\n\n```typescript\ninterface MotionParams {\n  duration: number;      \u002F\u002F 毫秒\n  easing: string;        \u002F\u002F CSS缓动函数\n  staggerDelay: number;  \u002F\u002F 错开延迟（毫秒）\n  hoverScale: number;    \u002F\u002F 悬停缩放比例\n  clickScale: number;    \u002F\u002F 点击缩放比例\n}\n\nfunction getMotionParams(motionIntensity: number): MotionParams {\n  \u002F\u002F 时长：80ms (克制) → 500ms (夸张)\n  const duration = 80 + motionIntensity * 4.2;\n  \n  \u002F\u002F 缓动函数随强度变化\n  let easing: string;\n  if (motionIntensity \u003C 25) {\n    easing = 'cubic-bezier(0.2, 0, 0, 1)';           \u002F\u002F 快速线性\n  } else if (motionIntensity \u003C 50) {\n    easing = 'cubic-bezier(0.16, 1, 0.3, 1)';        \u002F\u002F 标准ease-out\n  } else if (motionIntensity \u003C 75) {\n    easing = 'cubic-bezier(0.34, 1.56, 0.64, 1)';    \u002F\u002F 轻微弹性\n  } else {\n    easing = 'cubic-bezier(0.175, 0.885, 0.32, 1.275)'; \u002F\u002F 明显弹性\n  }\n  \n  \u002F\u002F 错开延迟：30ms (克制) → 80ms (夸张)\n  const staggerDelay = 30 + motionIntensity * 0.5;\n  \n  \u002F\u002F 悬停缩放：1.0 (无) → 1.05 (明显)\n  const hoverScale = 1 + (motionIntensity > 40 ? motionIntensity * 0.0005 : 0);\n  \n  \u002F\u002F 点击缩放：0.98 (轻微) → 0.92 (明显)\n  const clickScale = 0.98 - (motionIntensity * 0.0006);\n  \n  return { duration, easing, staggerDelay, hoverScale, clickScale };\n}\n```\n\n### 动效参数对照表\n\n| motionIntensity | 时长 | 缓动类型 | 特点 |\n|-----------------|------|----------|------|\n| 0-24 | 80-180ms | linear\u002Fsnap | 瞬间响应，无多余 |\n| 25-49 | 185-285ms | ease-out | 稳定，可预测 |\n| 50-74 | 290-395ms | spring轻弹 | 柔和，让人放松 |\n| 75-100 | 395-500ms | spring强弹 | 弹跳，有活力 |\n\n### 缓动函数库\n\n```css\n:root {\n  \u002F* 根据 motionIntensity 选择 *\u002F\n  \n  \u002F* 0-24: 快速响应 *\u002F\n  --easing-snap: cubic-bezier(0.2, 0, 0, 1);\n  \n  \u002F* 25-49: 标准流畅 *\u002F\n  --easing-smooth: cubic-bezier(0.16, 1, 0.3, 1);\n  \n  \u002F* 50-74: 轻微弹性 *\u002F\n  --easing-spring-soft: cubic-bezier(0.34, 1.56, 0.64, 1);\n  \n  \u002F* 75-100: 明显弹性 *\u002F\n  --easing-spring-hard: cubic-bezier(0.175, 0.885, 0.32, 1.275);\n}\n```\n\n### 动效应用示例\n\n```tsx\n\u002F\u002F 根据参数生成组件样式\nfunction AnimatedButton({ motionIntensity }: { motionIntensity: number }) {\n  const params = getMotionParams(motionIntensity);\n  \n  return (\n    \u003Cbutton\n      style={{\n        transition: `all ${params.duration}ms ${params.easing}`,\n      }}\n      className={`\n        hover:scale-[${params.hoverScale}]\n        active:scale-[${params.clickScale}]\n      `}\n    >\n      Click me\n    \u003C\u002Fbutton>\n  );\n}\n\n\u002F\u002F 列表错开动画\nfunction StaggerList({ items, motionIntensity }: Props) {\n  const params = getMotionParams(motionIntensity);\n  \n  return (\n    \u003Cul>\n      {items.map((item, i) => (\n        \u003Cli\n          key={item.id}\n          style={{\n            animation: `slide-up ${params.duration}ms ${params.easing}`,\n            animationDelay: `${i * params.staggerDelay}ms`,\n          }}\n        >\n          {item.content}\n        \u003C\u002Fli>\n      ))}\n    \u003C\u002Ful>\n  );\n}\n```\n\n### 动效场景适配\n\n| 场景 | 低参数 (0-40) | 高参数 (60-100) |\n|------|---------------|-----------------|\n| 元素出现 | 快速淡入 | 淡入 + 弹性上移 |\n| 弹窗出现 | 快速缩放 | 弹性缩放 + overshoot |\n| 悬停 | 仅背景色变化 | 背景色 + 上浮 + 阴影 |\n| 点击 | 轻微缩小(0.98) | 明显缩小(0.92) + 回弹 |\n| 列表加载 | 快速全部出现 | 错开出现(stagger) |\n\n### 错开延迟 (Stagger)\n\n```tsx\n\u002F\u002F 列表项依次出现\nfunction StaggerList({ items }: { items: any[] }) {\n  return (\n    \u003Cul>\n      {items.map((item, i) => (\n        \u003Cli\n          key={item.id}\n          className=\"animate-slide-up\"\n          style={{ animationDelay: `${i * 50}ms` }}\n        >\n          {item.content}\n        \u003C\u002Fli>\n      ))}\n    \u003C\u002Ful>\n  )\n}\n```\n\n### 基础动画代码\n\n```css\n@keyframes slide-up {\n  from { opacity: 0; transform: translateY(10px); }\n  to { opacity: 1; transform: translateY(0); }\n}\n\n@keyframes fade-in {\n  from { opacity: 0; }\n  to { opacity: 1; }\n}\n\n@keyframes scale-in {\n  from { opacity: 0; transform: scale(0.95); }\n  to { opacity: 1; transform: scale(1); }\n}\n\n\u002F* 弹性缩放（温暖\u002F活泼风格） *\u002F\n@keyframes pop-in {\n  0% { opacity: 0; transform: scale(0.8); }\n  70% { transform: scale(1.05); }\n  100% { opacity: 1; transform: scale(1); }\n}\n\n\u002F* 抖动（错误反馈） *\u002F\n@keyframes shake {\n  0%, 100% { transform: translateX(0); }\n  25% { transform: translateX(-5px); }\n  75% { transform: translateX(5px); }\n}\n\n.animate-slide-up { animation: slide-up 0.3s var(--ease-out); }\n.animate-fade-in { animation: fade-in 0.2s var(--ease-out); }\n.animate-scale-in { animation: scale-in 0.2s var(--ease-out); }\n.animate-pop-in { animation: pop-in 0.4s var(--spring-soft); }\n.animate-shake { animation: shake 0.3s ease-in-out; }\n```\n\n---\n\n## 微交互设计\n\n### 按钮交互\n\n```html\n\u003C!-- 完整交互状态 -->\n\u003Cbutton class=\"px-4 py-2.5 bg-primary-500 text-white rounded-xl\n               hover:bg-primary-600 \n               active:bg-primary-700 active:scale-[0.98]\n               focus:outline-none focus:ring-2 focus:ring-primary-500\u002F20\n               disabled:opacity-50 disabled:cursor-not-allowed\n               transition-all duration-200\">\n  按钮\n\u003C\u002Fbutton>\n```\n\n### 输入框交互\n\n```html\n\u003C!-- 完整输入框状态 -->\n\u003Cinput class=\"w-full px-4 py-2.5 bg-gray-50 border border-gray-200 rounded-xl\n              text-gray-900 text-sm placeholder-gray-400\n              hover:border-gray-300\n              focus:outline-none focus:ring-2 focus:ring-primary-500\u002F20 focus:border-primary-500\n              disabled:bg-gray-100 disabled:cursor-not-allowed\n              transition-all duration-200\"\n       placeholder=\"请输入...\">\n```\n\n### 卡片交互\n\n```html\n\u003C!-- 可点击卡片 -->\n\u003Cdiv class=\"bg-white rounded-2xl border border-gray-100 p-6\n            cursor-pointer\n            hover:border-gray-200 hover:shadow-md\n            active:scale-[0.99]\n            transition-all duration-200\">\n  卡片内容\n\u003C\u002Fdiv>\n```\n\n### 列表项交互\n\n```html\n\u003C!-- 列表项悬停 -->\n\u003Cdiv class=\"px-4 py-3 rounded-xl\n            hover:bg-gray-50\n            active:bg-gray-100\n            transition-colors duration-150 cursor-pointer\">\n  列表项\n\u003C\u002Fdiv>\n```\n\n---\n\n## 参数化文案系统\n\n> 根据 `emotionalTone` 参数（0-100）生成匹配的文案风格\n\n### 文案生成函数\n\n```typescript\ntype CopyStyle = 'minimal' | 'neutral' | 'friendly' | 'enthusiastic';\n\nfunction getCopyStyle(emotionalTone: number): CopyStyle {\n  if (emotionalTone \u003C 25) return 'minimal';      \u002F\u002F 0-24: 极简\n  if (emotionalTone \u003C 50) return 'neutral';      \u002F\u002F 25-49: 中性\n  if (emotionalTone \u003C 75) return 'friendly';     \u002F\u002F 50-74: 友好\n  return 'enthusiastic';                          \u002F\u002F 75-100: 热情\n}\n\n\u002F\u002F 文案库：每个场景4个级别\nconst COPY_LIBRARY = {\n  loading: {\n    minimal: 'Loading',\n    neutral: '加载中...',\n    friendly: '马上就好...',\n    enthusiastic: '稍等一下下~ ✨'\n  },\n  saveSuccess: {\n    minimal: 'Saved',\n    neutral: '已保存',\n    friendly: '保存成功！',\n    enthusiastic: '太棒了，搞定！?'\n  },\n  error: {\n    minimal: 'Failed',\n    neutral: '操作失败',\n    friendly: '哎呀，出了点问题',\n    enthusiastic: 'Oops！再试试？?'\n  },\n  empty: {\n    minimal: 'No items',\n    neutral: '暂无数据',\n    friendly: '这里空空如也，创建第一个吧',\n    enthusiastic: '还没有内容呢，要不创建一个？✨'\n  }\n};\n\n\u002F\u002F 使用\nfunction getCopy(scene: string, emotionalTone: number): string {\n  const style = getCopyStyle(emotionalTone);\n  return COPY_LIBRARY[scene][style];\n}\n\n\u002F\u002F 示例：\n\u002F\u002F emotionalTone: 30 → getCopy('loading', 30) → \"加载中...\"\n\u002F\u002F emotionalTone: 70 → getCopy('loading', 70) → \"马上就好...\"\n\u002F\u002F emotionalTone: 90 → getCopy('loading', 90) → \"稍等一下下~ ✨\"\n```\n\n### 文案参数对照表\n\n| emotionalTone | 风格 | 特点 | 示例(保存成功) |\n|---------------|------|------|---------------|\n| 0-24 | minimal | 极简、直接、无情绪 | \"Saved\" |\n| 25-49 | neutral | 清晰、友好、不过分 | \"已保存\" |\n| 50-74 | friendly | 亲切、鼓励、语气词 | \"保存成功！\" |\n| 75-100 | enthusiastic | 热情、emoji、感叹 | \"太棒了，搞定！?\" |\n\n### 完整文案库\n\n#### 状态文案\n\n| 场景 | minimal (0-24) | neutral (25-49) | friendly (50-74) | enthusiastic (75-100) |\n|------|----------------|-----------------|------------------|----------------------|\n| 加载中 | Loading | 加载中... | 马上就好... | 稍等一下下~ ✨ |\n| 保存成功 | Saved | 已保存 | 保存成功！ | 太棒了，搞定！? |\n| 操作失败 | Failed | 操作失败 | 哎呀，出了点问题 | Oops！再试试？? |\n| 空状态 | No items | 暂无数据 | 这里空空如也 | 还没有内容呢~ ✨ |\n| 网络错误 | Offline | 网络连接失败 | 网络不太稳定 | 网络开小差了~ ? |\n\n#### 确认弹窗文案\n\n| 场景 | minimal | neutral | friendly | enthusiastic |\n|------|---------|---------|----------|--------------|\n| 删除标题 | Delete? | 确认删除 | 确定要删除吗？ | 真的要删掉吗？? |\n| 删除描述 | Cannot undo | 此操作不可撤销 | 删除后无法恢复哦 | 删掉就找不回来啦！ |\n| 确认按钮 | Delete | 确认删除 | 确定删除 | 删掉它！ |\n| 取消按钮 | Cancel | 取消 | 再想想 | 我再想想 |\n\n#### 欢迎\u002F问候\n\n| 场景 | minimal | neutral | friendly | enthusiastic |\n|------|---------|---------|----------|--------------|\n| 首次欢迎 | Welcome | 欢迎使用 | 欢迎来到这里！ | Hey！欢迎加入！? |\n| 回访问候 | — | 您好 | 欢迎回来！ | 好久不见！? |\n| 完成引导 | Done | 设置完成 | 准备就绪！ | 搞定！准备起飞！? |\n\n### 文案通用原则\n\n| 原则 | 说明 | 好例子 | 坏例子 |\n|------|------|--------|--------|\n| 像人说话 | 避免机器腔 | \"哎呀，出了点问题\" | \"Error: Operation failed\" |\n| 避免责怪 | 不让用户感到愚蠢 | \"请输入邮箱地址\" | \"邮箱格式错误！\" |\n| 提供出路 | 告诉用户怎么办 | \"网络不稳定，点击重试\" | \"网络错误\" |\n| 适度幽默 | 根据参数调整程度 | emotionalTone > 70 时可用 | 低参数时避免 |\n\n### Emoji 使用规则\n\n```typescript\nfunction shouldUseEmoji(emotionalTone: number): boolean {\n  return emotionalTone >= 60;  \u002F\u002F 60以上才使用emoji\n}\n\nfunction getEmojiIntensity(emotionalTone: number): 'none' | 'sparse' | 'frequent' {\n  if (emotionalTone \u003C 60) return 'none';\n  if (emotionalTone \u003C 80) return 'sparse';  \u002F\u002F 偶尔使用\n  return 'frequent';  \u002F\u002F 大方使用\n}\n```\n\n---\n\n## 响应式交互\n\n### 触摸优化\n\n```css\n\u002F* 触摸设备优化 *\u002F\n@media (hover: none) {\n  \u002F* 移除 hover 效果，避免粘滞 *\u002F\n  .button:hover {\n    background-color: initial;\n  }\n  \n  \u002F* 增大点击区域 *\u002F\n  .touch-target {\n    min-height: 44px;\n    min-width: 44px;\n  }\n}\n```\n\n### 手势支持\n\n| 手势 | 操作 |\n|------|------|\n| 点击 | 主要交互 |\n| 长按 | 显示上下文菜单 |\n| 左滑 | 删除\u002F归档（列表项） |\n| 下拉 | 刷新 |\n\n---\n\n## 可访问性\n\n### 键盘导航\n\n```html\n\u003C!-- 确保可聚焦 -->\n\u003Cbutton tabindex=\"0\">可聚焦按钮\u003C\u002Fbutton>\n\n\u003C!-- 跳过链接 -->\n\u003Ca href=\"#main\" class=\"sr-only focus:not-sr-only\">跳到主内容\u003C\u002Fa>\n```\n\n### 焦点样式\n\n```css\n\u002F* 清晰的焦点指示 *\u002F\n:focus-visible {\n  outline: 2px solid var(--primary-500);\n  outline-offset: 2px;\n}\n\n\u002F* 移除默认 outline，使用自定义样式 *\u002F\n:focus {\n  outline: none;\n}\n```\n\n### 屏幕阅读器\n\n```html\n\u003C!-- 仅屏幕阅读器可见 -->\n\u003Cspan class=\"sr-only\">关闭弹窗\u003C\u002Fspan>\n\n\u003C!-- 实时区域 -->\n\u003Cdiv aria-live=\"polite\" aria-atomic=\"true\">\n  \u003C!-- 动态内容会被朗读 -->\n\u003C\u002Fdiv>\n```\n\n---\n\n## 必加 Classes\n\n```tsx\n\"transition-all duration-200\"  \u002F\u002F 所有交互元素\n\"tabular-nums\"                 \u002F\u002F 数字对齐\n\"font-mono\"                    \u002F\u002F 地址\u002F哈希\u002F代码\n\"truncate\"                     \u002F\u002F 文本截断\n\"select-none\"                  \u002F\u002F 禁止选中（按钮等）\n\"cursor-pointer\"               \u002F\u002F 可点击元素\n```\n\n---\n\n## 设计检查清单\n\n应用 UX 模式后，最终检查：\n\n```\n视觉一致性：\n- [ ] 圆角统一 (卡片 2xl，按钮 xl，输入框 xl)\n- [ ] 间距遵循 8px 基准系统\n- [ ] 字号阶梯清晰 (最多 3-4 种)\n- [ ] 颜色使用克制 (主色 + 灰度)\n\n交互体验：\n- [ ] 所有可交互元素有 hover 状态\n- [ ] 过渡动画平滑 (150-300ms)\n- [ ] 焦点状态清晰可见\n- [ ] 加载状态有反馈\n\n留白与层次：\n- [ ] 组件间有足够呼吸感\n- [ ] 视觉层次不超过 3 级\n- [ ] 使用边框代替重阴影\n- [ ] 背景色使用浅灰而非纯白\n\n文案：\n- [ ] 文案简洁明了\n- [ ] 错误提示说人话\n- [ ] 空状态有引导\n```\n\n---\n\n## 人性化反馈设计\n\n### 超越\"成功\u002F失败\"\n\n传统反馈只告诉用户结果，人性化反馈关心用户的感受：\n\n| 场景 | 传统反馈 | 人性化反馈 |\n|------|---------|-----------|\n| 保存成功 | \"保存成功\" | \"已保存。你今天效率真高！\" |\n| 删除成功 | \"删除成功\" | \"已删除。需要的话可以在回收站找回\" |\n| 上传完成 | \"上传完成\" | \"上传完成！文件看起来不错 ?\" |\n| 首次操作 | \"操作成功\" | \"太棒了，这是你的第一个项目！?\" |\n| 连续操作 | \"保存成功\" | \"又搞定一个！保持这个节奏 ?\" |\n\n### 错误反馈的温度\n\n```\n冷冰冰（❌ 避免）：\n- \"Error 500: Internal Server Error\"\n- \"操作失败\"\n- \"请求超时\"\n\n有温度（✅ 推荐）：\n- \"服务器开了个小差，我们正在修复，请稍后再试\"\n- \"哎呀，这个操作没成功，再试一次？\"\n- \"网络有点慢，要不换个信号好的地方？\"\n```\n\n### 空状态的温暖\n\n```html\n\u003C!-- 冷冰冰 ❌ -->\n\u003Cdiv class=\"text-center text-gray-500\">\n  暂无数据\n\u003C\u002Fdiv>\n\n\u003C!-- 有温度 ✅ -->\n\u003Cdiv class=\"text-center py-12\">\n  \u003Cdiv class=\"text-6xl mb-4\">?\u003C\u002Fdiv>\n  \u003Ch3 class=\"text-lg font-medium text-gray-900 mb-2\">还没有任何笔记\u003C\u002Fh3>\n  \u003Cp class=\"text-sm text-gray-500 mb-6\">\n    写下你的第一个想法吧，好记性不如烂笔头\n  \u003C\u002Fp>\n  \u003Cbutton class=\"px-4 py-2 bg-primary text-white rounded-xl\">\n    创建笔记\n  \u003C\u002Fbutton>\n\u003C\u002Fdiv>\n```\n\n### 加载状态的趣味\n\n```html\n\u003C!-- 无聊 ❌ -->\n\u003Cdiv class=\"animate-spin w-8 h-8 border-2 border-gray-300 border-t-primary rounded-full\">\u003C\u002Fdiv>\n\n\u003C!-- 有趣 ✅ -->\n\u003Cdiv class=\"flex flex-col items-center gap-3\">\n  \u003Cdiv class=\"text-4xl animate-bounce\">?\u003C\u002Fdiv>\n  \u003Cp class=\"text-sm text-gray-500\">正在准备精彩内容...\u003C\u002Fp>\n\u003C\u002Fdiv>\n\n\u003C!-- 或者：进度文案变化 -->\n\u003Cdiv class=\"text-center\">\n  \u003Cdiv class=\"animate-pulse text-sm text-gray-500\">\n    \u003C!-- 随时间变化的文案 -->\n    \u003C!-- 0-2s: \"加载中...\" -->\n    \u003C!-- 2-5s: \"快好了...\" -->\n    \u003C!-- 5s+:  \"稍微有点慢，再等等...\" -->\n  \u003C\u002Fdiv>\n\u003C\u002Fdiv>\n```\n\n### 进度反馈的鼓励\n\n```tsx\nfunction ProgressFeedback({ progress }: { progress: number }) {\n  const getMessage = () => {\n    if (progress \u003C 25) return \"开始了！继续加油 ?\"\n    if (progress \u003C 50) return \"进展不错！\"\n    if (progress \u003C 75) return \"已经过半了！\"\n    if (progress \u003C 100) return \"马上就完成了！\"\n    return \"太棒了，完成了！?\"\n  }\n  \n  return (\n    \u003Cdiv>\n      \u003Cdiv className=\"flex justify-between text-sm mb-2\">\n        \u003Cspan>{getMessage()}\u003C\u002Fspan>\n        \u003Cspan className=\"font-medium\">{progress}%\u003C\u002Fspan>\n      \u003C\u002Fdiv>\n      \u003Cdiv className=\"h-2 bg-gray-100 rounded-full overflow-hidden\">\n        \u003Cdiv \n          className=\"h-full bg-primary rounded-full transition-all duration-500\"\n          style={{ width: `${progress}%` }}\n        \u002F>\n      \u003C\u002Fdiv>\n    \u003C\u002Fdiv>\n  )\n}\n```\n\n---\n\n## 设计检查清单（消除AI味）\n\n最终检查，确保设计有灵魂：\n\n```\n文案检查：\n- [ ] 文案像真人说的话吗？\n- [ ] 错误提示是否让人感到被关心而非被责怪？\n- [ ] 空状态是否温暖\u002F有趣？\n- [ ] 有没有在适当的地方使用 emoji？\n\n动效检查：\n- [ ] 动效是否有个性（不只是 ease-out 200ms）？\n- [ ] 重要操作是否有惊喜反馈？\n- [ ] 列表是否有错开加载效果？\n- [ ] 成功状态是否有庆祝感？\n\n情感检查：\n- [ ] 首次用户有没有特别的欢迎？\n- [ ] 里程碑时刻有没有庆祝？\n- [ ] 等待时是否不无聊？\n- [ ] 用户离开时有没有温暖的告别？\n```\n\n---\n\n## 参数使用示例\n\n### 完整工作流\n\n```typescript\n\u002F\u002F 1. 从 brand-personality 获取参数\nconst styleParams = {\n  emotionalTone: 65,\n  motionIntensity: 55\n};\n\n\u002F\u002F 2. 生成文案\nconst loadingCopy = getCopy('loading', styleParams.emotionalTone);\n\u002F\u002F → \"马上就好...\"\n\n\u002F\u002F 3. 生成动效参数\nconst motion = getMotionParams(styleParams.motionIntensity);\n\u002F\u002F → { duration: 311, easing: 'cubic-bezier(0.34, 1.56, 0.64, 1)', ... }\n\n\u002F\u002F 4. 确定惊喜级别\nconst delightLevel = getDelightLevel(styleParams.emotionalTone);\n\u002F\u002F → 'moderate'\n\n\u002F\u002F 5. 应用到组件\n\u003CButton\n  style={{ transition: `all ${motion.duration}ms ${motion.easing}` }}\n  onClick={() => {\n    \u002F\u002F 操作成功后\n    showToast(getCopy('saveSuccess', styleParams.emotionalTone));\n    if (delightLevel !== 'none') showSuccessAnimation(delightLevel);\n  }}\n>\n  {getCopy('save', styleParams.emotionalTone)}\n\u003C\u002FButton>\n```\n\n---\n\n## 相关技能\n\n- **brand-personality**: 提供 emotionalTone 和 motionIntensity 参数\n- **design-tokens**: 提供圆角、颜色等视觉令牌\n- **ui-components**: 使用本技能的文案和动效参数\n- **uiux-designer**: 统一调度入口\n",{"name":5,"description":7},"main","4a618da5d2528627c4728e9aab7d602f9d00b649","genes\u002Fux-patterns",1,"https:\u002F\u002Fgithub.com\u002Frotifer-protocol\u002Frotifer-playground","https:\u002F\u002Fgithub.com\u002Frotifer-protocol","https:\u002F\u002Frotifer.dev","Open-source evolution framework for AI agents","2026-11-12 02:04:26",{"source":8,"skillName":5,"commands":45,"prompt":55,"zipAvailable":56},[46,49,52],{"tool":47,"command":48},"npx","npx skills add rotifer-protocol\u002Frotifer-playground --skill ux-patterns",{"tool":50,"command":51},"bunx","bunx skills add rotifer-protocol\u002Frotifer-playground --skill ux-patterns",{"tool":53,"command":54},"pnpm","pnpm dlx skills add rotifer-protocol\u002Frotifer-playground --skill ux-patterns","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Frotifer-protocol\u002Frotifer-playground\u002Fblob\u002Fmain\u002Fgenes\u002Fux-patterns\u002FSKILL.md",true,[58,64,68],{"path":59,"resourceType":60,"resourceTypeDesc":61,"sizeBytes":62,"sourceHtmlUrl":63},".cloud-manifest.json","REFERENCE","参考文档",156,"https:\u002F\u002Fgithub.com\u002Frotifer-protocol\u002Frotifer-playground\u002Fblob\u002Fmain\u002Fgenes\u002Fux-patterns\u002F.cloud-manifest.json",{"path":65,"resourceType":60,"resourceTypeDesc":61,"sizeBytes":66,"sourceHtmlUrl":67},".gene-manifest.json",263,"https:\u002F\u002Fgithub.com\u002Frotifer-protocol\u002Frotifer-playground\u002Fblob\u002Fmain\u002Fgenes\u002Fux-patterns\u002F.gene-manifest.json",{"path":69,"resourceType":60,"resourceTypeDesc":61,"sizeBytes":70,"sourceHtmlUrl":71},"phenotype.json",2959,"https:\u002F\u002Fgithub.com\u002Frotifer-protocol\u002Frotifer-playground\u002Fblob\u002Fmain\u002Fgenes\u002Fux-patterns\u002Fphenotype.json",[73,92,120,150,173,193],{"skillNo":74,"name":75,"nameZh":6,"description":76,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":77,"categories":78,"keywords":84,"publishedAt":30},"01M6H8FTYPK400JGQDW57GM49R","fixture-skill","A synthetic ClawHub skill for wrap --from-clawhub tests","https:\u002F\u002Fgithub.com\u002Frotifer-protocol\u002Frotifer-playground\u002Fblob\u002Fmain\u002Ftests\u002Ffixtures\u002Fclawhub\u002Ffixture-skill\u002FSKILL.md",[79],{"categoryNo":80,"categoryName":81,"taxonomyType":82,"taxonomyTypeDesc":83},"01JBSEEDCAT000000000000023","Skill与智能体开发","SCENARIO","使用场景",[85,86,87,88,89,90,91],"fixture","fixture skill","wrap","tests","clawhub","for","synthetic",{"skillNo":93,"name":94,"nameZh":6,"description":95,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":96,"categories":97,"keywords":99,"publishedAt":30},"01M6H8FPX91FF5FH8PPEW7HQSZ","rotifer-self-evolving-agent","Rank an Agent's Rotifer Genes against the Arena and swap in stronger ones. Invoked explicitly via \u002Fevolve — scan local capabilities, compare Genes, inspect fitness scores, and replace weak ones with user approval. Not for capabilities outside Rotifer.","https:\u002F\u002Fgithub.com\u002Frotifer-protocol\u002Frotifer-playground\u002Fblob\u002Fmain\u002Fskills\u002Frotifer-self-evolving-agent\u002FSKILL.md",[98],{"categoryNo":80,"categoryName":81,"taxonomyType":82,"taxonomyTypeDesc":83},[100,101,102,103,104,105,106,107,108,109,110,111,112,113,90,114,47,115,116,117,118,119],"rotifer self evolving agent","self","self evolving","inspect","local","MCP","access","capabilities","server","run","gene","evolve","network","arena","scan","compare","swap","with","mcp-server","fitness",{"skillNo":121,"name":122,"nameZh":6,"description":123,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":124,"categories":125,"keywords":129,"publishedAt":30},"01M6H8FGNKE933Q2JAAB7JY43V","rotifer-guide","Entry point for Rotifer Protocol — onboarding to Rotifer Genes, scaffolding a Gene from a description, diagnosing a Gene's F(g) or compile failure, searching the Rotifer Gene registry, and upgrading a Gene's fidelity from Wrapped to Native. Invoke explicitly when starting with Rotifer, or when unsure which Rotifer capability to use. Do NOT use for general onboarding, tutorials, troubleshooting, or search — every capability here operates on Rotifer Genes and the Rotifer CLI, and nothing else.","https:\u002F\u002Fgithub.com\u002Frotifer-protocol\u002Frotifer-playground\u002Fblob\u002Fmain\u002Fskills\u002Frotifer-guide\u002FSKILL.md",[126],{"categoryNo":127,"categoryName":128,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000038","人力资源",[130,131,132,133,134,135,136,110,137,138,90,139,140,141,117,142,143,144,145,146,147,148,149],"rotifer guide","guide","which","scaffolding","search","cli","native","registry","do","compile","general","use","protocol","troubleshooting","onboarding","rotifer gene","invoke","when","capability","point",{"skillNo":151,"name":152,"nameZh":6,"description":153,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":154,"categories":155,"keywords":159,"publishedAt":30},"01M6H8FBXGQM2RH27G0S6XMQ34","rotifer-gene","The Gene manual for Rotifer Protocol — write a Gene's express function and phenotype schema, run the four-layer security audit before publishing, and migrate a Gene's fidelity from Wrapped to Hybrid or Native. Invoke explicitly when building, auditing, or upgrading a Rotifer Gene. Do NOT use for general code review, dependency auditing, or framework migration — every procedure here operates on Rotifer Genes, their phenotype schemas, and the Rotifer CLI, and nothing else.","https:\u002F\u002Fgithub.com\u002Frotifer-protocol\u002Frotifer-playground\u002Fblob\u002Fmain\u002Fskills\u002Frotifer-gene\u002FSKILL.md",[156],{"categoryNo":157,"categoryName":158,"taxonomyType":82,"taxonomyTypeDesc":83},"01JBSEEDCAT000000000000007","代码审查",[145,110,138,113,160,90,161,162,140,163,164,165,47,141,106,166,167,168,169,170,171,172,146,147],"security audit","code review","manual","publishing","yes","schema","version","migrate","code","express","review","hybrid","submission",{"skillNo":174,"name":175,"nameZh":6,"description":176,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":177,"categories":178,"keywords":180,"publishedAt":30},"01M6H8F7DZPN54N2AQC32BWEKV","rotifer-arena","Benchmark Rotifer Genes against each other in the Arena — import from ClawHub \u002F local \u002F scratch, compile, match opponents, run Arena evaluation, and produce a Markdown report with F(g) fitness and V(g) security grades. Invoke explicitly to compare or benchmark Rotifer Genes. Do NOT use for general benchmarking, load testing, or comparing anything that is not a Rotifer Gene or Agent.","https:\u002F\u002Fgithub.com\u002Frotifer-protocol\u002Frotifer-playground\u002Fblob\u002Fmain\u002Fskills\u002Frotifer-arena\u002FSKILL.md",[179],{"categoryNo":80,"categoryName":81,"taxonomyType":82,"taxonomyTypeDesc":83},[181,113,138,182,90,139,183,104,140,89,184,141,185,115,117,186,187,188,109,110,145,146,189,190,119,191,192],"rotifer arena","import","testing","produce","load","benchmarking","load testing","markdown","Evaluation","benchmark","security","scratch",{"skillNo":194,"name":195,"nameZh":6,"description":196,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":197,"categories":198,"keywords":200,"publishedAt":30},"01M6H8F0WWXMTDWXQMQYC3PGPW","rotifer-agent","Build a Rotifer Agent from Genes — decompose intent into capability units, pick Genes by Arena F(g), compose a Rotifer Genome, create the Agent and test it. Use when the user is working with Rotifer specifically: \"Rotifer Agent\", \"compose Genes\", \"Rotifer Genome\", \"Gene composition\", \"rotifer agent create\". Do NOT use for general agent frameworks, or when the words Seq \u002F Par \u002F Cond \u002F Try appear as ordinary programming terms — in Rotifer those name Genome composition strategies, and this Skill applies only when the user is composing Rotifer Genes.","https:\u002F\u002Fgithub.com\u002Frotifer-protocol\u002Frotifer-playground\u002Fblob\u002Fmain\u002Fskills\u002Frotifer-agent\u002FSKILL.md",[199],{"categoryNo":80,"categoryName":81,"taxonomyType":82,"taxonomyTypeDesc":83},[201,202,203,204,205,206,207,110,208,209,210,138,113,211,90,212,140,141,213,117,147,214,148],"rotifer agent","Composition","pick","only","create","strategies","intent","seq","decompose","as","compose","frameworks","programming","agent frameworks"]