设计系统
在三个阶段提供相同的专业知识。编排器显式传递模式。
| 模式 | 时间 | 问题 |
|---|---|---|
| PLAN | 功能开发阶段2 | 此功能应使用哪些模式/抽象? |
| BUILD | 功能开发阶段4 | 在实现时应用PLAN决策。 |
| REVIEW | 功能开发阶段5 | 实现是否实际遵循了这些决策? |
当模式未指定且存在分支差异时,默认使用REVIEW模式。 当模式未指定且尚无差异时,默认使用PLAN模式。
PLAN模式
在代码存在之前。输入:细化简报、Figma节点或截图、作用域内的路由。
- 搜索模式库(
src/index.ts、src/theme.ts、src/core/)和app-pro-ui中类似的功能。 - 对设计中的每个主要UI元素运行抽象测试(见下文)。
- 对于每个元素:保留本地 | 使用现有的PL API | 令牌/变体 | 需要PL PR——并附上已引用的路径。
- 标记PL排序(PL PR在app-pro-ui之前/与之并行)以及缺失的文案/资源。
如果没有UI界面:在一行内返回不适用(无UI)。
输出: # 设计系统(PLAN):[功能] —— 复用列表、预期更改、排序。不需要分支差异。
BUILD模式
在实现期间。输入:设计系统PLAN输出、正在编辑的文件。
- 应用PLAN决策:使用命名的PL组件/令牌;尊重保留本地的调用。
- 遵循下面的推理层 —— 不要在功能代码中重新创建可复用的外观。
- 如果在编码过程中发现PLAN有误,请在构建摘要中记录偏差;不要无声地漂移。
输出: 除非有偏差,否则不需要输出 — 然后在构建摘要中注明。
REVIEW模式
在实现之后。扫描此分支(app-pro-ui或pattern-library)中应属于设计系统的UI决策。不要只说“删除样式”或“使用共享组件”。优先选择最小的全局模式库更改,使任何功能都能做同样的事情——或者在没有充分的抽象理由时,建议保留本地实现。
这并不意味着“所有样式都属于模式库”。重复的产品/UX决策应越来越多地编码到系统中,以便各个构建者不必重新发明它们。功能代码仍可以在本地组合。
架构规则:可复用的视觉决策属于模式库。功能代码可以使用sx实现真正的本地布局/组合,但不应重新创建可复用的组件样式、令牌、状态或交互模式。当存在已建立的PL/MUI API时,避免使用style、自定义CSS和遗留的MUI系统属性。
此技能是DS层。对于app-pro-ui hook/util/网格结构和通用代码卫生,请使用refactoring技能。
推理层
根据以下规则判断每个发现。它们来自多年的模式库和app-pro-ui审查评论。优先选择现有API而非新API。将代码移入模式库并不自动是一种改进。
抽象测试
对每个候选配方、令牌或新API运行此测试。它是主要的判断依据——检测仅产生候选对象。
- 这是本地组合吗?
- 相同的配方是否也出现在其他地方?
- 此组件是否本应拥有此内容?
- 将其移到模式库是否会减少有意义的未来决策?
- 添加API是否实际上会使模式库变得更糟?
仅凭相似性并不能证明抽象的合理性。外观相似的两个代码片段可能代表不同的产品概念。当相同的产品/UX决策应一起演进时,优先选择共享抽象。
sx不是问题。问题在于设计决策存在于何处。主题令牌sx优于十六进制。重复的配方可能属于模式库。一次性的<Stack sx={{ mt: 2 }}>通常则不然。如果测试表明本地方案是正确的,则将其从发现项中省略——不要将其列为低优先级。
1. 使用设计系统 —— 不要在功能中重新样式化可复用的决策
- 对于可复用的产品模式,优先使用已建立的模式库组件(即使没有操作的
CardWithAction、作为复合卡的CardCTAFeatured、DetailPanelToggle)。不要从原始的Card重建这些组件。 - 当布局是本地时,优先使用MUI组合原语如
Stack/Grid,而不是自定义布局CSS。 - 在发明本地几何形状之前,使用已建立的布局原语和默认值。
- 将可复用的颜色、阴影和营销/AI处理放在
pattern-library/src/theme.ts中,作为调色板形状的令牌(primary.main、ai.gradient.start)。当值是产品决策时,优先选择令牌或theme.shadows,而不是硬编码的十六进制、填充或阴影。 - 使用
sx,而不是已弃用的MUI样式即属性。不要在共享组件上添加样式命名的属性来解决该问题。当是组合而不是可复用外观时,本地sx是可以的。 - 如果某个功能需要一个其他界面也将共享的新外观(特色媒体、展开叠加、倒置/营销界面),则在模式库中添加一个模式或属性。
2. 保持共享组件通用
- 不要在共享的
Card、PageSection或公共index.ts导出上添加特定于功能的填充、侧边导航或图表更改。限定原型范围;恢复无关文件。当只有项目出错时,更改项目,而不是外壳。 - 为复用命名属性(
footerDescription,而不是一个功能的标签)。额外行为是可选的(文本区域上的行号、逗号)。 - 优先选择主题变体和Storybook
args,而不是分叉的JSX(variant === "marketing"检查)。 - 如果应用不消费它们,则不要从模式库导出图表或其他内部组件。
- 长期来看,将界面包装在主题中(例如营销),而不是在每个页面上传递一次性视觉属性。
3. 边缘视觉质量检查
- 检查圆角、等高卡、孤立的包裹文本、移动FAB折叠、相对于抽屉/模态框的z-index,以及控件在白色背景上是否仍然有效。
- 询问是否需要特殊间距,或者默认样式是否已经匹配其他模态框/页面。不要填充共享标题以与不对齐的邻居对齐——而是修复邻居。
4. 质疑设计需求
在添加DS能力以支持不常见的设计之前,确定设计本身是否应遵循已建立的系统行为。不要仅仅为了编码一个可疑的一次性需求而扩展设计系统。
5. 抵制不必要的API表面
每个提议的DS抽象必须证明其添加的API表面的合理性。将代码移入模式库并不自动是一种改进。不改善体验的配置是维护成本。
仅保持DS-架构卫生:干扰组合的不必要包装、重复样式、组件API复杂性以及共享原语中的特定于功能的逻辑。当嵌套的Box干扰Stack/sx组合时,将其展平。对于简单令牌,使用主题简写(background.main)而不是useTheme。
6. 与相关界面一起发布
- 应用必须消费的模式库更改需要匹配的app-pro-ui或moz-ui PR以及验证它的方法(amplify/domain或等效)。
- 在推荐如何升级之前,从消费仓库(
package.json、lockfile或安装文档)确认当前的包/版本约定。不要假设固定风格。 - 在消费应用PR准备好之前,不要合并共享原语。
当被调用时(REVIEW模式)
复制并跟踪:
审查进度:
- [ ] 将此分支与合并基础进行比较
- [ ] 收集候选对象(非结论)
- [ ] 按意图聚类(相同的决策,而不是相同的代码)
- [ ] 运行抽象测试
- [ ] 搜索模式库以查找现有位置
- [ ] 推荐最小的更改 — 包括保留本地 / 不做DS更改
- [ ] 报告发现;除非被要求,否则不进行实现
并非必须发现工作。如果差异是适当的本地化,则说明情况并停止。
步骤1:扫描分支
检查此分支与其合并基础的差异。检测默认分支(git symbolic-ref refs/remotes/origin/HEAD 或 origin/main,然后 main)。从包含更改的仓库(app-pro-ui 或 pattern-library)运行。
DEFAULT=$(git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's@^refs/remotes/@@')
DEFAULT=${DEFAULT:-origin/main}
git merge-base "$DEFAULT" HEAD
git diff $(git merge-base "$DEFAULT" HEAD)...HEAD -- '*.tsx' '*.ts' '*.jsx' '*.js' '*.css' '*.scss'
git diff --name-only $(git merge-base "$DEFAULT" HEAD)...HEAD
在添加的行中搜索候选对象:
样式
style=sx=styled(css\`` /css(`makeStyles/createStyles/withStyles- 硬编码
#hex、rgb(、rgba(、px(调查;不要自动分类) - 遗留的Box属性:
display=、alignItems=、justifyContent=、flexDirection=
重新发明或漂移的UI
- 在已建立的卡模式(
CardWithAction、CardCTAFeatured)适用时使用原始Card - 自定义展开控件而非
DetailPanelToggle - 在
Stack/Grid可本地组合时使用自定义布局CSS - 在布局原语或默认值已设置宽度时发明页面几何形状
- 当阴影是共享外观时使用硬编码阴影而非
theme.shadows - 仅服务于一个功能的新公共导出或主题编辑
然后打开每个匹配项并阅读周围的JSX以了解意图。还要捕获JSX之前分配的sx对象、<style>标签以及导入的样式表。
忽略.cursor/、node_modules/、.next/。包括功能代码、共享的components/、Storybook和src/theme.ts。
步骤2:检测,然后判断
检测是启发式的。分类发生在抽象测试之后。
| 检测器 | 视为 | 示例 |
|---|---|---|
style= / styled( / css / 新的.css | 候选泄漏 | <Card style={{ flexBasis: "50%" }}> |
| 看起来编码了设计系统决策的硬编码视觉值,尤其是颜色、间距、排版、圆角、阴影和重复维度 | 候选令牌 | color: "#002F50";在视为泄漏之前调查px |
使用主题键的sx={{ ... }} | 候选配方 | sx={{ mt: 3, width: "100%" }} |
| 遗留的Box系统属性 | 候选遗留 | <Box display="flex" alignItems="center"> |
| 未使用的现有PL组件 | 候选现有系统方案 | 未包装在CardWithAction中的表格 |
| 共享组件上的特定于功能的编辑 | 候选范围泄漏 | 为匹配一个故事而添加在CardHeader上的填充 |
| 一个功能的属性或导出 | 候选非通用API | 功能命名的页脚属性;导出未使用的图表 |
在将硬编码值分类之前进行调查。合法的本地情况包括计算维度、图表几何形状、图标/画布内部、边框、虚拟化布局和固有组件约束。
最后手段的例外情况(记录原因;不要发明原语):
- 无法使用模式库属性的第三方/画布/图表内部
- 没有现有报告原语且真正一次性的打印/PDF布局
- 仅限原型的文件,未从模式库导出
通过抽象测试被判定为本地组合的候选对象不是发现项。仅在它们可能被误认为是差距时将它们放在不要提升下。否则忽略它们。
步骤3:按意图聚类
对表达相同决策的命中进行分组,而不是相同的CSS或外观相似的标记。
典型意图:颜色/强调、间距/对齐配方、排版、组件外壳、交互状态、功能模式(横幅、页面标题、卡片CTA、状态)、通用vs单功能API、原型范围、可疑的设计需求。
一个聚类 → 一个建议。优先选择一个强建议而不是同一发现的多个次要变体。
步骤4:首先搜索模式库
在提议任何新内容之前,先搜索兄弟pattern-library仓库。引用路径。
- 公共导出 —
pattern-library/src/index.ts - 令牌和全局默认值 —
pattern-library/src/theme.ts pattern-library/src/core/下的组件属性/变体- 已避免泄漏的同一组件在app-pro-ui中的现有用法
关于将UI吸收到DS的先例(引用这些;不要将内部复制到app-pro-ui中):
- 语义属性:
Typography中的lineClamp—pattern-library/src/core/Typography/Typography.tsx - 语义属性:
Button中的aiGlow—pattern-library/src/core/Button/Button.tsx