@leejungkiin/awkit 1.7.0 → 1.7.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (241) hide show
  1. package/bin/awk.js +576 -84
  2. package/core/CLAUDE.md +1 -1
  3. package/core/GEMINI.md +148 -167
  4. package/core/GEMINI.md.bak +149 -116
  5. package/core/skill-runtime-manifest.json +3 -0
  6. package/docs/Claude Fable 5.md +3826 -0
  7. package/docs/android_kotlin_system_instruction.md +210 -0
  8. package/docs/brainstorm_ponytail_integration.md +146 -0
  9. package/docs/brainstorm_smart_setup.md +113 -0
  10. package/docs/deep-research-report (1).md +293 -0
  11. package/docs/history/GEMINI.v1.md +135 -0
  12. package/docs/history/brainstorm_antigravity_unified_architecture.v1.md +105 -0
  13. package/docs/history/implementation_plan.v1.md +58 -0
  14. package/package.json +4 -1
  15. package/scripts/artifact-storage.js +130 -0
  16. package/scripts/automation-gate.js +40 -7
  17. package/scripts/claude-plan.js +76 -0
  18. package/scripts/dependency-manager.js +210 -0
  19. package/scripts/exec-rtk.js +11 -5
  20. package/scripts/i18n-helper.js +381 -0
  21. package/scripts/multi-model-pipeline.js +144 -0
  22. package/skill-packs/mobile-ios/pack.json +4 -2
  23. package/skill-packs/reverse-engineering/pack.json +1 -0
  24. package/skills/CATALOG.md +20 -0
  25. package/skills/GEMINI.md +9 -1
  26. package/skills/TRIGGER_INDEX.md +10 -0
  27. package/skills/ai-music/SKILL.md +275 -0
  28. package/skills/android-re-analyzer/SKILL.md +238 -0
  29. package/skills/android-re-analyzer/references/api-extraction-patterns.md +119 -0
  30. package/skills/android-re-analyzer/references/call-flow-analysis.md +176 -0
  31. package/skills/android-re-analyzer/references/fernflower-usage.md +115 -0
  32. package/skills/android-re-analyzer/references/jadx-usage.md +116 -0
  33. package/skills/android-re-analyzer/references/setup-guide.md +221 -0
  34. package/skills/android-re-analyzer/scripts/check-deps.sh +129 -0
  35. package/skills/android-re-analyzer/scripts/decompile.sh +375 -0
  36. package/skills/android-re-analyzer/scripts/find-api-calls.sh +118 -0
  37. package/skills/android-re-analyzer/scripts/install-dep.sh +448 -0
  38. package/skills/animal-island-ui-style/SKILL.md +1450 -0
  39. package/skills/app-store-review-agent/SKILL.md +164 -0
  40. package/skills/app-store-review-agent/references/guidelines/README.md +154 -0
  41. package/skills/app-store-review-agent/references/guidelines/by-app-type/ai_apps.md +37 -0
  42. package/skills/app-store-review-agent/references/guidelines/by-app-type/all_apps.md +50 -0
  43. package/skills/app-store-review-agent/references/guidelines/by-app-type/crypto_finance.md +31 -0
  44. package/skills/app-store-review-agent/references/guidelines/by-app-type/games.md +31 -0
  45. package/skills/app-store-review-agent/references/guidelines/by-app-type/health_fitness.md +31 -0
  46. package/skills/app-store-review-agent/references/guidelines/by-app-type/kids.md +27 -0
  47. package/skills/app-store-review-agent/references/guidelines/by-app-type/macos.md +38 -0
  48. package/skills/app-store-review-agent/references/guidelines/by-app-type/social_ugc.md +32 -0
  49. package/skills/app-store-review-agent/references/guidelines/by-app-type/subscription_iap.md +34 -0
  50. package/skills/app-store-review-agent/references/guidelines/by-app-type/vpn.md +18 -0
  51. package/skills/app-store-review-agent/references/rules/design/minimum_functionality.md +96 -0
  52. package/skills/app-store-review-agent/references/rules/design/sign_in_with_apple.md +54 -0
  53. package/skills/app-store-review-agent/references/rules/entitlements/unused_entitlements.md +83 -0
  54. package/skills/app-store-review-agent/references/rules/metadata/accurate_metadata.md +54 -0
  55. package/skills/app-store-review-agent/references/rules/metadata/apple_trademark.md +99 -0
  56. package/skills/app-store-review-agent/references/rules/metadata/china_storefront.md +72 -0
  57. package/skills/app-store-review-agent/references/rules/metadata/competitor_terms.md +56 -0
  58. package/skills/app-store-review-agent/references/rules/metadata/subscription_metadata.md +81 -0
  59. package/skills/app-store-review-agent/references/rules/privacy/privacy_manifest.md +84 -0
  60. package/skills/app-store-review-agent/references/rules/privacy/unnecessary_data.md +60 -0
  61. package/skills/app-store-review-agent/references/rules/subscription/misleading_pricing.md +63 -0
  62. package/skills/app-store-review-agent/references/rules/subscription/missing_tos_pp.md +54 -0
  63. package/skills/awf-ponytail/SKILL.md +91 -0
  64. package/skills/awf-ponytail-review/SKILL.md +67 -0
  65. package/skills/awf-session-restore/SKILL.md +3 -3
  66. package/skills/brainstorm-agent/SKILL.md +11 -2
  67. package/skills/brainstorm-agent/templates/brief-template.md +8 -0
  68. package/skills/claude-planner/SKILL.md +47 -0
  69. package/skills/code-review/SKILL.md +87 -0
  70. package/skills/expo-game-development/SKILL.md +163 -0
  71. package/skills/flutter/LICENSE.txt +202 -0
  72. package/skills/flutter/SKILL.md +127 -0
  73. package/skills/flutter-project-creater/LICENSE.txt +202 -0
  74. package/skills/flutter-project-creater/SKILL.md +106 -0
  75. package/skills/game-developer/SKILL.md +163 -0
  76. package/skills/game-developer/references/ecs-patterns.md +501 -0
  77. package/skills/game-developer/references/multiplayer-networking.md +475 -0
  78. package/skills/game-developer/references/performance-optimization.md +422 -0
  79. package/skills/game-developer/references/unity-patterns.md +271 -0
  80. package/skills/game-developer/references/unreal-cpp.md +352 -0
  81. package/skills/generate-gui-assets/SKILL.md +305 -0
  82. package/skills/generate-gui-assets/agents/openai.yaml +4 -0
  83. package/skills/generate-gui-assets/references/catalog-schema.md +58 -0
  84. package/skills/generate-gui-assets/references/extraction-techniques.md +21 -0
  85. package/skills/generate-gui-assets/references/prompt-patterns.md +58 -0
  86. package/skills/generate-gui-assets/scripts/__pycache__/clean_chroma_edges.cpython-311.pyc +0 -0
  87. package/skills/generate-gui-assets/scripts/build_gui_contact_sheet.py +51 -0
  88. package/skills/generate-gui-assets/scripts/clean_chroma_edges.py +262 -0
  89. package/skills/generate-gui-assets/scripts/copy_approved_icons.py +64 -0
  90. package/skills/generate-gui-assets/scripts/prepare_gui_asset_run.py +91 -0
  91. package/skills/generate-gui-assets/scripts/suggest_grid_options.py +63 -0
  92. package/skills/generate-gui-assets/scripts/validate_gui_catalog.py +50 -0
  93. package/skills/godot-game-development/SKILL.md +142 -0
  94. package/skills/hatch-pet/LICENSE.txt +201 -0
  95. package/skills/hatch-pet/SKILL.md +420 -0
  96. package/skills/hatch-pet/agents/openai.yaml +4 -0
  97. package/skills/hatch-pet/references/animation-rows.md +29 -0
  98. package/skills/hatch-pet/references/codex-pet-contract.md +35 -0
  99. package/skills/hatch-pet/references/qa-rubric.md +60 -0
  100. package/skills/hatch-pet/scripts/__pycache__/clean_chroma_edges.cpython-311.pyc +0 -0
  101. package/skills/hatch-pet/scripts/clean_chroma_edges.py +262 -0
  102. package/skills/hatch-pet/scripts/compose_atlas.py +150 -0
  103. package/skills/hatch-pet/scripts/derive_running_left_from_running_right.py +143 -0
  104. package/skills/hatch-pet/scripts/extract_strip_frames.py +323 -0
  105. package/skills/hatch-pet/scripts/finalize_pet_run.py +382 -0
  106. package/skills/hatch-pet/scripts/generate_pet_images.py +287 -0
  107. package/skills/hatch-pet/scripts/inspect_frames.py +246 -0
  108. package/skills/hatch-pet/scripts/make_contact_sheet.py +96 -0
  109. package/skills/hatch-pet/scripts/package_custom_pet.py +108 -0
  110. package/skills/hatch-pet/scripts/pet_job_status.py +117 -0
  111. package/skills/hatch-pet/scripts/prepare_pet_run.py +673 -0
  112. package/skills/hatch-pet/scripts/queue_pet_repairs.py +172 -0
  113. package/skills/hatch-pet/scripts/record_imagegen_result.py +250 -0
  114. package/skills/hatch-pet/scripts/render_animation_videos.py +134 -0
  115. package/skills/hatch-pet/scripts/render_animation_videos.sh +5 -0
  116. package/skills/hatch-pet/scripts/validate_atlas.py +139 -0
  117. package/skills/i18n-orchestrator/SKILL.md +37 -0
  118. package/skills/ios-simulator-skill/SKILL.md +390 -0
  119. package/skills/ios-simulator-skill/scripts/accessibility_audit.py +300 -0
  120. package/skills/ios-simulator-skill/scripts/app_launcher.py +326 -0
  121. package/skills/ios-simulator-skill/scripts/app_state_capture.py +400 -0
  122. package/skills/ios-simulator-skill/scripts/appearance.py +385 -0
  123. package/skills/ios-simulator-skill/scripts/build_and_test.py +348 -0
  124. package/skills/ios-simulator-skill/scripts/clipboard.py +103 -0
  125. package/skills/ios-simulator-skill/scripts/common/__init__.py +61 -0
  126. package/skills/ios-simulator-skill/scripts/common/cache_utils.py +289 -0
  127. package/skills/ios-simulator-skill/scripts/common/device_utils.py +462 -0
  128. package/skills/ios-simulator-skill/scripts/common/env_config.py +35 -0
  129. package/skills/ios-simulator-skill/scripts/common/hang_pipeline.py +862 -0
  130. package/skills/ios-simulator-skill/scripts/common/hang_sessions.py +490 -0
  131. package/skills/ios-simulator-skill/scripts/common/idb_utils.py +180 -0
  132. package/skills/ios-simulator-skill/scripts/common/screenshot_utils.py +338 -0
  133. package/skills/ios-simulator-skill/scripts/container.py +668 -0
  134. package/skills/ios-simulator-skill/scripts/gesture.py +394 -0
  135. package/skills/ios-simulator-skill/scripts/hang_watcher.py +1533 -0
  136. package/skills/ios-simulator-skill/scripts/keyboard.py +391 -0
  137. package/skills/ios-simulator-skill/scripts/localization_audit.py +483 -0
  138. package/skills/ios-simulator-skill/scripts/location.py +467 -0
  139. package/skills/ios-simulator-skill/scripts/log_monitor.py +493 -0
  140. package/skills/ios-simulator-skill/scripts/model_inspector.py +645 -0
  141. package/skills/ios-simulator-skill/scripts/navigator.py +461 -0
  142. package/skills/ios-simulator-skill/scripts/privacy_manager.py +310 -0
  143. package/skills/ios-simulator-skill/scripts/push_notification.py +240 -0
  144. package/skills/ios-simulator-skill/scripts/screen_mapper.py +296 -0
  145. package/skills/ios-simulator-skill/scripts/sim_health_check.sh +245 -0
  146. package/skills/ios-simulator-skill/scripts/sim_list.py +299 -0
  147. package/skills/ios-simulator-skill/scripts/simctl_boot.py +312 -0
  148. package/skills/ios-simulator-skill/scripts/simctl_create.py +316 -0
  149. package/skills/ios-simulator-skill/scripts/simctl_delete.py +357 -0
  150. package/skills/ios-simulator-skill/scripts/simctl_erase.py +351 -0
  151. package/skills/ios-simulator-skill/scripts/simctl_shutdown.py +290 -0
  152. package/skills/ios-simulator-skill/scripts/simulator_selector.py +375 -0
  153. package/skills/ios-simulator-skill/scripts/status_bar.py +250 -0
  154. package/skills/ios-simulator-skill/scripts/test_recorder.py +323 -0
  155. package/skills/ios-simulator-skill/scripts/visual_diff.py +235 -0
  156. package/skills/ios-simulator-skill/scripts/xcode/__init__.py +13 -0
  157. package/skills/ios-simulator-skill/scripts/xcode/builder.py +397 -0
  158. package/skills/ios-simulator-skill/scripts/xcode/cache.py +204 -0
  159. package/skills/ios-simulator-skill/scripts/xcode/config.py +178 -0
  160. package/skills/ios-simulator-skill/scripts/xcode/reporter.py +343 -0
  161. package/skills/ios-simulator-skill/scripts/xcode/xcresult.py +451 -0
  162. package/skills/ios-visual-qa-strategist/SKILL.md +111 -0
  163. package/skills/ios-visual-qa-strategist/agents/openai.yaml +4 -0
  164. package/skills/ios-visual-qa-strategist/references/ios-tool-selection.md +61 -0
  165. package/skills/ios-visual-qa-strategist/references/minimal-capture-policy.md +56 -0
  166. package/skills/ios-visual-qa-strategist/references/visual-reasoning-heuristics.md +53 -0
  167. package/skills/orchestrator/SKILL.md +0 -20
  168. package/skills/persistent-storage/SKILL.md +55 -0
  169. package/skills/short-maker/SKILL.md +23 -0
  170. package/skills/short-maker/scripts/effects.js +56 -0
  171. package/skills/short-maker/scripts/shortmaker-bridge.js +332 -0
  172. package/skills/short-maker/scripts/videomix.js +601 -0
  173. package/skills/short-maker/templates/hyperframes/cinematic-character.template.html +172 -0
  174. package/skills/short-maker/templates/hyperframes/index.template.html +194 -0
  175. package/skills/smali-to-kotlin/SKILL.md +128 -0
  176. package/skills/smali-to-kotlin/examples/getting-started/tech-stack.md +58 -0
  177. package/skills/smali-to-kotlin/examples/pipeline/data-ui-parity.md +118 -0
  178. package/skills/smali-to-kotlin/examples/pipeline/scanner-and-bootstrap.md +106 -0
  179. package/skills/smali-to-kotlin/library-patterns.md +189 -0
  180. package/skills/smali-to-kotlin/phase-0-discovery.md +128 -0
  181. package/skills/smali-to-kotlin/phase-1-architecture.md +166 -0
  182. package/skills/smali-to-kotlin/phase-2-blueprint-ui.md +347 -0
  183. package/skills/smali-to-kotlin/phase-2-blueprint.md +228 -0
  184. package/skills/smali-to-kotlin/phase-3-build.md +248 -0
  185. package/skills/smali-to-kotlin/phase-3-logic-build.md +268 -0
  186. package/skills/smali-to-kotlin/smali-reading-guide.md +310 -0
  187. package/skills/smali-to-kotlin/templates/app-map.md +101 -0
  188. package/skills/smali-to-kotlin/templates/architecture.md +142 -0
  189. package/skills/smali-to-kotlin/templates/blueprint.md +145 -0
  190. package/skills/spec-gate/SKILL.md +6 -2
  191. package/skills/symphony-enforcer/SKILL.md +8 -0
  192. package/skills/symphony-enforcer/examples/mindful-stop.md +2 -0
  193. package/skills/symphony-enforcer/examples/three-phase.md +16 -0
  194. package/skills/symphony-enforcer/examples/trigger-points.md +7 -1
  195. package/skills/unity-game-development/SKILL.md +231 -0
  196. package/skills/verification-gate/SKILL.md +4 -2
  197. package/skills/video-edit/SKILL.md +36 -0
  198. package/skills/video-edit/scripts/video_edit.py +324 -0
  199. package/templates/setup-mapping.json +48 -0
  200. package/templates/specs/design-template.md +161 -71
  201. package/templates/specs/requirements-template.md +65 -133
  202. package/templates/specs/task-spec-template.xml +3 -0
  203. package/workflows/_uncategorized/critic.md +40 -0
  204. package/workflows/_uncategorized/git-rebase-flow.md +81 -0
  205. package/workflows/_uncategorized/image-gen.md +118 -0
  206. package/workflows/_uncategorized/multi-model-pipeline.md +60 -0
  207. package/workflows/_uncategorized/pixel-gen.md +86 -0
  208. package/workflows/_uncategorized/pixel-setup.md +90 -0
  209. package/workflows/_uncategorized/ponytail-review.md +59 -0
  210. package/workflows/_uncategorized/reverse-android-build.md +222 -0
  211. package/workflows/_uncategorized/reverse-android-design.md +139 -0
  212. package/workflows/_uncategorized/reverse-android-discover.md +150 -0
  213. package/workflows/_uncategorized/reverse-android-scan.md +158 -0
  214. package/workflows/_uncategorized/reverse-android.md +143 -0
  215. package/workflows/_uncategorized/reverse-ios-build.md +240 -0
  216. package/workflows/_uncategorized/reverse-ios-design.md +112 -0
  217. package/workflows/_uncategorized/reverse-ios-discover.md +120 -0
  218. package/workflows/_uncategorized/reverse-ios-scan.md +155 -0
  219. package/workflows/_uncategorized/reverse-ios.md +152 -0
  220. package/workflows/_uncategorized/safety-router.md +34 -0
  221. package/workflows/_uncategorized/teach.md +89 -0
  222. package/workflows/_uncategorized/verify-ui.md +53 -0
  223. package/workflows/_uncategorized/visualize-screenshots.md +34 -0
  224. package/workflows/ads/ads-analyst.md +201 -0
  225. package/workflows/ads/ads-audit.md +106 -0
  226. package/workflows/ads/ads-optimize.md +97 -0
  227. package/workflows/ads/ads-targeting.md +241 -0
  228. package/workflows/ads/adsExpert.md +160 -0
  229. package/workflows/ads/smali-ads-config.md +400 -0
  230. package/workflows/ads/smali-ads-flow.md +331 -0
  231. package/workflows/ads/smali-ads-interstitial.md +377 -0
  232. package/workflows/ads/smali-ads-native.md +382 -0
  233. package/workflows/context/teach.md +89 -0
  234. package/workflows/gitnexus.md +8 -8
  235. package/workflows/lifecycle/brainstorm.md +43 -0
  236. package/workflows/lifecycle/code.md +5 -0
  237. package/workflows/lifecycle/init.md +23 -5
  238. package/workflows/lifecycle/multi-model-pipeline.md +60 -0
  239. package/workflows/quality/ponytail-review.md +59 -0
  240. package/workflows/roles/critic.md +40 -0
  241. package/workflows/roles/safety-router.md +34 -0
@@ -0,0 +1,1450 @@
1
+ ---
2
+ name: animal-island-ui-style
3
+ description: >
4
+ 使用 animal-island-ui 设计风格创建 React UI 界面或组件。当用户需要:
5
+ (1) 用动物森友会风格创建 UI 页面或组件;
6
+ (2) 使用 animal-island-ui 组件库开发界面;
7
+ (3) 构建温馨自然、圆润可爱风格的 React 界面;
8
+ (4) 复现或扩展 animal-island-ui 的视觉语言;
9
+ (5) 提问"动物森友会风格"、"animal island 风格"、"可爱圆润风格"的 UI 时,务必使用此 skill。
10
+ ---
11
+
12
+ # Animal Island UI 设计风格指南
13
+
14
+ > **三文档分工**(生成代码 / 调样式时按需查阅,避免互相翻查):
15
+ > - `AI_USAGE.md` — API 手册:每个组件的 props、类型、默认值、合法取值、禁用用法。**写代码优先查这里**。
16
+ > - `skill/SKILL.md`(本文档)— 像素级样式:设计 token、每组件精确 CSS(hex/px/keyframe)、Demo 布局、新组件开发模板。**要自己实现/扩展样式时查这里**。
17
+ > - `DESIGN_PROMPT.md` — 给外部工具(v0 / Figma AI / Midjourney / DALL-E)的提示词包,含 clip-path、色板速查、禁用清单。**只在喂别的 AI 时用**。
18
+
19
+ ## 概述
20
+
21
+ animal-island-ui 是一套受《集合啦!动物森友会》启发的 React + TypeScript UI 组件库。
22
+ 设计语言核心:**温暖大地色系 + 大圆角 pill 形 + 游戏按键立体感 + 柔和动效 + 有机不规则形状**。
23
+
24
+ - 源码:`src/components/<ComponentName>/`
25
+ - Demo 站:`demo/`
26
+ - 构建:Vite (library mode) + `vite.config.ts`(库)/ `vite.config.demo.ts`(Demo)
27
+ - 样式系统:Less Modules + `src/styles/variables.less` 设计 token
28
+
29
+ ### 全量组件清单(17 个)
30
+
31
+ 从 `src/index.ts` 导出:
32
+
33
+ | 组件 | 职责 | 交互 | 装饰 / 纯展示 |
34
+ |---|---|---|---|
35
+ | `Button` | 按钮,5 种类型 × 3 种尺寸 | ✓ | |
36
+ | `Input` | 输入框,3 种尺寸 + clear/prefix/suffix | ✓ | |
37
+ | `Switch` | 开关,默认/小号 | ✓ | |
38
+ | `Modal` | SVG blob 裁切弹窗 | ✓ | |
39
+ | `Card` | 容器,`default`/`title`,13 种 NookPhone 配色 | | ✓ |
40
+ | `Collapse` | 手风琴(CSS Grid,无 JS 过渡) | ✓ | |
41
+ | `Select` | 下拉选择器(受控) | ✓ | |
42
+ | `Checkbox` | 多选框组,水平/垂直,3 种尺寸 | ✓ | |
43
+ | `Icon` | SVG 图标库(10 个) | | ✓ |
44
+ | `Time` | HUD 实时时钟 | | ✓ |
45
+ | `Phone` | NookPhone 3×3 应用网格 | | ✓ |
46
+ | `Footer` | 底部装饰图(`sea`/`tree`) | | ✓ |
47
+ | `Divider` | 装饰分割线,5 种风格 | | ✓ |
48
+ | `Cursor` | 游戏手指光标包裹器 | | ✓ |
49
+ | `Typewriter` | 打字机效果,保留 ReactNode 结构 | | ✓ |
50
+ | `Tabs` | 标签页切换,叶子摆动动画可选 | ✓ | |
51
+ | `CodeBlock` | JSX/TS 语法高亮代码块 | | ✓ |
52
+
53
+ 类型导出:`ButtonProps/ButtonType/ButtonSize`、`InputProps/InputSize`、`SwitchProps/SwitchSize`、`ModalProps`、`CardProps/CardType/CardColor`、`FooterProps/FooterType`、`CollapseProps`、`CursorProps`、`TimeProps`、`PhoneProps`、`DividerProps`、`TypewriterProps`、`SelectProps/SelectOption`、`IconProps/IconName`、`TabsProps/TabItem`、`CheckboxProps/CheckboxOption/CheckboxSize`、`CodeBlockProps`。运行时值:`ICON_LIST`。
54
+
55
+ ---
56
+
57
+ ## 1. Design Tokens
58
+
59
+ ### 色彩系统
60
+
61
+ ```less
62
+ // 主色(薄荷青绿)
63
+ @primary-color: #19c8b9;
64
+ @primary-color-hover: #3dd4c6;
65
+ @primary-color-active: #11a89b;
66
+ @primary-color-bg: #e6f9f6;
67
+
68
+ // 文字(温暖棕色系)
69
+ @text-color: #794f27; // 主文字(header/sidebar)
70
+ @text-color-body: #725d42; // 正文(组件内文字)
71
+ @text-color-secondary: #9f927d; // 次级文字
72
+ @text-color-muted: #8a7b66; // 浅棕(modal body)
73
+ @text-color-disabled: #c4b89e; // 禁用
74
+
75
+ // 边框
76
+ @border-color: #9f927d;
77
+ @border-color-light: #c4b89e; // 输入框边框
78
+ @border-color-hover: #a89878; // 输入框 hover
79
+
80
+ // 背景(奶油米白)
81
+ @bg-color: #f8f8f0; // 主背景
82
+ @bg-color-content: rgb(247, 243, 223); // 内容区(Modal、Card)
83
+ @bg-color-secondary: #f0e8d8;
84
+ @bg-color-disabled: #f0ece2;
85
+ @bg-color-input: rgb(247, 243, 223); // 输入框背景
86
+ @bg-color-input-dis: #ece8dc; // 输入框禁用
87
+
88
+ // 状态色
89
+ @success-color: #6fba2c;
90
+ @success-color-active: #5a9e1e;
91
+ @warning-color: #f5c31c;
92
+ @warning-color-active: #dba90e;
93
+ @error-color: #e05a5a;
94
+ @error-color-active: #c94444;
95
+
96
+ // 游戏特殊色
97
+ @focus-yellow: #ffcc00; // 焦点高亮(非蓝色)
98
+ @focus-yellow-dark: #e0b800; // 焦点阴影
99
+ @sidebar-active-bg: #B7C6E5; // 侧边栏选中背景
100
+ @sidebar-hover-bg: #d6dff0; // 侧边栏 hover 背景
101
+
102
+ // 3D 阴影色
103
+ @shadow-btn: #bdaea0; // 按钮 3D 阴影
104
+ @shadow-input: #d4c9b4; // 输入框 3D 阴影
105
+ @shadow-switch-on: #5a9e1e; // Switch 开启 3D 阴影
106
+ ```
107
+
108
+ **NookPhone 应用调色板**(Card `color` prop 可选值):
109
+
110
+ | color 值 | 背景色 | 文字色 |
111
+ |---|---|---|
112
+ | default | `rgb(247, 243, 223)` | `#725d42` |
113
+ | app-pink | `#f8a6b2` | `#fff` |
114
+ | purple | `#b77dee` | `#fff` |
115
+ | app-blue | `#889df0` | `#fff` |
116
+ | app-yellow | `#f7cd67` | `#725d42` |
117
+ | app-orange | `#e59266` | `#fff` |
118
+ | app-teal | `#82d5bb` | `#fff` |
119
+ | app-green | `#8ac68a` | `#fff` |
120
+ | app-red | `#fc736d` | `#fff` |
121
+ | lime-green | `#d1da49` | `#3d5a1a` |
122
+ | yellow-green | `#ecdf52` | `#725d42` |
123
+ | brown | `#9a835a` | `#fff` |
124
+ | warm-peach-pink | `#e18c6f` | `#fff` |
125
+
126
+ ---
127
+
128
+ ### 字体
129
+
130
+ 项目使用三款 Google Fonts 圆体字,**必须**按以下方式引入,本地未安装时通过在线地址加载:
131
+
132
+ ```html
133
+ <!-- 在 index.html <head> 中引入 -->
134
+ <link rel="preconnect" href="https://fonts.googleapis.com" />
135
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
136
+ <link
137
+ href="https://fonts.googleapis.com/css2?family=Nunito:wght@400;500;600;700;800;900&family=Zen+Maru+Gothic:wght@400;500;700&family=M+PLUS+Rounded+1c:wght@400;500;700&display=swap"
138
+ rel="stylesheet"
139
+ />
140
+ ```
141
+
142
+ 或在 CSS / Less 入口文件顶部:
143
+
144
+ ```css
145
+ @import url('https://fonts.googleapis.com/css2?family=Nunito:wght@400;500;600;700;800;900&family=Noto+Sans+SC:wght@400;500;700&family=Zen+Maru+Gothic:wght@400;500;700&display=swap');
146
+ ```
147
+
148
+ ```css
149
+ font-family: Nunito, 'Noto Sans SC', 'Zen Maru Gothic',
150
+ -apple-system, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', sans-serif;
151
+ ```
152
+
153
+ | 字体 | 用途 | Google Fonts key |
154
+ |---|---|---|
155
+ | **Nunito** | 主字体,拉丁字符 | `family=Nunito` |
156
+ | **Noto Sans SC** | 中文字体,简体覆盖 | `family=Noto+Sans+SC` |
157
+ | **Zen Maru Gothic** | 日文字体 | `family=Zen+Maru+Gothic` |
158
+
159
+ 字重分级:
160
+ - 正文内容:**500**
161
+ - 按钮文字、标题、菜单项:**600–700**
162
+ - 数字强调(时间数字、时钟):**900**
163
+ - placeholder / 说明文字:**400**
164
+
165
+ 字间距:`letter-spacing: 0.01em`(正文)/ `0.02em`(按钮/标题)/ `1.5px`(星期大写)
166
+
167
+ 禁止使用细体(weight < 400)或等宽字体。
168
+
169
+ ---
170
+
171
+ ### 间距 / 圆角 / 边框
172
+
173
+ ```
174
+ 间距:xs=4px sm=8px md=12px lg=16px xl=24px
175
+ 圆角:sm=12px base=18px lg=24px pill=50px(按钮/输入框)
176
+ 边框:默认 2px solid,输入框 2.5px,大尺寸输入框 3px
177
+ ```
178
+
179
+ ---
180
+
181
+ ### 阴影
182
+
183
+ ```css
184
+ /* 卡片/容器阴影(暖色调,非冷黑)*/
185
+ box-shadow: 0 3px 10px 0 rgba(61, 52, 40, 0.10); /* 基础 */
186
+ box-shadow: 0 8px 24px 0 rgba(61, 52, 40, 0.14); /* 较大 */
187
+ box-shadow: 0 4px 10px rgba(107, 92, 67, 0.42); /* Card */
188
+
189
+ /* 游戏按键立体阴影(最重要特征)*/
190
+ box-shadow: 0 5px 0 0 #bdaea0; /* 按钮默认 */
191
+ box-shadow: 0 6px 0 0 #bdaea0; /* 按钮 hover */
192
+ box-shadow: 0 1px 0 0 #bdaea0; /* 按钮 active */
193
+ box-shadow: 0 3px 0 0 #d4c9b4; /* 输入框 */
194
+ box-shadow: 0 2px 0 0 #d4c9b4; /* 小号输入框 */
195
+ box-shadow: 0 4px 0 0 #d4c9b4; /* 大号输入框 */
196
+ box-shadow: 0 3px 0 0 #5a9e1e; /* Switch 开启态 */
197
+ box-shadow: 0 2px 0 0 #5a9e1e; /* Switch 小号开启态 */
198
+ ```
199
+
200
+ ---
201
+
202
+ ### 动效
203
+
204
+ ```css
205
+ transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1); /* 通用 */
206
+ transition: all 0.15s; /* 快速(clear 按钮等)*/
207
+ transition: all 0.3s ease; /* 卡片 */
208
+ transition: grid-template-rows 0.3s cubic-bezier(0.4, 0, 0.2, 1); /* 手风琴 */
209
+
210
+ /* Hover:上浮 */
211
+ transform: translateY(-1px); /* 按钮 / 输入框 */
212
+ transform: translateY(-2px); /* Switch handle */
213
+ transform: translateY(-4px); /* 卡片 */
214
+
215
+ /* Active:下压(游戏按键反馈)*/
216
+ transform: translateY(2px); /* 按钮 active */
217
+
218
+ /* 出现动画 */
219
+ @keyframes animal-zoom-in {
220
+ from { opacity: 0; transform: scale(0.92); }
221
+ to { opacity: 1; transform: scale(1); }
222
+ }
223
+ @keyframes animal-fade-in {
224
+ from { opacity: 0; }
225
+ to { opacity: 1; }
226
+ }
227
+ @keyframes ac-fade-up {
228
+ from { opacity: 0; transform: translateY(8px); }
229
+ to { opacity: 1; transform: translateY(0); }
230
+ }
231
+ ```
232
+
233
+ ---
234
+
235
+ ## 2. 组件精确样式规范
236
+
237
+ ### Button
238
+
239
+ | 属性 | small | middle | large |
240
+ |---|---|---|---|
241
+ | height | 32px | **45px** | 48px |
242
+ | padding | `0 16px` | `0 20px` | `0 32px` |
243
+ | font-size | 12px | 14px | 16px |
244
+ | border-radius | 12px | **50px** | 24px |
245
+ | border-width | 2px | 2px | 2px |
246
+
247
+ **primary 按钮精确值:**
248
+ ```css
249
+ color: #794f27;
250
+ background: #f8f8f0;
251
+ border-color: #f8f8f0;
252
+ font-weight: 600;
253
+ letter-spacing: 0.02em;
254
+ line-height: 1;
255
+ box-shadow: 0 5px 0 0 #bdaea0;
256
+
257
+ /* hover */
258
+ transform: translateY(-1px);
259
+ box-shadow: 0 6px 0 0 #bdaea0;
260
+
261
+ /* active */
262
+ transform: translateY(2px);
263
+ box-shadow: 0 1px 0 0 #bdaea0;
264
+
265
+ /* focus-visible */
266
+ outline: 2px solid #19c8b9;
267
+ outline-offset: 2px;
268
+
269
+ /* disabled */
270
+ opacity: 0.5;
271
+ ```
272
+
273
+ **loading 斜纹动画(精确值):**
274
+ ```css
275
+ background: #0ec4b6;
276
+ border: 4px solid #4de2da;
277
+ color: #fff;
278
+ background-image: repeating-linear-gradient(
279
+ -45deg,
280
+ #0ec4b6, #0ec4b6 10px,
281
+ #01b0a7 10px, #01b0a7 20px
282
+ );
283
+ background-size: 28.28px 28.28px;
284
+ animation: animal-btn-loading 1s linear infinite;
285
+
286
+ @keyframes animal-btn-loading {
287
+ 0% { background-position: 0 0; }
288
+ 100% { background-position: -28.28px 0; }
289
+ }
290
+ ```
291
+
292
+ **danger primary 按钮:**
293
+ ```css
294
+ color: #fff;
295
+ box-shadow: 0 5px 0 0 #c94444; /* error-active */
296
+ ```
297
+
298
+ ---
299
+
300
+ ### Input
301
+
302
+ | 属性 | small | middle | large |
303
+ |---|---|---|---|
304
+ | height | 32px | 40px | 48px |
305
+ | padding | `0 14px` | `0 18px` | `0 22px` |
306
+ | font-size | 12px | 14px | 16px |
307
+ | border-radius | 40px | 50px | 50px |
308
+ | border-width | 2.5px | 2.5px | **3px** |
309
+ | box-shadow | `0 2px 0 0 #d4c9b4` | `0 3px 0 0 #d4c9b4` | `0 4px 0 0 #d4c9b4` |
310
+
311
+ **精确颜色值:**
312
+ ```css
313
+ background: rgb(247, 243, 223);
314
+ border: 2.5px solid #c4b89e;
315
+ box-shadow: 0 3px 0 0 #d4c9b4;
316
+
317
+ /* 文字 */
318
+ color: #725d42;
319
+ font-weight: 500;
320
+ letter-spacing: 0.01em;
321
+
322
+ /* placeholder */
323
+ color: #c4b89e;
324
+ font-weight: 400;
325
+
326
+ /* prefix/suffix */
327
+ color: #a0936e;
328
+
329
+ /* prefix margin-right */
330
+ margin-right: 6px;
331
+
332
+ /* suffix margin-left */
333
+ margin-left: 6px;
334
+
335
+ /* hover */
336
+ border-color: #a89878;
337
+ box-shadow: 0 3px 0 0 #c4b89e;
338
+
339
+ /* focus */
340
+ border-color: #ffcc00;
341
+ box-shadow: 0 3px 0 0 #e0b800, 0 0 0 3px rgba(255, 204, 0, 0.15);
342
+
343
+ /* disabled */
344
+ background: #ece8dc;
345
+ border-color: #d4c9b4;
346
+ box-shadow: none;
347
+ opacity: 0.6;
348
+ color: #c4b89e;
349
+
350
+ /* error */
351
+ box-shadow: 0 3px 0 0 #c94444;
352
+
353
+ /* warning */
354
+ box-shadow: 0 3px 0 0 #dba90e;
355
+ ```
356
+
357
+ **clear 按钮:**
358
+ ```css
359
+ width: 20px; height: 20px;
360
+ margin-left: 4px;
361
+ color: #c4b89e;
362
+ font-size: 13px; font-weight: 700;
363
+ border-radius: 50%;
364
+ transition: all 0.15s;
365
+ /* hover */ color: #725d42; background: rgba(114, 93, 66, 0.1);
366
+ ```
367
+
368
+ ---
369
+
370
+ ### Switch
371
+
372
+ **默认尺寸:**
373
+ ```css
374
+ min-width: 52px;
375
+ height: 28px;
376
+ border: 2.5px solid #c4b89e;
377
+ border-radius: 50px;
378
+ background: #d4c9b4;
379
+ box-shadow: inset 0 2px 4px rgba(114, 93, 66, 0.15);
380
+
381
+ /* handle */
382
+ width: 21px; height: 21px;
383
+ top: 2px; left: 2px;
384
+ background: rgb(247, 243, 223);
385
+ border: 2px solid #c4b89e;
386
+ border-radius: 50%;
387
+ box-shadow: 0 3px 0 0 #bdaea0;
388
+ transform: translateY(-2px); /* 悬浮效果 */
389
+
390
+ /* 开启态 */
391
+ background: #86d67a;
392
+ border-color: #6fba2c;
393
+ box-shadow: inset 0 2px 4px rgba(90, 158, 30, 0.2);
394
+ /* handle 开启后 left */
395
+ left: calc(100% - 24px);
396
+ border-color: #6fba2c;
397
+ box-shadow: 0 3px 0 0 #5a9e1e;
398
+
399
+ /* focus-visible */
400
+ outline: 2px solid #ffcc00;
401
+ outline-offset: 2px;
402
+
403
+ /* disabled */
404
+ opacity: 0.5;
405
+ ```
406
+
407
+ **small 尺寸:**
408
+ ```css
409
+ min-width: 38px; height: 20px; border-width: 2px;
410
+ /* handle */ width: 14px; height: 14px; top: 1px; left: 1px;
411
+ box-shadow: 0 2px 0 0 #bdaea0;
412
+ /* 开启 handle left */ left: calc(100% - 16px);
413
+ box-shadow: 0 2px 0 0 #5a9e1e;
414
+ ```
415
+
416
+ **inner 文字(checkedChildren/unCheckedChildren):**
417
+ ```css
418
+ font-size: 11px; font-weight: 700; color: #fff;
419
+ line-height: 1; letter-spacing: 0.02em;
420
+ text-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
421
+ padding: 0 8px 0 28px; /* 未开启 */
422
+ padding: 0 28px 0 8px; /* 开启 */
423
+ /* small 版 */ padding: 0 6px 0 20px; font-size: 9px;
424
+ ```
425
+
426
+ **loading spinner:**
427
+ ```css
428
+ width: 11px; height: 11px;
429
+ border: 2px solid #6fba2c;
430
+ border-right-color: transparent;
431
+ border-radius: 50%;
432
+ animation: animal-spin 0.6s linear infinite;
433
+ /* 关闭态 */ border-color: #a89878;
434
+ @keyframes animal-spin { to { transform: rotate(360deg); } }
435
+ ```
436
+
437
+ ---
438
+
439
+ ### Card
440
+
441
+ ```css
442
+ /* 默认 */
443
+ border-radius: 20px;
444
+ background: rgb(247, 243, 223);
445
+ padding: 16px 24px;
446
+ color: #725d42;
447
+ font-weight: 500;
448
+ box-shadow: 0 4px 10px rgba(107, 92, 67, 0.42);
449
+ transition: all 0.3s ease;
450
+ /* hover */ transform: translateY(-4px);
451
+
452
+ /* title 类型 */
453
+ background: #fdfdf5;
454
+ border-radius: 40px 35px 45px 38px / 38px 45px 35px 40px;
455
+ padding: 12px 32px;
456
+ font-weight: 600;
457
+ ```
458
+
459
+ ---
460
+
461
+ ### Collapse
462
+
463
+ ```css
464
+ /* 外层卡片 */
465
+ border-radius: 18px;
466
+ border: 2px solid #9f927d;
467
+ margin-bottom: 12px;
468
+ /* disabled */ opacity: 0.6;
469
+
470
+ /* 问题栏 */
471
+ padding: 16px 24px;
472
+ gap: 12px;
473
+
474
+ /* 图标圆圈 */
475
+ width: 28px; height: 28px;
476
+ background: #19c8b9;
477
+ color: #fff;
478
+ border-radius: 50%;
479
+ font-size: 18px; font-weight: 700;
480
+ box-shadow: 0 2px 4px rgba(25, 200, 185, 0.3);
481
+ /* 展开时 */ transform: rotate(180deg);
482
+
483
+ /* 叶子装饰 */
484
+ opacity: 0.5;
485
+ /* 展开时 */ opacity: 1; transform: rotate(45deg);
486
+
487
+ /* 问题文字 */
488
+ font-size: 16px; font-weight: 600; line-height: 1.4;
489
+
490
+ /* 答案展开(CSS Grid trick,无 JS)*/
491
+ display: grid;
492
+ grid-template-rows: 0fr;
493
+ transition: grid-template-rows 0.3s cubic-bezier(0.4, 0, 0.2, 1);
494
+ /* 展开 */ grid-template-rows: 1fr;
495
+ /* 内层 */ overflow: hidden;
496
+
497
+ /* 答案文字 */
498
+ padding: 0 24px;
499
+ font-size: 14px; line-height: 1.7;
500
+ /* 展开后 padding-bottom */ 24px;
501
+ ```
502
+
503
+ ---
504
+
505
+ ### Tabs
506
+
507
+ ```css
508
+ /* 外层容器 */
509
+ .tabs {
510
+ background: rgb(247, 243, 223);
511
+ border-radius: 20px;
512
+ border: 2px solid #9f927d;
513
+ overflow: hidden;
514
+ }
515
+
516
+ /* 标签列表 */
517
+ .tabList {
518
+ display: flex;
519
+ gap: 4px;
520
+ padding: 12px;
521
+ background: rgba(255, 255, 255, 0.6);
522
+ border-bottom: 2px solid #c4b89e;
523
+ }
524
+
525
+ /* 标签项 */
526
+ .tabItem {
527
+ display: flex;
528
+ align-items: center;
529
+ gap: 6px;
530
+ padding: 6px 14px;
531
+ background: transparent;
532
+ border: none;
533
+ border-radius: 50px;
534
+ cursor: pointer;
535
+ font-size: 14px;
536
+ font-weight: 500;
537
+ color: #8a7b66;
538
+ transition: all 0.2s ease;
539
+ }
540
+ /* hover */
541
+ .tabItem:hover {
542
+ background: rgba(25, 200, 185, 0.1);
543
+ color: #725d42;
544
+ }
545
+ /* 激活状态 */
546
+ .tabItem.active {
547
+ background: rgba(25, 200, 185, 0.15);
548
+ color: #19c8b9;
549
+ font-weight: 600;
550
+ box-shadow: 0 3px 0 0 #d4c9b4;
551
+ }
552
+
553
+ /* 标签图标 */
554
+ .tabIcon {
555
+ font-size: 10px;
556
+ }
557
+ /* 激活时图标放大 */
558
+ .tabItem.active .tabIcon {
559
+ transform: scale(1.2);
560
+ }
561
+
562
+ /* 叶子装饰动画 */
563
+ .tabLeaf {
564
+ position: absolute;
565
+ right: -6px;
566
+ top: -3px;
567
+ font-size: 12px;
568
+ animation: leafWiggle 2s ease-in-out infinite;
569
+ }
570
+ /* leafAnimation={false} 时追加 tabLeafStatic 类去除 animation */
571
+
572
+ @keyframes leafWiggle {
573
+ 0%, 100% { transform: rotate(0deg); }
574
+ 25% { transform: rotate(-10deg); }
575
+ 75% { transform: rotate(10deg); }
576
+ }
577
+
578
+ /* 内容区 */
579
+ .tabContent {
580
+ padding: 24px;
581
+ animation: fadeIn 0.25s ease;
582
+ }
583
+
584
+ @keyframes fadeIn {
585
+ from { opacity: 0; transform: translateY(4px); }
586
+ to { opacity: 1; transform: translateY(0); }
587
+ }
588
+ ```
589
+
590
+ ---
591
+
592
+ ### Modal
593
+
594
+ **SVG clip-path 完整 path d 值(精确还原 blob 轮廓):**
595
+ ```jsx
596
+ <svg style={{ position: 'absolute', width: 0, height: 0 }} aria-hidden>
597
+ <defs>
598
+ <clipPath id="animal-modal-clip" clipPathUnits="objectBoundingBox">
599
+ <path d="M0.501,0.005 L0.501,0.005 L0.523,0.005 L0.549,0.006
600
+ C0.704,0.01,0.796,0.017,0.825,0.027
601
+ L0.827,0.028
602
+ C0.872,0.045,0.939,0.044,0.978,0.17
603
+ C1,0.254,1,0.365,0.99,0.505
604
+ L0.988,0.513
605
+ C0.979,0.558,0.971,0.598,0.965,0.633
606
+ C0.956,0.689,0.979,0.77,0.964,0.865
607
+ C0.953,0.928,0.921,0.966,0.869,0.979
608
+ C0.821,0.986,0.773,0.992,0.726,0.995
609
+ L0.712,0.996 L0.694,0.997
610
+ C0.648,1,0.586,1,0.507,1
611
+ L0.501,1 L0.464,1
612
+ C0.385,1,0.325,0.998,0.283,0.995
613
+ C0.234,0.992,0.184,0.987,0.133,0.979
614
+ C0.081,0.966,0.05,0.928,0.039,0.865
615
+ C0.023,0.77,0.047,0.689,0.037,0.633
616
+ C0.031,0.595,0.023,0.552,0.013,0.505
617
+ C-0.006,0.365,-0.002,0.254,0.024,0.17
618
+ C0.064,0.045,0.13,0.045,0.174,0.028
619
+ L0.175,0.028
620
+ C0.204,0.017,0.303,0.009,0.474,0.005
621
+ L0.501,0.005" />
622
+ </clipPath>
623
+ </defs>
624
+ </svg>
625
+ ```
626
+
627
+ **Modal 精确样式:**
628
+ ```css
629
+ /* 遮罩 */
630
+ background: rgba(0, 0, 0, 0.35);
631
+ animation: animal-fade-in 0.25s ease;
632
+ z-index: 1000;
633
+
634
+ /* 弹窗容器 */
635
+ max-width: calc(100vw - 32px);
636
+ max-height: calc(100vh - 64px);
637
+ animation: animal-zoom-in 0.3s ease;
638
+
639
+ /* 裁切内容区 */
640
+ clip-path: url(#animal-modal-clip);
641
+ background: rgb(247, 243, 223);
642
+ color: rgb(128, 115, 89);
643
+ padding: 48px 48px 32px 48px;
644
+
645
+ /* 标题 */
646
+ font-size: 28px; font-weight: 700;
647
+ color: rgba(114, 93, 66, 1);
648
+ padding-bottom: 15px;
649
+
650
+ /* 关闭按钮 */
651
+ width: 32px; height: 32px;
652
+ font-size: 22px;
653
+ color: rgba(114, 93, 66, 0.6);
654
+ border-radius: 50%;
655
+ transition: all 0.2s;
656
+ /* hover */ background: rgba(114, 93, 66, 0.1); color: rgba(114, 93, 66, 1);
657
+
658
+ /* body */
659
+ font-size: 20px; font-weight: 600; line-height: 1.6;
660
+ color: #8a7b66;
661
+ padding-bottom: 20px;
662
+
663
+ /* footer */
664
+ gap: 12px;
665
+
666
+ /* 普通按钮 */
667
+ height: 40px; padding: 0 24px;
668
+ font-size: 18px;
669
+ border: 2px solid rgba(114, 93, 66, 0.3);
670
+ border-radius: 39.81px;
671
+ transition: all 0.2s; line-height: 1;
672
+ /* hover */ border-color: rgba(114,93,66,0.6); background: rgba(114,93,66,0.08);
673
+
674
+ /* 主按钮(确认)*/
675
+ color: rgba(114, 93, 66, 1);
676
+ background: rgba(255, 204, 0, 1); /* 游戏黄色!*/
677
+ border-color: rgba(255, 204, 0, 1);
678
+ /* hover */ background: rgba(255,204,0,0.85); border-color: rgba(255,204,0,0.85);
679
+ ```
680
+
681
+ ---
682
+
683
+ ### Time
684
+
685
+ ```css
686
+ /* 容器 */
687
+ display: flex; align-items: center;
688
+ gap: 20px;
689
+ padding: 16px 36px;
690
+ background: linear-gradient(180deg, #fff 0%, #f8f8f0 100%);
691
+ border: 3px solid #d4cfc3;
692
+ border-radius: 18px;
693
+ animation: ac-fade-up 0.5s ease-out;
694
+
695
+ /* 日期块(右侧分隔线)*/
696
+ padding-right: 24px;
697
+ border-right: 3px solid rgba(159, 146, 125, 0.35);
698
+
699
+ /* 星期 */
700
+ color: #6fba2c;
701
+ font-weight: 900; font-size: 14px;
702
+ letter-spacing: 1.5px;
703
+
704
+ /* 月日 */
705
+ color: #8b7355;
706
+ font-weight: 800; font-size: 22px;
707
+
708
+ /* 时间数字 */
709
+ color: #8b7355;
710
+ font-weight: 900; font-size: 48px;
711
+ letter-spacing: 2px;
712
+
713
+ /* 冒号(闪烁)*/
714
+ font-size: 48px; color: #8b7355;
715
+ position: relative; top: -0.08em;
716
+ margin: 0 1px;
717
+ animation: blink 1s step-end infinite;
718
+
719
+ @keyframes blink { 50% { opacity: 0; } }
720
+
721
+ /* 响应式 768px */
722
+ padding: 12px 20px; gap: 12px;
723
+ .acWeekday → font-size: 11px;
724
+ .acMonthday → font-size: 16px;
725
+ .acTime / .acColon → font-size: 32px;
726
+ ```
727
+
728
+ ---
729
+
730
+ ### Phone(NookPhone)
731
+
732
+ **外壳(固定尺寸,不响应式):**
733
+ ```css
734
+ .phone {
735
+ width: 527px; height: 788px;
736
+ background: #F8F4E8; /* 奶油米 */
737
+ border-radius: 136px; /* 超大圆角,近似胶囊 */
738
+ overflow: hidden;
739
+ }
740
+ .homeScreen {
741
+ height: 100%;
742
+ padding-top: 40px;
743
+ background: #F8F4E8;
744
+ background-size: 100% 200%;
745
+ animation: grasswave 8s ease-in-out infinite;
746
+ display: flex; flex-direction: column; align-items: center;
747
+ }
748
+ @keyframes grasswave {
749
+ 0%, 100% { background-position: 0% 0%; }
750
+ 50% { background-position: 0% 100%; }
751
+ }
752
+ ```
753
+
754
+ **顶部时间栏:**
755
+ ```css
756
+ .dateDisplay { padding: 0 70px 31px 70px; text-align: center; }
757
+ .dateDisplayHeader { display:flex; justify-content:space-between; align-items:center;
758
+ font-size: 32px; font-weight: 800; letter-spacing: 2px; color: #DDDBCC; }
759
+ .blink { font-size: 32px; font-weight: 800; color: #DDDBCC;
760
+ animation: blink 1s steps(1) infinite; vertical-align: text-bottom; }
761
+ @keyframes blink { 0%,50% { opacity: 1; } 51%,100% { opacity: 0; } }
762
+ .dayText { font-size: 48px; font-weight: 800; color: #725C4E;
763
+ letter-spacing: 2px; height: 56px; margin-top: 20px; }
764
+ ```
765
+
766
+ **3×3 应用网格:**
767
+ ```css
768
+ .appsGrid { display: grid; grid-template-columns: repeat(3, 1fr);
769
+ gap: 32px; padding: 8px; flex: 1;
770
+ align-content: center; justify-content: center; }
771
+ .appItem { width: 123px; height: 123px;
772
+ border-radius: 45px; /* 圆角正方形 */
773
+ position: relative;
774
+ display: flex; justify-content: center; align-items: center; }
775
+ .appItem:hover .appIcon { animation: iconBounce 0.3s ease-in-out forwards; }
776
+ .appIcon { width: 100%; height: 100%;
777
+ background-repeat: no-repeat; background-position: center;
778
+ background-size: 70% auto; }
779
+ .appItemOffset { overflow: hidden; }
780
+ .appIconOffset { transform: translateY(10px); }
781
+
782
+ @keyframes iconBounce {
783
+ 0% { transform: scale(1) rotate(0deg); }
784
+ 50% { transform: scale(1.2) rotate(-5deg); }
785
+ 100% { transform: scale(1.1) rotate(-4deg); }
786
+ }
787
+ ```
788
+
789
+ **应用数据结构(`src/components/Phone/Phone.tsx`):**
790
+
791
+ | id | iconClass | 背景色 | offset | hasNewMessage |
792
+ |---|---|---|---|---|
793
+ | camera | iconCamera | `#B77DEE` | | ✓ |
794
+ | app | iconApp | `#889DF0` | ✓ | |
795
+ | critterpedia | iconCritterpedia | `#F7CD67` | | |
796
+ | diy | iconDiy | `#E59266` | | |
797
+ | shopping | iconDesign | `#F8A6B2` | | |
798
+ | variant | iconMap | `#82D5BB` | | ✓ |
799
+ | design | iconVariant | `#8AC68A` | | |
800
+ | map | iconHelicopter | `#FC736D` | | |
801
+ | chat | iconChat | `#D1DA49` | | |
802
+
803
+ 每个 iconClass 都绑定一个 `background-image: url('./img/icon-*.svg')`,`iconApp` 特殊使用 `background-size: 100% auto`(其他是 `70% auto`)。可用图标资源:`icon-miles/camera/chat/critterpedia/design/diy/helicopter/map/shopping/variant.svg`,以及状态图标 `wifi.svg` / `location.svg` / `page.svg`。
804
+
805
+ **小红点(新消息):**
806
+ ```css
807
+ .badge {
808
+ position: absolute; top: 0; left: 0;
809
+ width: 28px; height: 28px; border-radius: 50%;
810
+ background: #FF544A;
811
+ border: 5px solid #F8F4E8; /* 奶油米描边,形成游戏风徽章 */
812
+ }
813
+ ```
814
+
815
+ **底部状态图标:**
816
+ ```css
817
+ .iconWifi { width: 79px; height: 29px; background: url('./img/wifi.svg') center/contain no-repeat; }
818
+ .iconLocation { width: 36px; height: 36px; background: url('./img/location.svg') center/contain no-repeat; }
819
+ .iconPage { width: 65px; height: 32px; background: url('./img/page.svg') center/contain no-repeat; }
820
+ .pageIndicator{ display: flex; justify-content: center; align-items: center;
821
+ margin-top: 74px; }
822
+ ```
823
+
824
+ **行为:** 内部 `useEffect + setInterval(1000)` 更新时间,`12 小时制 + AM/PM + 零填充分钟`,冒号闪烁 1s 一个周期。组件无业务回调,纯展示。
825
+
826
+ ---
827
+
828
+ ### Footer
829
+
830
+ ```tsx
831
+ <Footer /> // 默认:森林(tree,高 60px)
832
+ <Footer type="sea" /> // 海浪(高 80px)
833
+ ```
834
+
835
+ ```less
836
+ .footer { width: 100%; height: 80px;
837
+ background: url('./img/footer-sea.svg') center/contain no-repeat; }
838
+ .tree { background-image: url('./img/footer-tree.webp');
839
+ height: 60px;
840
+ background-size: cover;
841
+ background-position: bottom center; }
842
+ ```
843
+
844
+ - `sea`:SVG 海浪插画,`viewBox="0 0 1440 186"`,多色(珊瑚 `#EC7175`、海蓝 `#327A93`、浅蓝 `#98D2E3`、深青 `#008077` 等)。
845
+ - `tree`:webp 森林剪影,置于页面最底部。
846
+
847
+ ---
848
+
849
+ ### Divider
850
+
851
+ ```tsx
852
+ <Divider type="line-brown" /> // 默认
853
+ <Divider type="line-teal" />
854
+ <Divider type="line-white" />
855
+ <Divider type="line-yellow" />
856
+ <Divider type="wave-yellow" />
857
+ ```
858
+
859
+ ```less
860
+ .divider { width: 100%; height: 12px;
861
+ background: url('./img/divider-line-brown.svg') center/contain no-repeat; }
862
+ .line-teal { background-image: url('./img/divider-line-teal.svg'); }
863
+ .line-white { background-image: url('./img/divider-line-white.png'); }
864
+ .line-yellow { background-image: url('./img/divider-line-yellow.svg'); }
865
+ .wave-yellow { background-image: url('./img/wave-yellow.svg'); }
866
+ ```
867
+
868
+ 默认 SVG 色值参考:`#D8D0C3`(米褐),`viewBox="0 0 297 14"`。
869
+
870
+ ---
871
+
872
+ ### Cursor
873
+
874
+ ```tsx
875
+ <Cursor>
876
+ <App /> {/* 此范围内所有元素变为游戏手指光标 */}
877
+ </Cursor>
878
+ ```
879
+
880
+ 样式文件为 **普通 CSS**(非 module):
881
+ ```css
882
+ .animal-cursor,
883
+ .animal-cursor * {
884
+ cursor: url('./cursor-icon.png') 4 0, auto !important;
885
+ }
886
+ ```
887
+
888
+ - `cursor-icon.png` 热点坐标 `(4, 0)`
889
+ - 使用 `!important` 覆盖默认光标;`className` 直接挂在根 `<div>` 上,类名固定为 `animal-cursor`
890
+
891
+ ---
892
+
893
+ ### Typewriter
894
+
895
+ ```tsx
896
+ <Typewriter speed={90} trigger={openCount} autoPlay onDone={() => ...}>
897
+ <p>第一行 <strong>加粗</strong></p>
898
+ <p>第二行</p>
899
+ </Typewriter>
900
+ ```
901
+
902
+ Props:
903
+
904
+ | name | type | default | 说明 |
905
+ |---|---|---|---|
906
+ | `children` | `ReactNode` | — | 要逐字打出的内容,**保留原有元素结构 / 换行 / 样式** |
907
+ | `speed` | `number (ms)` | `90` | 每字间隔 |
908
+ | `trigger` | `unknown` | — | 值变化即重新播放(通常传递弹窗 open 次数或递增 key) |
909
+ | `autoPlay` | `boolean` | `true` | `false` 直接全量显示 |
910
+ | `onDone` | `() => void` | — | 播放完成回调 |
911
+
912
+ **实现要点:**
913
+ - `countText(node)`:递归统计 ReactNode 的纯文本长度
914
+ - `renderTruncated(node, state)`:按剩余字符数递归裁剪,`React.cloneElement` 保留原节点与样式
915
+ - `useEffect` 依赖 `[total, speed, trigger, autoPlay]`,内部 `setInterval` 按步递增 `count`
916
+ - **无样式文件**,不包裹任何额外 DOM(返回 `<>...</>`),对布局零影响
917
+
918
+ ---
919
+
920
+ ### Checkbox
921
+
922
+ Props:
923
+
924
+ | name | type | default | 说明 |
925
+ |---|---|---|---|
926
+ | `options` | `CheckboxOption[]` | — | **必填**;每项 `{ label, value, disabled? }` |
927
+ | `value` | `Array<string \| number>` | — | 受控选中值 |
928
+ | `defaultValue` | `Array<string \| number>` | `[]` | 非受控默认值 |
929
+ | `size` | `'small' \| 'middle' \| 'large'` | `'middle'` | 尺寸 |
930
+ | `disabled` | `boolean` | `false` | 禁用全部项 |
931
+ | `direction` | `'horizontal' \| 'vertical'` | `'horizontal'` | 排列方向 |
932
+ | `onChange` | `(values) => void` | — | 选中值变化 |
933
+
934
+ **尺寸表(box 方框):**
935
+
936
+ | 属性 | small | middle | large |
937
+ |---|---|---|---|
938
+ | 宽高 | 18×18px | **22×22px** | 28×28px |
939
+ | border-width | 2px | 2.5px | 3px |
940
+ | 标签 font-size | 12px | 14px | 16px |
941
+ | 对勾 font-size | 11px | 13px | 16px |
942
+
943
+ **精确样式:**
944
+ ```css
945
+ /* group */
946
+ display: flex; flex-wrap: wrap;
947
+ gap: 12px; /* horizontal */
948
+ /* vertical */ flex-direction: column; gap: 8px;
949
+
950
+ /* item */
951
+ display: inline-flex; align-items: center;
952
+ gap: 8px;
953
+ cursor: pointer;
954
+ transition: all 0.25s cubic-bezier(0.4,0,0.2,1);
955
+
956
+ /* box(未选)*/
957
+ background: rgb(247, 243, 223);
958
+ border: 2.5px solid #c4b89e;
959
+ border-radius: 8px;
960
+ display: inline-flex; align-items: center; justify-content: center;
961
+
962
+ /* box hover */
963
+ border-color: #19c8b9;
964
+ transform: translateY(-1px);
965
+
966
+ /* box focus-visible */
967
+ outline: 2px solid #ffcc00; outline-offset: 2px;
968
+
969
+ /* 选中 */
970
+ background: #19c8b9;
971
+ border-color: #11a89b;
972
+ /* 选中 hover */ background: #3dd4c6; border-color: #19c8b9;
973
+
974
+ /* 对勾 ✓ */
975
+ color: #fff; font-weight: 700; line-height: 1;
976
+ animation: animal-checkbox-pop 0.15s cubic-bezier(0.4,0,0.2,1);
977
+
978
+ @keyframes animal-checkbox-pop {
979
+ 0% { transform: scale(0.4); opacity: 0; }
980
+ 60% { transform: scale(1.2); }
981
+ 100% { transform: scale(1); opacity: 1; }
982
+ }
983
+
984
+ /* label */
985
+ color: #725d42; font-weight: 500;
986
+ letter-spacing: 0.01em;
987
+ /* item hover */ label color: #794f27;
988
+
989
+ /* 禁用(单项或整组)*/
990
+ cursor: not-allowed;
991
+ opacity: 0.55;
992
+ /* box */ background: #f0ece2; border-color: #d4c9b4; transform: none !important;
993
+ /* label */ color: #c4b89e;
994
+ ```
995
+
996
+ ---
997
+
998
+ ### CodeBlock
999
+
1000
+ Props:
1001
+
1002
+ | name | type | default | 说明 |
1003
+ |---|---|---|---|
1004
+ | `code` | `string` | — | **必填**;原始源码字符串,内部自动按 JSX/TS 分词高亮 |
1005
+ | `style` | `CSSProperties` | — | 会合并覆盖默认深色主题 |
1006
+ | `className` | `string` | — | 自定义类名 |
1007
+
1008
+ **默认主题(写死在组件,不走 Less):**
1009
+
1010
+ ```css
1011
+ padding: 20px 24px;
1012
+ background: #2b2118;
1013
+ border: 1px solid #3d3028;
1014
+ border-radius: 20px;
1015
+ font-size: 14px;
1016
+ line-height: 1.7;
1017
+ font-family: 'SF Mono','Fira Code','Cascadia Code',Consolas,monospace;
1018
+ font-weight: 600;
1019
+ color: #e8d5bc;
1020
+ white-space: pre;
1021
+ overflow: auto;
1022
+ tab-size: 4;
1023
+ ```
1024
+
1025
+ **Token 调色板(`COLORS` 常量):**
1026
+
1027
+ | token | 颜色 | 覆盖 |
1028
+ |---|---|---|
1029
+ | comment | `#6b5e50` | `/* */`、`//` |
1030
+ | string | `#a8d4a0` | 反引号 / 单双引号、数字 |
1031
+ | keyword | `#d4a0e0` | `import/export/const/return/async/...`、`true/false/null/undefined` |
1032
+ | react | `#e06c75` | `React/useState/useEffect/FC/ReactNode/CSSProperties/...` |
1033
+ | component| `#80c0e0` | 大写驼峰标识符(JSX 组件名、类型名) |
1034
+ | func | `#61afef` | 小写标识符后跟 `(` |
1035
+ | prop | `#e8c87a` | 标识符后跟 `=`(JSX props / 赋值) |
1036
+ | jsx | `#f0a870` | `<Tag`、`</Tag`、`/>` |
1037
+ | operator | `#d4b896` | `{}[]();,` 和 `+-*/=<>&|^~?:` 等 |
1038
+ | default | `#e8d5bc` | 其余文本 |
1039
+
1040
+ > 不支持 `language` prop;非 JS/TS 代码(Python/Shell/SQL)会按通用规则着色,显示可能不准确。不带 copy 按钮、行号或折行。
1041
+
1042
+ ---
1043
+
1044
+ ## 3. Demo 布局精确规范
1045
+
1046
+ 这是 Demo 站(`demo/App.tsx`)的实际布局数值,用于还原完整页面效果:
1047
+
1048
+ ### 整体布局
1049
+
1050
+ ```css
1051
+ /* 页面背景 */
1052
+ /* 首页 */ background: url(home_bg.svg) center/cover no-repeat, #7DC395;
1053
+ /* 组件页 */ background: url(content_bg_pc.jpg) center fixed;
1054
+
1055
+ /* Sidebar */
1056
+ width: 220px; min-width: 220px;
1057
+ background: url(menu_bg.svg) center/cover no-repeat;
1058
+ ```
1059
+
1060
+ ### Sidebar 精确值
1061
+
1062
+ ```css
1063
+ /* 顶部 Logo 区 */
1064
+ padding: 20px 16px 12px;
1065
+ border-bottom: 1px solid #e8e2d6;
1066
+ font-weight: 700; font-size: 15px;
1067
+ color: #725d42; letter-spacing: -0.3px;
1068
+
1069
+ /* Logo 图片 */
1070
+ width: 24px; height: 24px; margin-right: 8px;
1071
+
1072
+ /* 菜单列表 */
1073
+ padding: 8px 0;
1074
+
1075
+ /* 分类标题 */
1076
+ padding: 12px 16px 4px;
1077
+ font-size: 11px; color: #a0936e;
1078
+ font-weight: 600; letter-spacing: 0.5px;
1079
+ text-transform: uppercase;
1080
+
1081
+ /* 菜单项 */
1082
+ margin: 1px 5px;
1083
+ height: 40px; padding: 0 16px;
1084
+ padding-left: 26px;
1085
+ font-weight: 600; font-size: 14px;
1086
+ border-radius: 12px;
1087
+ transition: all 0.15s;
1088
+
1089
+ /* inactive */ color: #8a7b66; background: transparent;
1090
+ /* inactive hover */ background: #d6dff0;
1091
+ /* active */ color: #fff; background: #B7C6E5;
1092
+ ```
1093
+
1094
+ ### 主内容区
1095
+
1096
+ ```css
1097
+ /* 桌面 */
1098
+ padding: 32px 40px;
1099
+
1100
+ /* 底部装饰图(桌面端,固定定位)*/
1101
+ left: 220px;
1102
+ width: calc(100% - 220px);
1103
+ z-index: 0; pointer-events: none;
1104
+ ```
1105
+
1106
+ ### 移动端适配
1107
+
1108
+ ```css
1109
+ /* 顶栏 */
1110
+ height: 52px; padding: 0 12px;
1111
+ background: rgba(255, 252, 244, 0.92);
1112
+ backdrop-filter: blur(8px);
1113
+ border-bottom: 1px solid #e8e2d6;
1114
+ z-index: 50;
1115
+
1116
+ /* 按钮 */ font-size: 20px; color: #725d42; padding: 4px 8px; border-radius: 8px;
1117
+
1118
+ /* 主内容区 padding-top */ 68px;
1119
+
1120
+ /* 抽屉 */
1121
+ width: 240px; z-index: 99;
1122
+ box-shadow: 4px 0 24px rgba(0, 0, 0, 0.15);
1123
+ /* 遮罩 */ background: rgba(0, 0, 0, 0.35); z-index: 98;
1124
+ ```
1125
+
1126
+ ---
1127
+
1128
+ ## 4. HomePage 精确规范
1129
+
1130
+ ```css
1131
+ /* Hero 区域 */
1132
+ padding: 60px 40px 40px;
1133
+ min-height: 80vh;
1134
+
1135
+ /* 主标题 */
1136
+ font-size: 50px; font-weight: 700;
1137
+ color: #FFF9E6;
1138
+ text-shadow: 0px 4px 1px rgba(0, 0, 0, 0.4);
1139
+ margin: 0 0 12px;
1140
+
1141
+ /* 版本 Badge */
1142
+ font-size: 12px; font-weight: 600;
1143
+ padding: 2px 10px; border-radius: 10px;
1144
+ background: #e6f9f6; color: #19c8b9;
1145
+ margin-left: 8px;
1146
+
1147
+ /* 副标题 */
1148
+ font-size: 17px; color: #7c5734; line-height: 1.7;
1149
+ margin: 0 0 28px; max-width: 520px;
1150
+
1151
+ /* Logo 图片 */
1152
+ width: 172px; height: 172px;
1153
+
1154
+ /* Section */
1155
+ padding: 48px 40px; max-width: 960px; margin: 0 auto;
1156
+
1157
+ /* Section 标题 */
1158
+ font-size: 24px; font-weight: 700; color: #725d42; margin: 0 0 8px;
1159
+
1160
+ /* Section 描述 */
1161
+ font-size: 14px; color: #7c5734; margin-bottom: 32px;
1162
+
1163
+ /* Feature 网格 */
1164
+ grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
1165
+ gap: 16px;
1166
+
1167
+ /* Feature Card hover */
1168
+ transform: translateY(-4px);
1169
+ box-shadow: 0 8px 24px rgba(114, 93, 66, 0.15);
1170
+
1171
+ /* Feature 图标 hover */
1172
+ transform: scale(1.1) rotate(-4deg);
1173
+
1174
+ /* 代码块 */
1175
+ max-width: 600px; margin: 0 auto;
1176
+ padding: 20px 28px;
1177
+ background: #2b2118;
1178
+ border: 1px solid #3d3028;
1179
+ border-radius: 20px;
1180
+ font-size: 13px; font-weight: 600;
1181
+ color: #e8d5bc; line-height: 1.8;
1182
+ ```
1183
+
1184
+ **代码高亮配色:**
1185
+
1186
+ | Token 类型 | 颜色 |
1187
+ |---|---|
1188
+ | 注释 | `#6b5e50`(italic, weight 400)|
1189
+ | 字符串 | `#a8d4a0` |
1190
+ | JSX 标签 | `#f0a870` |
1191
+ | 关键字 / npm/pnpm | `#f0a870` |
1192
+ | 命令动词(install/add)| `#a8d4a0` |
1193
+ | 括号 `{}` | `#d4b896` |
1194
+ | 箭头 `=>` | `#d4a0e0` |
1195
+ | CSS 变量名 | `#e8c87a` |
1196
+ | `:root` | `#f0a870` |
1197
+ | 十六进制色值 | `#8ab8e0` |
1198
+
1199
+ ---
1200
+
1201
+ ## 5. 自实现 CSS 变量完整模板
1202
+
1203
+ 不依赖组件库时,在 `:root` 中声明以下变量:
1204
+
1205
+ ```css
1206
+ :root {
1207
+ /* 字体 */
1208
+ --animal-font: Nunito, 'Noto Sans SC', 'Zen Maru Gothic',
1209
+ -apple-system, 'PingFang SC', 'Hiragino Sans GB', sans-serif;
1210
+
1211
+ /* 主色 */
1212
+ --animal-primary: #19c8b9;
1213
+ --animal-primary-hover: #3dd4c6;
1214
+ --animal-primary-active: #11a89b;
1215
+ --animal-primary-bg: #e6f9f6;
1216
+
1217
+ /* 文字 */
1218
+ --animal-text: #794f27;
1219
+ --animal-text-body: #725d42;
1220
+ --animal-text-secondary: #9f927d;
1221
+ --animal-text-muted: #8a7b66;
1222
+ --animal-text-disabled: #c4b89e;
1223
+
1224
+ /* 背景 */
1225
+ --animal-bg: #f8f8f0;
1226
+ --animal-bg-content: rgb(247, 243, 223);
1227
+ --animal-bg-disabled: #f0ece2;
1228
+
1229
+ /* 边框 */
1230
+ --animal-border: #c4b89e;
1231
+ --animal-border-hover: #a89878;
1232
+
1233
+ /* 圆角 */
1234
+ --animal-radius-sm: 12px;
1235
+ --animal-radius: 18px;
1236
+ --animal-radius-lg: 24px;
1237
+ --animal-radius-pill: 50px;
1238
+
1239
+ /* 3D 阴影 */
1240
+ --animal-shadow-btn: #bdaea0;
1241
+ --animal-shadow-input: #d4c9b4;
1242
+ --animal-shadow-switch: #5a9e1e;
1243
+
1244
+ /* 游戏特殊色 */
1245
+ --animal-focus-yellow: #ffcc00;
1246
+ --animal-focus-yellow-d: #e0b800;
1247
+ --animal-sidebar-active: #B7C6E5;
1248
+ --animal-sidebar-hover: #d6dff0;
1249
+
1250
+ /* 状态 */
1251
+ --animal-success: #6fba2c;
1252
+ --animal-warning: #f5c31c;
1253
+ --animal-error: #e05a5a;
1254
+
1255
+ /* 动效 */
1256
+ --animal-ease: cubic-bezier(0.4, 0, 0.2, 1);
1257
+ --animal-duration-fast: 0.15s;
1258
+ --animal-duration: 0.25s;
1259
+ --animal-duration-slow: 0.35s;
1260
+ }
1261
+ ```
1262
+
1263
+ ---
1264
+
1265
+ ## 6. 7 条设计铁律
1266
+
1267
+ 1. **颜色**:大地棕色系文字 + 薄荷青绿主色 + 奶油米白背景,禁止纯黑 / 冷灰
1268
+ 2. **圆角**:最小 12px;按钮、输入框必须 50px pill 形
1269
+ 3. **立体感**:所有可点击元素加底部厚阴影 `0 Npx 0 0 [暗色]`,hover 上浮,active 下压
1270
+ 4. **字体**:Nunito(Google Fonts)圆体,按钮/标题 weight 600+,从不使用细体
1271
+ 5. **动效**:过渡 0.15~0.35s,缓动 `cubic-bezier(0.4, 0, 0.2, 1)`,平滑不生硬
1272
+ 6. **焦点**:输入框用黄色 `#ffcc00`,按钮用青绿 `#19c8b9`,绝不用蓝色
1273
+ 7. **禁止**:直角矩形交互元素、纯黑文字 `#000`、冷蓝色调、扁平无阴影设计
1274
+
1275
+ ---
1276
+
1277
+ ## 7. 新组件文件结构模板
1278
+
1279
+ ```
1280
+ src/components/MyComponent/
1281
+ ├── MyComponent.tsx # 组件逻辑(必须设置 displayName)
1282
+ ├── myComponent.module.less # CSS Modules 样式
1283
+ └── index.ts # 统一导出
1284
+ ```
1285
+
1286
+ `src/index.ts` 追加:
1287
+ ```ts
1288
+ // 方式 A:组件用 default export
1289
+ export { default as MyComponent } from './components/MyComponent'
1290
+ export type { MyComponentProps } from './components/MyComponent/MyComponent'
1291
+
1292
+ // 方式 B:组件用 named export(如 Checkbox / CodeBlock / Select / Icon / Tabs 当前采用)
1293
+ export { MyComponent } from './components/MyComponent'
1294
+ export type { MyComponentProps } from './components/MyComponent'
1295
+ ```
1296
+ > 仓库内两种风格并存;新增组件选一种即可,只要 `src/index.ts` 能成功 re-export。
1297
+
1298
+ Less 模板(直接使用设计 token):
1299
+
1300
+ ```less
1301
+ @import '../../styles/variables.less';
1302
+
1303
+ .container {
1304
+ background: @bg-color-content; // rgb(247,243,223)
1305
+ color: @text-color-body; // #725d42
1306
+ border: @border-width solid @border-color-light; // 2px solid #c4b89e
1307
+ border-radius: @border-radius-base; // 18px
1308
+ font-family: @font-family;
1309
+ font-weight: 500;
1310
+ letter-spacing: 0.01em;
1311
+ transition: all @motion-duration-base @motion-ease;
1312
+ box-shadow: 0 3px 0 0 @shadow-input; // #d4c9b4
1313
+
1314
+ &:hover:not(.disabled) {
1315
+ border-color: @border-color-hover; // #a89878
1316
+ transform: translateY(-1px);
1317
+ box-shadow: 0 4px 0 0 @shadow-input;
1318
+ }
1319
+
1320
+ &:focus-within {
1321
+ border-color: @focus-yellow; // #ffcc00
1322
+ box-shadow: 0 3px 0 0 @focus-yellow-dark,
1323
+ 0 0 0 3px rgba(255, 204, 0, 0.15);
1324
+ }
1325
+
1326
+ &.disabled {
1327
+ opacity: 0.6;
1328
+ cursor: not-allowed;
1329
+ background: @bg-color-disabled;
1330
+ color: @text-color-disabled;
1331
+ border-color: @shadow-input;
1332
+ box-shadow: none;
1333
+ }
1334
+ }
1335
+ ```
1336
+
1337
+ TSX 模板:
1338
+
1339
+ ```tsx
1340
+ import React from 'react'
1341
+ import styles from './myComponent.module.less'
1342
+ import classNames from 'classnames'
1343
+
1344
+ export interface MyComponentProps {
1345
+ /** 尺寸 */
1346
+ size?: 'small' | 'middle' | 'large'
1347
+ /** 禁用 */
1348
+ disabled?: boolean
1349
+ /** 子元素 */
1350
+ children?: React.ReactNode
1351
+ /** 自定义类名 */
1352
+ className?: string
1353
+ /** 自定义样式 */
1354
+ style?: React.CSSProperties
1355
+ }
1356
+
1357
+ const MyComponent: React.FC<MyComponentProps> = ({
1358
+ size = 'middle',
1359
+ disabled = false,
1360
+ children,
1361
+ className,
1362
+ style,
1363
+ }) => {
1364
+ const cls = classNames(
1365
+ styles.container,
1366
+ styles[size],
1367
+ { [styles.disabled]: disabled },
1368
+ className
1369
+ )
1370
+
1371
+ return (
1372
+ <div className={cls} style={style}>
1373
+ {children}
1374
+ </div>
1375
+ )
1376
+ }
1377
+
1378
+ MyComponent.displayName = 'MyComponent'
1379
+ export default MyComponent
1380
+ ```
1381
+
1382
+ ---
1383
+
1384
+ ## 8. Demo 页面规范
1385
+
1386
+ 每个组件在 `demo/components/<ComponentName>/index.tsx` 创建演示页:
1387
+
1388
+ ```tsx
1389
+ import { CodeBlock, ApiTable } from '../../tools'
1390
+
1391
+ const props = [
1392
+ { name: 'size', type: "'small' | 'middle' | 'large'", default: "'middle'", description: '尺寸' },
1393
+ ]
1394
+
1395
+ export default function MyComponentDemo() {
1396
+ return (
1397
+ <div>
1398
+ <h2>MyComponent</h2>
1399
+ <CodeBlock code={`<MyComponent size="large">内容</MyComponent>`} />
1400
+ <ApiTable data={props} />
1401
+ </div>
1402
+ )
1403
+ }
1404
+ ```
1405
+
1406
+ 并在 `demo/ComponentPage.tsx` 中注册路由,同时把 `title / desc` 写入 `demo/pageInfo.ts`:
1407
+
1408
+ ```ts
1409
+ // demo/pageInfo.ts — 供 App 静态导入的轻量元信息
1410
+ export const PAGE_INFO: Record<string, { title: string; desc: string }> = {
1411
+ button: { title: 'Button 按钮', desc: '...' },
1412
+ input: { title: 'Input 输入框', desc: '...' },
1413
+ switch: { title: 'Switch 开关', desc: '...' },
1414
+ card: { title: 'Card 卡片', desc: '...' },
1415
+ collapse: { title: 'Collapse 折叠面板', desc: '...' },
1416
+ cursor: { title: 'Cursor 光标', desc: '...' },
1417
+ time: { title: 'Time 时间', desc: '...' },
1418
+ phone: { title: 'Phone 手机', desc: '...' },
1419
+ footer: { title: 'Footer 底部装饰', desc: '...' },
1420
+ modal: { title: 'Modal 弹窗', desc: '...' },
1421
+ typewriter: { title: 'Typewriter 打字机', desc: '...' },
1422
+ 'divider-comp': { title: 'Divider 分割线', desc: '...' },
1423
+ icon: { title: 'Icon 图标', desc: '...' },
1424
+ select: { title: 'Select 选择器', desc: '...' },
1425
+ checkbox: { title: 'Checkbox 多选框', desc: '...' },
1426
+ codeblock: { title: 'CodeBlock 代码高亮', desc: '...' },
1427
+ }
1428
+ ```
1429
+
1430
+ 新增组件务必追加对应条目,否则 Demo 侧栏不会展示。
1431
+
1432
+ ---
1433
+
1434
+ ## 9. 新增组件 Checklist
1435
+
1436
+ - [ ] Google Fonts 已在 `index.html` 或样式入口引入(Nunito + Noto Sans SC + Zen Maru Gothic)
1437
+ - [ ] Props interface 从组件文件导出
1438
+ - [ ] 所有 props 有 JSDoc 注释(中文 OK)
1439
+ - [ ] 有状态组件同时支持受控(`value`)和非受控(`defaultValue`)模式
1440
+ - [ ] `disabled` 状态:cursor: not-allowed + opacity 0.5~0.6 + 移除阴影
1441
+ - [ ] 颜色优先引用 `variables.less` token,避免硬编码 hex
1442
+ - [ ] 阴影使用暖色调(`#bdaea0` / `#d4c9b4` / `rgba(61,52,40,...)`),非冷黑
1443
+ - [ ] hover 时 `translateY(-1px 或 -4px)` + 阴影加深
1444
+ - [ ] active 时 `translateY(2px)` + 阴影减小
1445
+ - [ ] 焦点:输入类用 `#ffcc00`,按钮类用 `#19c8b9`
1446
+ - [ ] 动画使用 `@motion-duration-*` 和 `@motion-ease` token
1447
+ - [ ] 组件从 `src/index.ts` 导出
1448
+ - [ ] Demo 页创建于 `demo/components/`
1449
+ - [ ] Demo 在 `demo/ComponentPage.tsx` 中注册
1450
+ - [ ] `demo/pageInfo.ts` 追加 `{ title, desc }` 元信息