@teamix-evo/skills 0.3.0 → 0.4.0

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 (66) hide show
  1. package/manifest.json +61 -45
  2. package/package.json +2 -2
  3. package/{skills/teamix-evo-coding-conventions → src/teamix-evo-code-opentrek}/SKILL.md +18 -18
  4. package/{skills/teamix-evo-coding-conventions → src/teamix-evo-code-opentrek}/checklist.md +2 -2
  5. package/{skills/teamix-evo-coding-conventions → src/teamix-evo-code-opentrek}/reuse-first.md +25 -17
  6. package/src/teamix-evo-code-uni-manager/SKILL.md +95 -0
  7. package/src/teamix-evo-code-uni-manager/api-layering.md +370 -0
  8. package/src/teamix-evo-code-uni-manager/checklist.md +193 -0
  9. package/src/teamix-evo-code-uni-manager/error-and-loading.md +389 -0
  10. package/src/teamix-evo-code-uni-manager/file-structure.md +339 -0
  11. package/src/teamix-evo-code-uni-manager/forms-and-validation.md +459 -0
  12. package/src/teamix-evo-code-uni-manager/reuse-first.md +188 -0
  13. package/src/teamix-evo-code-uni-manager/routing-and-codesplit.md +450 -0
  14. package/src/teamix-evo-code-uni-manager/testing.md +396 -0
  15. package/src/teamix-evo-design-opentrek/SKILL.md +71 -0
  16. package/src/teamix-evo-design-opentrek/boundaries.md +513 -0
  17. package/src/teamix-evo-design-opentrek/brand.md +154 -0
  18. package/src/teamix-evo-design-opentrek/checklist.md +83 -0
  19. package/src/teamix-evo-design-opentrek/components.md +245 -0
  20. package/src/teamix-evo-design-opentrek/flows.md +51 -0
  21. package/src/teamix-evo-design-opentrek/foundations.md +271 -0
  22. package/src/teamix-evo-design-opentrek/generation-flow.md +185 -0
  23. package/src/teamix-evo-design-opentrek/patterns/dashboard.md +31 -0
  24. package/src/teamix-evo-design-opentrek/patterns/detail-page.md +202 -0
  25. package/src/teamix-evo-design-opentrek/patterns/form-page.md +289 -0
  26. package/src/teamix-evo-design-opentrek/patterns/list-page.md +334 -0
  27. package/src/teamix-evo-design-opentrek/patterns/page-types.md +154 -0
  28. package/src/teamix-evo-design-opentrek/philosophy.md +96 -0
  29. package/src/teamix-evo-design-opentrek/rules/README.md +39 -0
  30. package/src/teamix-evo-design-opentrek/rules/boundaries.rules.json +391 -0
  31. package/src/teamix-evo-design-uni-manager/SKILL.md +73 -0
  32. package/src/teamix-evo-design-uni-manager/boundaries.md +564 -0
  33. package/src/teamix-evo-design-uni-manager/brand.md +202 -0
  34. package/src/teamix-evo-design-uni-manager/checklist.md +115 -0
  35. package/src/teamix-evo-design-uni-manager/components.md +254 -0
  36. package/src/teamix-evo-design-uni-manager/flows.md +63 -0
  37. package/src/teamix-evo-design-uni-manager/foundations.md +258 -0
  38. package/src/teamix-evo-design-uni-manager/generation-flow.md +194 -0
  39. package/src/teamix-evo-design-uni-manager/patterns/dashboard.md +95 -0
  40. package/src/teamix-evo-design-uni-manager/patterns/detail-page.md +224 -0
  41. package/src/teamix-evo-design-uni-manager/patterns/form-page.md +329 -0
  42. package/src/teamix-evo-design-uni-manager/patterns/list-page.md +356 -0
  43. package/src/teamix-evo-design-uni-manager/patterns/page-types.md +165 -0
  44. package/src/teamix-evo-design-uni-manager/philosophy.md +106 -0
  45. package/src/teamix-evo-design-uni-manager/rules/README.md +49 -0
  46. package/src/teamix-evo-design-uni-manager/rules/boundaries.rules.json +418 -0
  47. package/src/teamix-evo-manage/SKILL.md +281 -0
  48. package/skills/teamix-evo-design-rules/SKILL.md +0 -86
  49. package/skills/teamix-evo-design-rules/boundaries.md +0 -89
  50. package/skills/teamix-evo-design-rules/checklist.md +0 -108
  51. package/skills/teamix-evo-design-rules/generation-flow.md +0 -142
  52. package/skills/teamix-evo-design-rules/prompts/page-design.md +0 -148
  53. package/skills/teamix-evo-design-rules-opentrek/SKILL.md +0 -48
  54. package/skills/teamix-evo-design-rules-opentrek/brand-rules.md +0 -74
  55. package/skills/teamix-evo-design-rules-uni-manager/SKILL.md +0 -51
  56. package/skills/teamix-evo-design-rules-uni-manager/ai-scenarios.md +0 -51
  57. package/skills/teamix-evo-design-rules-uni-manager/command-center.md +0 -108
  58. package/skills/teamix-evo-design-rules-uni-manager/danger-ops.md +0 -87
  59. package/skills/teamix-evo-manage/SKILL.md +0 -178
  60. package/skills/teamix-evo-ui-upgrade/SKILL.md +0 -75
  61. /package/{skills/teamix-evo-coding-conventions → src/teamix-evo-code-opentrek}/api-layering.md +0 -0
  62. /package/{skills/teamix-evo-coding-conventions → src/teamix-evo-code-opentrek}/error-and-loading.md +0 -0
  63. /package/{skills/teamix-evo-coding-conventions → src/teamix-evo-code-opentrek}/file-structure.md +0 -0
  64. /package/{skills/teamix-evo-coding-conventions → src/teamix-evo-code-opentrek}/forms-and-validation.md +0 -0
  65. /package/{skills/teamix-evo-coding-conventions → src/teamix-evo-code-opentrek}/routing-and-codesplit.md +0 -0
  66. /package/{skills/teamix-evo-coding-conventions → src/teamix-evo-code-opentrek}/testing.md +0 -0
@@ -0,0 +1,513 @@
1
+ # 硬约束 · Boundaries
2
+
3
+ > 本文件列出所有"AI 生成页面 / 组件代码时**不能做什么**"的硬规则。共 38 条规则分 5 组:
4
+ >
5
+ > - **F1-F10**:禁止项(视觉与 token 层面)
6
+ > - **FF1-FF4**:表单专属硬约束(错误信息、必填、状态色块、Card 嵌套)
7
+ > - **S1-S8**:样式规则(className 写法)
8
+ > - **C1-C12**:组件结构规则(shadcn/ui 复合组件用法)
9
+ > - **I1-I4**:图标规则
10
+ >
11
+ > 严重等级:`ERROR` 必须修复,`WARN` 建议修复。
12
+ >
13
+ > **本文件是硬规则的唯一真值**。其他 skill 文件(patterns / components / brand / philosophy)遇到规则引用一律 `[boundaries.md X#]` inline 链接,不复述。
14
+
15
+ ---
16
+
17
+ ## F1-F10 · 禁止项
18
+
19
+ ### [ERROR] F1 · 禁止硬编码色值
20
+
21
+ ```diff
22
+ - <div style={{ color: '#333333' }}>...</div>
23
+ - <div className="text-[#333333]">...</div>
24
+ + <div className="text-foreground">...</div>
25
+ ```
26
+
27
+ 使用 CSS 变量引用,参照 [foundations.md](./foundations.md) §色彩。
28
+
29
+ > 检查: eslint `teamix-evo/no-color-literal` (JSX/TSX 字符串) · stylelint `teamix-evo/no-color-literal` (CSS 声明)
30
+
31
+ ### [ERROR] F2 · 禁止硬编码尺寸
32
+
33
+ ```diff
34
+ - <input className="h-8 text-xs" />
35
+ + <Input /> {/* 组件已封装 token */}
36
+ ```
37
+
38
+ 不要绕过组件用 Tailwind 任意值(`h-[32px]` / `text-[12px]`)覆盖默认尺寸。
39
+
40
+ > 例外:`*-[var(--xxx)]` 形式(CSS 变量包裹的任意值)允许使用,因为变量本身就是 token。详见 [F7]。
41
+ >
42
+ > 检查: eslint `teamix-evo/no-arbitrary-tw-value` (Tailwind className) · stylelint `teamix-evo/no-hardcoded-dimension` (CSS gap/padding/margin/width/height/font-size 等)
43
+
44
+ ### [ERROR] F3 · 禁止按组件新增重复语义变量
45
+
46
+ 新增 CSS 变量前**必须**先检索 `tokens/theme.css`:
47
+
48
+ - 已有语义匹配的变量 → 直接复用
49
+ - 完全没有可对应变量 → 才允许新增(提交前过 architect subagent 评审)
50
+
51
+ > 检查: 无 lint (人工评审 / architect subagent)
52
+
53
+ ### [ERROR] F4 · 禁止页头添加底色或下边框 · scope: PageHeader
54
+
55
+ ```diff
56
+ - <PageHeader className="bg-card border-b">
57
+ + <PageHeader> {/* 透明无底色 */}
58
+ ```
59
+
60
+ > 检查: 无 lint (人工评审 / Storybook visual diff)
61
+
62
+ ### [ERROR] F5 · outline 按钮禁止使用 border-input · scope: Button
63
+
64
+ ```diff
65
+ - <Button variant="outline" className="border-input">
66
+ + <Button variant="outline"> {/* 默认已使用 border-gray-line */}
67
+ ```
68
+
69
+ > 检查: 无 lint (人工评审 / Button.stories visual diff)
70
+
71
+ ### [ERROR] F6 · 禁止直接写 `font-size: 12px`
72
+
73
+ 使用 token:`text-xs` / `text-sm` / `text-base`,或 CSS 变量 `var(--input-font-size)`。
74
+
75
+ > 检查: stylelint `teamix-evo/no-hardcoded-dimension` (CSS `font-size`) · eslint `teamix-evo/no-arbitrary-tw-value` (Tailwind `text-[12px]`)
76
+
77
+ ### [ERROR] F7 · 语义间距必须走 CSS 变量
78
+
79
+ ```diff
80
+ - <div className="grid gap-4">
81
+ + <div className="grid gap-[var(--card-gap)]">
82
+ ```
83
+
84
+ 适用范围:
85
+
86
+ - **必须用变量**:Card、Tabs、Form、Section 等"具备语义间距"的容器 —— 用 `gap-[var(--card-gap)]` / `gap-[var(--form-gap)]`。
87
+ - **允许用 token 类**:列表、网格、表单内一般行间距等通用容器允许 `gap-2/4/6`(这些是 Tailwind 已映射 token 的预设类,不是任意值)。
88
+ - **禁止用裸数字任意值**:`gap-[16px]` / `gap-[1rem]` 是 [F2] 禁止的硬编码,永远不允许。
89
+
90
+ 判定关键:`*-[var(--xxx)]` 形态走 token、合规;`*-[16px]` 形态硬编码、违规。
91
+
92
+ > 检查: eslint `teamix-evo/no-arbitrary-tw-value` (Tailwind `gap-[16px]`,`*-[var(--…)]` 是允许的例外) · stylelint `teamix-evo/no-hardcoded-dimension` (CSS `gap`/`row-gap`/`column-gap`)
93
+
94
+ ### [ERROR] F8 · 禁止在 DialogTitle 中加图标 · scope: Dialog
95
+
96
+ ```diff
97
+ - <DialogTitle><AlertIcon /> 永久删除</DialogTitle>
98
+ + <DialogTitle>永久删除</DialogTitle>
99
+ ```
100
+
101
+ 标题区只放纯文字。如需视觉提醒,用 `variant="destructive"` 或 DialogDescription 表达。
102
+
103
+ > 检查: 无 lint (人工评审,可由 reviewer subagent 抽检 Dialog 用法)
104
+
105
+ ### [ERROR] F9 · 弹窗确定按钮禁止加 disabled 禁用态 · scope: Dialog
106
+
107
+ ```diff
108
+ - <Button type="submit" disabled={!isValid}>提交</Button>
109
+ + <Button type="submit">提交</Button>
110
+ {/* 始终可点击,校验后通过 inline error / Toast 反馈 */}
111
+ ```
112
+
113
+ 理由:禁用态切断了"为什么不能提交"的反馈链路,改用 inline error 显式说明。
114
+
115
+ > 检查: 无 lint (UX 评审 / scenario-instantiator subagent)
116
+
117
+ ### [WARN] F10 · hover 时禁止将 boxShadow 设为 undefined · scope: HoverCard
118
+
119
+ 切换 box-shadow 必须保留初始值 + 通过 animation 过渡,否则会引发布局抖动。
120
+
121
+ > 检查: 无 lint (Storybook hover 交互验证)
122
+
123
+ ---
124
+
125
+ ## FF1-FF4 · 表单专属硬约束
126
+
127
+ > 来自源仓 `teamix-evo-design/src/form-page.json` 的表单反模式。
128
+ > 注:DialogTitle 不加图标(源仓 F6) 与 提交按钮不可 disabled(源仓 F2) 已分别由 [F8] / [F9] 覆盖,本节只收录无重叠的 4 条。
129
+
130
+ ### [ERROR] FF1 · 禁止用色块表达表单状态 · scope: Form
131
+
132
+ ```diff
133
+ - <div className="bg-red-50 border-red-300 p-3">用户名已存在</div>
134
+ + <div className="text-destructive text-sm">用户名已存在</div>
135
+ + {/* 或 */}
136
+ + <Alert variant="destructive">...</Alert>
137
+ ```
138
+
139
+ 表单字段错误用 `text-destructive` 文字 + 图标前缀;页面级错误用 `<Alert>`;不要为单字段错误造彩色块,会与 Dialog 内主色冲突且增加视觉噪音。
140
+
141
+ > 检查: eslint `teamix-evo/no-raw-color-scale` (拦截 `bg-red-50`) · 模式识别需评审
142
+
143
+ ### [WARN] FF2 · Card 不嵌套 Card · scope: Form
144
+
145
+ ```diff
146
+ - <Card>
147
+ - <Card>
148
+ - <FieldGroup>...</FieldGroup>
149
+ - </Card>
150
+ - </Card>
151
+ + <Card>
152
+ + <FieldGroup>...</FieldGroup>
153
+ + <Separator />
154
+ + <FieldGroup>...</FieldGroup>
155
+ + </Card>
156
+ ```
157
+
158
+ 白卡是表单页的**单例容器**(参 [list-page.md §9 嵌套约束](./patterns/list-page.md#9-嵌套约束) / [form-page.md §9](./patterns/form-page.md#9-嵌套约束))。分区表单确需嵌入子 Card 时,子 Card 必须有明确边框/阴影差异,且仅限**分区表单**用例(form-page.md §2.3)。
159
+
160
+ > 检查: 无 lint (人工评审 / reviewer subagent)
161
+
162
+ ### [ERROR] FF3 · 错误信息禁止暴露技术栈痕迹 · scope: Form
163
+
164
+ ```diff
165
+ - <FormMessage>POST /api/users failed: 500 Internal Server Error (stacktrace: at UserService.create...)</FormMessage>
166
+ - <FormMessage>ERR_DUPLICATE_KEY: violates unique constraint "users_email_key"</FormMessage>
167
+ + <FormMessage>该邮箱已被注册,请换一个或<a>登录</a></FormMessage>
168
+ ```
169
+
170
+ 不允许:HTTP status code、stack trace、SQL 错误片段、ORM 异常名。要给的是**用户能采取的下一步行动**。
171
+
172
+ > 检查: 无 lint (评审 / scenario-instantiator subagent 模拟错误链路)
173
+
174
+ ### [WARN] FF4 · 必填用红色 `*` 星号,放标签后空格 · scope: Form
175
+
176
+ ```diff
177
+ - <FormLabel>用户名 (required)</FormLabel>
178
+ - <FormLabel>用户名*</FormLabel>
179
+ + <FormLabel>用户名 <span className="text-destructive">*</span></FormLabel>
180
+ + {/* 推荐用项目封装的 <RequiredMark /> 或 FormLabel required={true} */}
181
+ ```
182
+
183
+ 不要 "(required)" / "(必填)" 文本,会增加阅读宽度;不要把 `*` 紧贴标签(影响 OCR / 截屏识别)。
184
+
185
+ > 检查: 无 lint (代码评审)
186
+
187
+ ---
188
+
189
+ ## S1-S8 · 样式规则
190
+
191
+ ### [ERROR] S1 · className 仅用于布局,不用于覆盖组件颜色 / 字体
192
+
193
+ ```diff
194
+ - <Button className="bg-blue-100 text-blue-900 font-bold">提交</Button>
195
+ + <Button>提交</Button> {/* 用 variant,不用 className 强改色 */}
196
+ - <Card className="text-red-500">...</Card>
197
+ + <Card><CardContent className="max-w-md mx-auto">...</CardContent></Card>
198
+ ```
199
+
200
+ className 只允许写**布局相关**类(`flex` / `grid` / `gap-*` / `max-w-*` / `mx-auto` / `space-*`)。
201
+
202
+ > 检查: 部分覆盖 — eslint `teamix-evo/no-color-literal` (色值字面量) + `teamix-evo/no-raw-color-scale` (Tailwind 色阶) 拦截显式颜色覆盖;字号/尺寸覆盖由 `no-arbitrary-tw-value` 处理。其余命名覆盖需评审。
203
+
204
+ ### [ERROR] S2 · 不用 `space-x-*` / `space-y-*`,改用 `flex + gap-*`
205
+
206
+ ```diff
207
+ - <div className="space-y-4">
208
+ + <div className="flex flex-col gap-4">
209
+ ```
210
+
211
+ 理由:space-_ 通过 margin 实现,会与第一项的外边距产生冲突;gap-_ 在 flex / grid 容器内统一管理。
212
+
213
+ > 检查: eslint `teamix-evo/prefer-gap-over-space`
214
+
215
+ ### [WARN] S3 · 等宽高用 `size-*`,不用 `w-* h-*`
216
+
217
+ ```diff
218
+ - <div className="w-10 h-10">
219
+ + <div className="size-10">
220
+ ```
221
+
222
+ > 检查: 无 lint (代码风格评审)
223
+
224
+ ### [WARN] S4 · 用 `truncate` 简写文本截断
225
+
226
+ ```diff
227
+ - <span className="overflow-hidden text-ellipsis whitespace-nowrap">
228
+ + <span className="truncate">
229
+ ```
230
+
231
+ > 检查: 无 lint (代码风格评审)
232
+
233
+ ### [ERROR] S5 · 不用手动 `dark:` 颜色覆盖,用语义 token
234
+
235
+ ```diff
236
+ - <div className="bg-white dark:bg-gray-950 text-black dark:text-white">
237
+ + <div className="bg-background text-foreground">
238
+ ```
239
+
240
+ CSS 变量已在 dark 模式下自动切换。手动 `dark:` 会绕过主题系统,破坏一致性。
241
+
242
+ > 检查: eslint `teamix-evo/no-manual-dark-classnames`
243
+
244
+ ### [ERROR] S6 · 用 `cn()` 处理条件类名,不用模板字符串三元
245
+
246
+ ```diff
247
+ - className={`flex ${isActive ? 'bg-primary' : 'bg-muted'}`}
248
+ + className={cn('flex', isActive ? 'bg-primary text-primary-foreground' : 'bg-muted')}
249
+ ```
250
+
251
+ `cn()` 来自 `@teamix-evo/ui` 工具函数,自动处理 tailwind-merge 冲突。
252
+
253
+ > 检查: 无 lint (代码评审 / 后续可加 ESLint 规则)
254
+
255
+ ### [ERROR] S7 · overlay 组件不手动设置 z-index
256
+
257
+ ```diff
258
+ - <Dialog><DialogContent className="z-50">
259
+ + <Dialog><DialogContent>
260
+ ```
261
+
262
+ 适用:`Dialog / Sheet / Drawer / Popover / Tooltip / DropdownMenu / HoverCard`。组件自带层级管理。
263
+
264
+ > 检查: 无 lint (运行时 / 评审,可由 reviewer subagent 抽检)
265
+
266
+ ### [ERROR] S8 · 不用原始色值表示状态
267
+
268
+ ```diff
269
+ - <span className="text-emerald-600">+20.1%</span>
270
+ + <Badge variant="secondary">+20.1%</Badge>
271
+
272
+ - <span className="text-red-500">-3.2%</span>
273
+ + <span className="text-destructive">-3.2%</span>
274
+ ```
275
+
276
+ 状态信息一律走语义 token / Badge variant。
277
+
278
+ > 检查: eslint `teamix-evo/no-raw-color-scale` (拦截 `text-emerald-600` 等原始色阶)
279
+
280
+ ---
281
+
282
+ ## C1-C12 · 组件结构规则
283
+
284
+ ### [ERROR] C1 · Item 必须在 Group 内
285
+
286
+ 适用:`SelectItem / DropdownMenuItem / CommandItem / MenubarItem / ContextMenuItem`
287
+
288
+ ```diff
289
+ - <SelectContent>
290
+ - <SelectItem value="a">Apple</SelectItem>
291
+ - </SelectContent>
292
+ + <SelectContent>
293
+ + <SelectGroup>
294
+ + <SelectItem value="a">Apple</SelectItem>
295
+ + </SelectGroup>
296
+ + </SelectContent>
297
+ ```
298
+
299
+ | Item | Group |
300
+ | ---------------------------------------- | ------------------- |
301
+ | `SelectItem` / `SelectLabel` | `SelectGroup` |
302
+ | `DropdownMenuItem` / `DropdownMenuLabel` | `DropdownMenuGroup` |
303
+ | `CommandItem` | `CommandGroup` |
304
+ | `MenubarItem` | `MenubarGroup` |
305
+ | `ContextMenuItem` | `ContextMenuGroup` |
306
+
307
+ > 检查: 无 lint (后续可加 ESLint JSX 结构规则,目前由 reviewer subagent 抽检)
308
+
309
+ ### [ERROR] C2 · Dialog / Sheet / Drawer 必须有 Title
310
+
311
+ ```diff
312
+ - <DialogContent>...</DialogContent>
313
+ + <DialogContent>
314
+ + <DialogHeader>
315
+ + <DialogTitle>编辑配置</DialogTitle>
316
+ + <DialogDescription>修改资源参数</DialogDescription>
317
+ + </DialogHeader>
318
+ + ...
319
+ + </DialogContent>
320
+ ```
321
+
322
+ 无障碍要求。如视觉上不需要标题,用 `<VisuallyHidden>` 或 sr-only 包裹但保留语义。
323
+
324
+ > 检查: eslint `teamix-evo/dialog-must-have-title`
325
+
326
+ ### [WARN] C3 · Card 用完整结构
327
+
328
+ ```diff
329
+ - <Card><CardContent>标题 + 内容 + 操作</CardContent></Card>
330
+ + <Card>
331
+ + <CardHeader>
332
+ + <CardTitle>团队成员</CardTitle>
333
+ + <CardDescription>管理团队访问权限</CardDescription>
334
+ + </CardHeader>
335
+ + <CardContent>...</CardContent>
336
+ + <CardFooter><Button>邀请</Button></CardFooter>
337
+ + </Card>
338
+ ```
339
+
340
+ > 检查: 无 lint (人工评审)
341
+
342
+ ### [ERROR] C4 · Button 用 Spinner + disabled 组合表达 loading
343
+
344
+ ```diff
345
+ - <Button isPending>保存中...</Button>
346
+ + <Button disabled><Spinner data-icon="inline-start" /> 保存中...</Button>
347
+ ```
348
+
349
+ 或直接用 `<Button loading>` —— `@teamix-evo/ui` Button 已封装 loading prop。
350
+
351
+ > 检查: 无 lint (代码评审 / Storybook loading 故事)
352
+
353
+ ### [ERROR] C5 · TabsTrigger 必须在 TabsList 内
354
+
355
+ ```diff
356
+ - <Tabs><TabsTrigger value="a">账户</TabsTrigger></Tabs>
357
+ + <Tabs defaultValue="account">
358
+ + <TabsList>
359
+ + <TabsTrigger value="account">账户</TabsTrigger>
360
+ + </TabsList>
361
+ + <TabsContent value="account">...</TabsContent>
362
+ + </Tabs>
363
+ ```
364
+
365
+ > 检查: 无 lint (后续可加 JSX 结构规则)
366
+
367
+ ### [WARN] C6 · Avatar 必须有 AvatarFallback
368
+
369
+ ```diff
370
+ - <Avatar><AvatarImage src="/avatar.png" /></Avatar>
371
+ + <Avatar>
372
+ + <AvatarImage src="/avatar.png" alt="User" />
373
+ + <AvatarFallback>JD</AvatarFallback>
374
+ + </Avatar>
375
+ ```
376
+
377
+ > 检查: 无 lint (代码评审)
378
+
379
+ ### [WARN] C7 · 提示用 Alert,不用自定义 div
380
+
381
+ ```diff
382
+ - <div className="border border-red-500 p-4">Warning...</div>
383
+ + <Alert variant="destructive">
384
+ + <AlertTitle>警告</AlertTitle>
385
+ + <AlertDescription>需要关注的内容</AlertDescription>
386
+ + </Alert>
387
+ ```
388
+
389
+ > 检查: eslint `teamix-evo/no-color-literal` + `no-raw-color-scale` 拦截"自定义警示框"的色值,但容器结构需评审
390
+
391
+ ### [WARN] C8 · 空状态用 Empty 组件
392
+
393
+ ```diff
394
+ - <div className="flex flex-col items-center p-8">
395
+ - <p>暂无数据</p>
396
+ - <Button>创建</Button>
397
+ - </div>
398
+ + <Empty>
399
+ + <EmptyHeader>
400
+ + <EmptyTitle>暂无项目</EmptyTitle>
401
+ + <EmptyDescription>创建第一个项目以开始</EmptyDescription>
402
+ + </EmptyHeader>
403
+ + <EmptyContent><Button>创建项目</Button></EmptyContent>
404
+ + </Empty>
405
+ ```
406
+
407
+ > 检查: 无 lint (代码评审)
408
+
409
+ ### [WARN] C9 · Toast 用 sonner
410
+
411
+ ```diff
412
+ - alert("Changes saved");
413
+ - 自定义 toast 组件
414
+ + import { toast } from "sonner";
415
+ + toast.success("已保存修改");
416
+ ```
417
+
418
+ > 检查: 无 lint (依赖审计 / 代码评审)
419
+
420
+ ### [WARN] C10 · 分隔线用 Separator
421
+
422
+ ```diff
423
+ - <hr />
424
+ - <div className="border-t" />
425
+ + <Separator />
426
+ ```
427
+
428
+ > 检查: 无 lint (代码评审)
429
+
430
+ ### [WARN] C11 · 加载占位用 Skeleton
431
+
432
+ ```diff
433
+ - <div className="animate-pulse bg-gray-200 h-4 w-3/4" />
434
+ + <Skeleton className="h-4 w-3/4" />
435
+ ```
436
+
437
+ > 检查: eslint `teamix-evo/no-raw-color-scale` 部分覆盖 (拦截 `bg-gray-200`),但模式识别仍需评审
438
+
439
+ ### [WARN] C12 · 标签 / 状态用 Badge
440
+
441
+ ```diff
442
+ - <span className="rounded-full bg-green-100 text-green-800">Active</span>
443
+ + <Badge variant="secondary">Active</Badge>
444
+ ```
445
+
446
+ > 检查: eslint `teamix-evo/no-raw-color-scale` (拦截 `bg-green-100` / `text-green-800`)
447
+
448
+ ---
449
+
450
+ ## I1-I4 · 图标规则
451
+
452
+ ### [ERROR] I1 · 按钮内图标用 data-icon 属性定位
453
+
454
+ ```diff
455
+ - <Button><SearchIcon className="mr-2 size-4" /> 搜索</Button>
456
+ + <Button><SearchIcon data-icon="inline-start" /> 搜索</Button>
457
+ + <Button>下一步 <ArrowRightIcon data-icon="inline-end" /></Button>
458
+ ```
459
+
460
+ > 检查: 无 lint (代码评审,可由 reviewer subagent 抽检 Button 内图标)
461
+
462
+ ### [ERROR] I2 · 组件内图标不设尺寸类
463
+
464
+ 适用:`Button` / `DropdownMenuItem` / `Alert` / `Sidebar*`
465
+
466
+ ```diff
467
+ - <Button><SettingsIcon className="mr-2 size-4" /></Button>
468
+ + <Button><SettingsIcon /></Button> {/* 组件 CSS 控制尺寸 */}
469
+ ```
470
+
471
+ > 检查: 无 lint (Button/Item 容器内 icon 尺寸由 component CSS 强制,代码评审)
472
+
473
+ ### [ERROR] I3 · 图标作为组件对象传递
474
+
475
+ ```diff
476
+ - const iconMap = { check: CheckIcon };
477
+ - <StatusBadge icon="check" />
478
+ + function StatusBadge({ icon: Icon }) { return <Icon /> }
479
+ + <StatusBadge icon={CheckIcon} />
480
+ ```
481
+
482
+ > 检查: 无 lint (API 设计评审)
483
+
484
+ ### [ERROR] I4 · 按项目配置的 iconLibrary 导入
485
+
486
+ `@teamix-evo/ui` OpenTrek 变体默认使用 `lucide-react`。如项目切换图标库,遵循 `tokens.overrides.css` 中的 `--icon-library` 配置。
487
+
488
+ > 检查: eslint `teamix-evo/icon-from-lucide` (拦截 import 自非配置图标库)
489
+
490
+ ---
491
+
492
+ ## Overlay 组件选型表
493
+
494
+ | 场景 | 组件 |
495
+ | ---------------------- | ----------------------------------- |
496
+ | 需要输入的任务 | `Dialog` |
497
+ | 危险操作确认 | `AlertDialog variant="destructive"` |
498
+ | 侧面板(详情 / 筛选) | `Sheet` |
499
+ | 移动端底部面板 | `Drawer` |
500
+ | 悬浮信息(hover 触发) | `HoverCard` |
501
+ | 点击弹出小内容 | `Popover` |
502
+
503
+ ---
504
+
505
+ ## 自定义优先级
506
+
507
+ 需要差异化样式时按以下优先级:
508
+
509
+ 1. **优先**:内置 `variant`(如 `variant="outline"` / `variant="destructive"`)
510
+ 2. **其次**:语义 token(如 `bg-primary` / `text-muted-foreground`)
511
+ 3. **最后**:CSS 变量覆盖(在 `tokens.overrides.css` 中定义)
512
+
513
+ **严禁**:直接 className 覆盖颜色 / 字号 / 尺寸(违反 S1)。
@@ -0,0 +1,154 @@
1
+ # Brand — OpenTrek 视觉调性 + 文案语气 + 正反例
2
+
3
+ > OpenTrek 服务于运维与平台管理场景。本文是品牌定标尺:所有视觉、文案决策不应越过这里定义的边界。
4
+
5
+ ---
6
+
7
+ ## 1. 视觉风格五维
8
+
9
+ | 维度 | 定位 | 具体表现 | 对立面(禁止) |
10
+ | ------------ | -------- | --------------------------------------- | -------------------- |
11
+ | **色彩情绪** | 沉稳专业 | 深色底色为主基调 + 高对比度信息层级 | 花哨多彩、渐变堆叠 |
12
+ | **信息密度** | 高效紧凑 | 单屏承载核心操作,减少翻页 | 大面积留白、装饰占位 |
13
+ | **视觉层次** | 克制有序 | 间距、字重、色彩建立 3 级层级 | 多重强调、全部高亮 |
14
+ | **交互反馈** | 即时确定 | 操作后 200ms 内明确反馈 | 模糊状态、静默 |
15
+ | **圆角风格** | 轻圆角 | `rounded-md` (6px) / `rounded-lg` (8px) | 全直角、超大圆角 |
16
+
17
+ ---
18
+
19
+ ## 2. 情感矩阵
20
+
21
+ ```
22
+ 可信赖 ████████████████████ 95% ← 不可让步
23
+ 高效率 ███████████████████░ 90% ← 不可让步
24
+ 专业感 ██████████████████░░ 85%
25
+ 现代感 ████████████████░░░░ 75%
26
+ 亲和力 ███████████░░░░░░░░░ 55% ← 次要,不刻意追求
27
+ 趣味性 ████░░░░░░░░░░░░░░░░ 20% ← 极度克制
28
+ ```
29
+
30
+ > "可信赖" 与 "高效率" 是不能让步的两根支柱。"亲和力" 与 "趣味性" 刻意低,避免在严肃场景产生轻浮感。
31
+
32
+ ---
33
+
34
+ ## 3. 品牌个性
35
+
36
+ | 特征 | 描述 | 设计映射 |
37
+ | -------- | ------------------------------ | ------------------------------ |
38
+ | **稳定** | 云基础设施核心诉求是"不出问题" | 一致的布局骨架、可预期的交互 |
39
+ | **透明** | 用户需要知道系统正在做什么 | 状态指示器、进度反馈、操作确认 |
40
+ | **掌控** | 管理员需要"全局在握"的感觉 | 数据概览、筛选能力、批量操作 |
41
+ | **专注** | 运维操作容错率低 | 清晰的信息层级、防误操作确认 |
42
+
43
+ ### Moodboard 参考
44
+
45
+ - 开发者控制台:Vercel、Linear、Datadog、PlanetScale
46
+ - 现代企业 SaaS:Notion Admin、Stripe Dashboard
47
+ - 工程化文档:Tailwind / shadcn / Radix UI Docs
48
+
49
+ ---
50
+
51
+ ## 4. 文案语气总体风格
52
+
53
+ > **精确 > 友好。简短 > 完整。可执行 > 可理解。**
54
+ >
55
+ > 不卖萌、不感叹、不"恭喜你"。所有文案以**"是否帮助用户做下一步决策"**为唯一评价标准。
56
+
57
+ ### 4.1 语气矩阵
58
+
59
+ | 场景 | 语气 | ✅ 正例 | ❌ 反例 |
60
+ | ----------- | ---------------- | ---------------------------------- | ---------------------- |
61
+ | 标题 / 导航 | 名词、定语短句 | "实例列表" / "安全组规则" | "你的实例们" |
62
+ | 引导说明 | 简洁、可执行 | "选择资源后,可执行批量操作" | "快来选个资源试试吧~" |
63
+ | 主操作按钮 | 动宾结构、≤ 5 字 | "创建实例" / "释放资源" | "去创建一个新的实例" |
64
+ | 危险按钮 | 名词 + 动作 | "永久删除" / "立即停机" | "确认" / "OK" |
65
+ | 错误提示 | 具体原因 + 建议 | "实例正在运行中,请先停止后再删除" | "操作失败,请重试" |
66
+ | 成功反馈 | 已完成的事实 | "已释放 3 个实例" | "操作成功!🎉" |
67
+ | 空状态 | 解释 + 入口 | "暂无实例。创建第一个实例以开始" | "这里空空如也~" |
68
+ | 加载提示 | 进行时 | "正在加载实例…" | "马上就好~" |
69
+
70
+ ### 4.2 写作规范
71
+
72
+ 1. **动词在前** — 按钮以动词开头:「创建项目」非「项目创建」
73
+ 2. **避免歧义** — 「删除」与「释放」严格区分(删除不可恢复 / 释放进入回收站)
74
+ 3. **不省略主语** — 错误信息指出"什么"出错:「实例 i-xxx 启动失败」非「启动失败」
75
+ 4. **量词精确** — "已删除 3 项" 而非 "已删除几项"
76
+ 5. **主动语态** — "系统已保存配置" 而非 "配置已被系统保存"
77
+
78
+ ### 4.3 标点与排版
79
+
80
+ - 按钮文字 / 表头标签:**不加**句号
81
+ - 描述、提示、说明:**完整句子** + 句号
82
+ - 列表项格式统一(全加句号 或 全不加)
83
+ - 中英文 / 中数字之间加 1 空格:`已选 3 项 / 共 128 项`
84
+ - 数字使用半角;区间用 `~`(中文)/ `–`(英文)
85
+ - 时间格式统一:`2026-05-14 10:23:45`(ISO-like)
86
+
87
+ ---
88
+
89
+ ## 5. 危险操作专用文案(硬约束)
90
+
91
+ 破坏性操作(删除、释放、强制重启)必须满足:
92
+
93
+ | 元素 | 规则 | 示例 |
94
+ | -------------------- | ---------------- | ------------------------------------------------------------------------- |
95
+ | **AlertDialog 标题** | 陈述句而非疑问句 | ✅「永久删除实例 i-xxx」 ❌「确定要删除吗?」 |
96
+ | **正文** | 列出具体后果 | ✅「该实例的数据盘将被释放且不可恢复。关联的快照(共 2 个)将一并删除。」 |
97
+ | **确认按钮** | 重复动作动词 | ✅「永久删除」 ❌「确认」 |
98
+ | **取消按钮** | 用「取消」 | ❌「不」/「再想想」 |
99
+
100
+ ---
101
+
102
+ ## 6. AI 场景文案规则
103
+
104
+ AI 助手在生成回复时遵循:
105
+
106
+ - **不使用**第一人称「我」(避免拟人化)→ 用「OpenTrek AI」或省略主语
107
+ - 操作建议必须给出**确定性** + **量化影响**:「建议将实例规格升级至 ecs.g7.large(预计成本 +¥120/月)」
108
+ - 不确定时**明确表达**:「此问题可能由 A、B 两个原因引起,建议先排查 A」
109
+ - 拒绝执行不可逆操作时给出明确原因 + 替代路径
110
+
111
+ ---
112
+
113
+ ## 7. 视觉正反例对照
114
+
115
+ ### 7.1 布局
116
+
117
+ | ✅ 正例 | ❌ 反例 |
118
+ | ---------------------------------------------------------------- | ---------------------------------------- |
119
+ | ListPage 搜索/筛选固定顶部,表格自适应高度,分页固定底部 | 同一页面同时使用左右两套 Sidebar |
120
+ | 表单左对齐标签,字段按"必填 → 可选"排序,主操作右下角 | 主操作按钮放在一屏之外(需滚动才能看到) |
121
+ | 详情页 Tab 顺序:基本信息 → 监控 → 配置 → 操作日志(按使用频率) | 表单字段按字母顺序排序(忽略业务优先级) |
122
+
123
+ ### 7.2 色彩
124
+
125
+ | ✅ 正确 | ❌ 错误 |
126
+ | -------------------------------------------------------------------- | ------------------------------------ |
127
+ | 主色仅用于主行动点(CTA 按钮、当前选中项、品牌标识) | 用主色表示"错误"状态 |
128
+ | 状态色:`destructive` = 错误/删除;绿/黄按业务语义;图表用 `chart-*` | 把 `destructive` 红色用在 Tab 选中态 |
129
+ | 暗色模式直接切换 CSS 变量,不重写组件 | 同一页面 4 种以上"重要"按钮颜色 |
130
+
131
+ ### 7.3 动效
132
+
133
+ | ✅ 正确 | ❌ 错误 |
134
+ | -------------------------------------------------------- | ------------------------------------------------------ |
135
+ | Hover 色彩切换 `transition-colors duration-150 ease-out` | 给 width / height / margin 加过渡(性能差 + 布局抖动) |
136
+ | 弹窗入场 `zoom-in-95 + fade-in` 300ms | 整页加载用复杂 Loader + 进度条(用 Skeleton 即可) |
137
+ | Skeleton 占位 → 数据到达后 `fade-in` | 微交互动效超过 200ms(hover 不应让用户等待) |
138
+
139
+ ### 7.4 圆角与阴影对应表
140
+
141
+ > **完整对应表见 [foundations.md §6.3 圆角 × 阴影对应表](./foundations.md#63-圆角--阴影对应表)** — 圆角与阴影必须同档对应,这是 foundations 层的语义归一规则,brand 层不再重复。
142
+
143
+ ---
144
+
145
+ ## 8. 品牌自检
146
+
147
+ - [ ] 文案动词在前,按钮 ≤ 5 字
148
+ - [ ] 错误提示含主语 + 原因 + 建议
149
+ - [ ] 危险操作 AlertDialog 标题用陈述句、按钮用动作动词
150
+ - [ ] 不出现 emoji 表情、感叹号过多、拟人化主语「我」
151
+ - [ ] 主色仅用于 CTA 与当前选中态,不滥用
152
+ - [ ] 圆角阴影同档对应(rounded-md ↔ shadow-sm ↔ rounded-lg ↔ shadow-md/xl)
153
+ - [ ] 动效仅 transition-colors / opacity / transform,禁 width/height/margin
154
+ - [ ] 中英文之间有空格,时间格式统一 ISO-like