35 KiB
AtomUI 控件文档规范
本文档定义 AtomUI 控件级研发文档的结构、内容边界、写作规则和审查标准,适用于 AtomUI.Controls、AtomUI.Desktop.Controls、DataGrid、ColorPicker 以及其他控件包。
控件文档用于描述控件的最新设计状态、公共契约、交互模型、状态模型、主题架构、Token 边界、内部实现原理和维护规则。它不替代面向最终用户的站点文档、API reference、正式发布 CHANGELOG.md 或代码注释。
文档目录结构
每个控件必须使用独立目录承载文档:
docs/controls/<platform>/<category>/<control>/
├── overview.md
├── implementation.md
├── semantic-part.md # 条件必需,控件公开 Semantic Part 时提供
├── <topic>-design.md # 可选,复杂专项设计
├── token.md
└── changelog.md
要求:
overview.md必须存在,用于描述控件设计定位、公共契约、状态模型、视觉主题关系和维护入口。implementation.md必须存在,用于描述特定控件的内部实现原理、源码职责边界、关键状态流和维护规则,以提升控件可维护性。semantic-part.md在控件公开 Semantic Part 时必须存在,是完整 Part 表、逐 Part 说明、Selector 用法、定制边界、兼容性和验证要求的唯一正式来源。changelog.md必须存在,用于记录控件级设计、API、主题契约、Token 和实现结构变化。token.md仅当控件存在专属 Token 或复杂主题变量关系时存在。- 内容过多时可以继续拆分专题文档,但
overview.md只保留设计与契约主线,implementation.md只保留实现原理主线,并链接专题文档。 - 同一主题跨越 Public API、平台/状态策略、内部架构、Template、算法和验证边界时,使用本文定义的
<topic>-design.md控件专项设计文档,不把 Issue 分析、方案比较或实施计划塞入控件主文档。 - 分类入口文档必须链接控件目录中的主要文档。
Mobile Control 文档
docs/controls/mobile/ 及 AtomUI.Mobile.Controls 相关文档同时遵循
AtomUI Mobile 文档规范。同名 Desktop/Mobile Control 分别拥有独立的文档根和
Gallery 证据 ownership;iOS、Android、Release 与发布状态必须分开表达。
在 Mobile Control 的 Public API、Theme、Contract/Headless 测试和 Gallery API/Token/ShowCase 证据同时存在前,不创建 空的单 Control 文档目录。具体状态词、分类清单和同步门禁由 Mobile 专项规范维护,本文不重复。
写作原则
控件文档必须采用严谨、稳定、工程化的语言。
必须遵守:
- 描述最新设计状态,不写历史过程。
- 不使用“未来”“后续”“演进方向”等路线图表述。
- 不堆砌属性清单;属性必须服务于 API 模型、状态模型或兼容边界。
- 不重复全局规范;通用规则应链接全局规范文档。
- 不记录临时讨论、实现流水账或无长期维护价值的细节。
- API、主题契约、Token、template part、伪类等必须表述为稳定契约。
overview.md不展开具体代码实现,具体实现原理进入implementation.md。implementation.md不重复公共 API 清单、Token 全局规则或用户文档内容,只解释当前控件内部实现为什么这样组织、状态如何流动、维护时必须守住哪些边界。semantic-part.md只描述对应用公开的主题契约,不把PART_*、内部节点、视觉层级或实现类型提升为公共 Part。
历史变化统一进入控件级 changelog.md。
控件专项设计文档
控件专项设计文档用于描述一个控件内部具有独立语义、跨越公共契约与实现职责、且无法在
overview.md 或 implementation.md 中简洁说明的稳定设计主题。
典型主题包括:
- 跨平台窗口布局、原生能力投影或平台自适应策略。
- 复杂选择、展开、过滤、校验、异步加载或状态同步模型。
- 跨多个主题、presenter、popup host 或内部协作控件的组合机制。
- 具有明确公式、边界条件和生命周期约束的布局或数据算法。
- 同时影响 Public API、模板契约、内部职责和验证矩阵的专项能力。
专项设计文档不是独立的控件总览,也不替代实现文档。它只展开一个稳定设计主题,并由控件的
overview.md 和 implementation.md 提供导航。
创建条件
满足以下任一条件时可以创建专项设计文档:
- 同一主题同时涉及公共 API、内部架构、模板或平台适配,放入单一主文档会破坏其内容边界。
- 主题包含需要独立维护的术语、状态、区域、角色或数据模型。
- 主题包含跨平台、跨宿主、跨模式或跨窗口状态的策略矩阵。
- 主题包含维护者必须共同遵守的算法、公式、退化规则或时序不变量。
- 主题需要独立的兼容性、定制边界和分层验证要求。
以下情况不创建专项设计文档:
- 仅罗列少量属性、事件或方法。
- 仅记录一个私有方法或局部实现技巧。
- 仅记录 Issue 调查、截图分析、复现过程或根因取证。
- 仅比较候选方案、记录会议结论或实现计划。
- 仅记录版本变化、迁移过程、commit、PR 或发布说明。
- 内容能够在
overview.md或implementation.md的一个短小章节内完整表达。
文件位置与命名
专项设计文档与对应控件的主文档放在同一目录:
docs/controls/<platform>/<category>/<control>/
├── overview.md
├── implementation.md
├── <topic>-design.md
├── token.md
└── changelog.md
命名规则:
- 文件名使用稳定的英文 kebab-case 主题名,以
-design.md结尾。 - 标题使用
# <Control> <专项主题>设计。 - 主题名表达长期设计能力,不使用 Issue 编号、版本号、日期、分支名或修复动作。
- 同一主题只维护一份专项设计文档,不按平台或实现阶段复制多份。
示例:
window-title-bar/title-alignment-design.md
tree/selection-model-design.md
image-previewer/loading-pipeline-design.md
带日期的调查、迁移或方案记录继续放在对应的 specs、迁移记录或发布记录目录,不放入控件专项设计文档。
写作边界
专项设计文档只描述最终采用的设计状态,使用确定、稳定、可验证的工程语言。
必须遵守:
- 直接说明控件如何设计,不以 Issue、缺陷、截图、实现任务或讨论过程作为叙事入口。
- 描述采用的模型、契约、职责和算法,不保留候选方案比较或“不采用方案”章节。
- API 使用稳定语义描述,不使用“准备新增”“待实现”“当前尚不支持”等实施状态措辞。
- 文件结构表达稳定 ownership,不写成目标文件清单或任务拆分清单。
- 平台差异使用能力、metrics 和策略表达,不把当前开发机或本地路径当作设计事实。
- 算法必须定义输入、输出、坐标系、边界条件和退化规则。
- 兼容性必须描述不可破坏的契约和定制边界,不写一次性变更摘要。
- 验证要求必须对应设计不变量,不写与专项主题无关的通用测试清单。
不得包含:
- Issue 编号、截图像素取证、复现步骤和根因调查流水。
- 设计状态、实现状态、人员分工、排期、todo 或实施 checklist。
- commit、PR、tag、本地仓库路径或外部项目源码行号。
- 版本历史、迁移历史和 release note;这些内容进入
changelog.md或专项历史记录。 - 与控件专项主题无关的全局工程规范副本。
标准结构
专项设计文档按以下通用结构组织。允许根据主题合并相邻章节,但不能混淆内容职责。
# <Control> <专项主题>设计
1. 设计定位
2. 设计原则
3. 专项模型与 Public API
4. 变体、平台或状态策略
5. 架构、文件结构与职责
6. Template、组合与集成契约
7. 核心算法、数据流与生命周期
8. 资源、性能与 AOT 边界
9. 兼容性与定制边界
10. 验证要求
章节适用规则:
| 章节 | 要求 | 说明 |
|---|---|---|
| 设计定位 | 必须 | 说明专项能力解决什么设计职责,以及覆盖哪些控件、宿主或状态。 |
| 设计原则 | 必须 | 定义后续 API、策略和算法共同遵守的不变量。 |
| 专项模型与 Public API | 必须 | 先定义术语、区域、状态或角色模型,再说明相关公共契约;没有 Public API 时明确内部契约边界。 |
| 变体、平台或状态策略 | 条件必须 | 存在 Auto、平台、CSD、主题变体、模式或状态差异时必须提供映射或策略矩阵。 |
| 架构、文件结构与职责 | 必须 | 说明稳定模块结构、owner、输入输出和明确不负责的内容。 |
| Template、组合与集成契约 | 条件必须 | 涉及 ControlTheme、Template Part、internal presenter、host 或组合关系时必须说明。 |
| 核心算法、数据流与生命周期 | 条件必须 | 存在公式、状态同步、异步流程或资源获取释放时必须说明输入、流程、边界和退化。 |
| 资源、性能与 AOT 边界 | 必须评估 | 无专项影响时可以简短说明不引入额外资源、分配、反射或动态发现。 |
| 兼容性与定制边界 | 必须 | 说明稳定 API、默认值、模板、渲染、平台语义和外部定制责任。 |
| 验证要求 | 必须 | 按纯逻辑、控件行为、主题契约、平台实机、Gallery/demo 和 AOT 风险分层。 |
各章节内容要求
设计定位与原则
设计定位从控件能力出发,说明设计是什么、适用在哪里、与相邻职责如何分界。设计原则只记录能够约束后续 API、架构和算法的稳定规则,不写项目目标、实施收益或讨论结论。
专项模型与 Public API
先定义主题自己的术语和模型,例如:
- Leading、Title、Trailing 区域。
- selected、current、checked、expanded 状态 owner。
- loading pipeline、request、result 和 cancellation 状态。
- visible frame、content bounds、overlay bounds 等坐标语义。
Public API 按语义说明属性、枚举、事件和默认值。可以使用短代码片段准确表达契约,但不复制完整 API 表, 不把源码成员顺序改写成文档结构。
变体、平台或状态策略
存在自动模式或变体时,文档必须明确:
Auto如何解析。- 显式值是否跨平台保持同义。
- CSD、平台、主题、宿主和 WindowState 如何影响输入或策略。
- 哪些差异允许进入平台层,哪些共享语义不得复制。
- Unknown、unsupported 或能力缺失时如何回退。
映射和组合较多时使用矩阵,不用散落的条件句描述同一状态空间。
架构、文件结构与职责
文件结构只列出该专项的稳定源码边界。每个类型、Panel、Strategy、presenter、handler 或 host 必须有单一 职责,并说明主要输入、输出和 owner。若明确不引入某类辅助对象,应以职责和数据规模解释边界,不写成对 历史方案的评价。
Template、组合与集成契约
涉及主题时,说明:
- 语义区域与真实 Template Part 或主题节点的对应关系。
- public control、internal control、presenter、host 和 item container 的组合结构。
- 哪些 part、ControlTheme key、Role、伪类和命中测试语义稳定。
- 默认模板、派生模板和特殊宿主如何复用同一模型。
- 外部替换模板时由 AtomUI 和应用各自承担什么责任。
核心算法、数据流与生命周期
算法设计至少定义:
- 输入、输出、单位和坐标系。
- 状态或数据的 owner 与单向流向。
- 主流程顺序。
- 空值、零尺寸、重叠、取消、异常或能力缺失时的退化规则。
- 触发重新计算、重新测量、重新订阅或释放的条件。
公式应集中在一个共享职责中;平台、模板或派生控件不能复制同一算法。
资源、性能与 AOT
说明专项设计是否引入:
- DynamicResource、binding、subscription、timer、cache 或异步任务。
- measure/arrange、render、pointer move 等热路径分配。
- 反射、动态发现、运行时注册或 trimming 风险。
- owner/container/template reapply 对应的释放路径。
不涉及这些能力时,也应写明使用纯值、静态注册或无状态对象等边界。
兼容性、定制与验证
兼容性描述 API 默认值、显式语义、模板 part、主题 key、渲染结果和外部定制责任。验证要求必须直接证明 这些设计不变量,并按风险选择纯函数测试、headless 控件测试、主题结构测试、Gallery/demo、平台实机或 NativeAOT publish。
与控件主文档的关系
overview.md保留专项能力的设计摘要、Public API 入口和兼容性主线,并链接专项设计文档。implementation.md保留源码索引、核心 owner、生命周期和维护入口,并链接专项设计文档。- 专项设计文档在首段链接回
overview.md和implementation.md。 token.md只记录 Token 语义;专项设计引用 Token 时链接token.md,不复制 Token 表。changelog.md只记录专项设计、API、主题或实现结构的变化,不解释当前设计。- 专项设计中的公共契约和语义结构不能只存在于专题文件;
overview.md与implementation.md必须保留 足以支撑导航的摘要。
审查清单
- 文档是否从控件设计本身开始,而不是从 Issue、截图或修复过程开始。
- 是否只描述采用的最终设计,没有候选方案比较和实施状态。
- 设计定位、原则、专项模型、职责和兼容边界是否互相一致。
- Public API、默认值和显式语义是否明确。
- 平台、CSD、模式、宿主或状态差异是否使用完整矩阵表达。
- 文件结构是否表达稳定 ownership,而不是任务拆分。
- Template Part、Role、ControlTheme key、组合节点和外部定制责任是否明确。
- 算法是否定义输入、输出、坐标系、边界和退化规则。
- 生命周期是否存在明确的获取、失效、取消和释放路径。
- 性能和 AOT 是否经过明确评估。
- 验证要求是否能够证明每项设计不变量。
overview.md、implementation.md和专项设计文档是否互相链接。- 是否没有重复全局规范、版本历史或无长期维护价值的实现细节。
验证要求
专项设计文档改动至少执行:
git diff --check
同时检查:
- 文件名和标题符合专项设计命名规则。
- 所有相对链接存在。
overview.md和implementation.md已添加专项设计入口。- 文档不包含 Issue 叙事、实现状态、历史过程或任务清单。
- 章节与专项复杂度匹配,没有为了套模板制造无意义内容。
- Public API、Template、算法和平台矩阵与同一变更中的源码设计保持一致。
overview.md 结构
overview.md 必须按以下结构书写:
# <Control> <平台>架构设计
1. 控件定位
2. 设计语言
3. API 与契约模型
4. 行为与状态模型
5. 视觉与主题模型
6. 控件家族或集成关系
7. 兼容性不变量
8. 专项模型
9. 文档导航与验证策略
章节要求:
- 控件定位:定义控件职责边界,说明控件是什么、不是什么。
- 设计语言:描述控件表达的产品语义和视觉语义。
- API 与契约模型:说明公共属性、事件、方法、template part、伪类和主题入口的契约边界,不机械罗列成员。
- 行为与状态模型:说明 hover、pressed、disabled、loading、focus、keyboard、motion 等交互语义,以及 public API 如何归一为 effective state。
- 视觉与主题模型:说明模板、Theme、Token、SharedToken 的总体关系和不可破坏的视觉契约,不展开具体 AXAML 结构。
- 控件家族或集成关系:说明与派生控件、组合控件、Form、Compact、Browser theme 等关系。
- 兼容性不变量:列出优化和扩展时必须保持不变的 API、行为和渲染。
- 专项模型:记录控件特有模型,例如 Button 的
Color / Variant。 - 文档导航与验证策略:链接
implementation.md、semantic-part.md(存在时)、token.md、changelog.md,并按 Public API、状态、AXAML、Token、文档分层列出验证要求。
无对应内容的章节不能删除,应写明“不适用”及原因。
md
概述
包与命名空间
何时使用
公共 API
事件与命令
使用示例
状态模型
主题与 Design Token
AOT 与裁剪注意事项
源码索引
相关文档
内容来源要求:
- “概述”“何时使用”“状态模型”主要来自 `overview.md`。
- “公共 API”“事件与命令”来自 `overview.md` 语义摘要和源码 public surface。
- “使用示例”来自 Gallery ShowCase 和源码片段 catalog。
- “主题与 Design Token”来自 `token.md`、Token 类型或生成数据。
- “AOT 与裁剪注意事项”来自 `implementation.md` 和全局 AOT 规范。
- “源码索引”来自 `implementation.md` 的源码文件结构。
生成的 `controls/<control>/semantic-cn.md` 必须使用以下结构:
```md
# <Control> 语义结构
## `semantic-part.md` 结构
控件公开 Semantic Part 时必须创建 `semantic-part.md`。该文件是公共 Part 契约的唯一完整来源;`overview.md` 只保留
owner、Part 名称和职责摘要,`implementation.md` 只保留 descriptor、marker 与真实模板或运行时节点的映射。
标准结构如下。多 owner 控件可以按 owner 分组逐 Part 说明,但不能省略任何职责:
```text
# <Control> Semantic Part 契约
1. Semantic Parts
2. Part 说明,或按 public owner 分组的 Parts 说明
3. Selector 用法
4. 状态与数量语义
5. 定制边界
6. 兼容性与验证
首段必须链接回 overview.md 和 implementation.md,并链接
AtomUI Semantic Part 系统设计。
Semantic Parts 表格必须按 public owner 和控件语义区域组织:
Abstract AXAML Structure
Composition Model
Template Parts
Pseudo Classes
State Flow
Theme and Token Boundaries
Customization Boundaries
AtomUI 的 semantic 文档描述 AXAML、ControlTemplate、运行时组合结构、Template Part、伪类、状态流和 Token 语义,不描述 Web DOM。
`Semantic Parts` 正式文档统一采用按 public owner 和 Part 分组的“字段 / 值”两列表格,不再新增横向宽表。
每个 Part 必须单独成组,表格必须完整保留 `Owner`、`Part`、`Selector`、`SelectorRoute`、`ContractType`、`Cardinality`、
`Customization`、`CrossVisualRoot`、`RuntimeCreated`、`AtomUI 节点`、`职责`、`相关 API`、`相关 Token` 和 `稳定性`;
不能为了缩短表格而省略类型、数量或运行时边界。
```md
### 1.1 `Button`
#### `content`
| 字段 | 值 |
| --- | --- |
| Owner | `Button` |
| Part | `content` |
| Selector | `.semantic-content` |
| SelectorRoute | `/template/ .semantic-content` |
| ContractType | `ContentPresenter` |
| Cardinality | `Single` |
| Customization | `Selector` |
| CrossVisualRoot | `false` |
| RuntimeCreated | `false` |
| AtomUI 节点 | 内容展示区域 |
| 职责 | 用户内容区域 |
| 相关 API | `Content` |
| 相关 Token | 组件 Token / SharedToken |
| 稳定性 | stable since 6.2.0 |
要求:
Part是语义名,不一定等于 Template Part 名。Owner必须是实际声明 descriptor 的 public 控件;同一控件目录存在多个 public owner 时逐项区分。Selector必须与生成式 Semantic Part descriptor 一致;root不添加.semantic-root。SelectorRoute必须与 descriptor 一致;root 写“不适用”。静态根模板 Part 通常为/template/ .semantic-*,RuntimeCreated=true必须记录完整 owner-relative route。ContractType是 marker 节点必须兼容的最低稳定 public 类型,也是 Semantic Style 的x:SetterTargetType;它不作为.semantic-*selector 的类型前缀。- 用户示例必须把 Part 身份写成
.semantic-*。包含 Setter 时显式写x:SetterTargetType="<ContractType>",不得生成Control.semantic-*或:is(Control).semantic-*形式。 Cardinality只能是Single、Optional或Multiple。Single表示每个适用模板恰好一个,Optional表示零或一个,Multiple表示一个或多个;表格必须与生成 descriptor 和所有内置模板一致。AtomUI 节点可以是 Template Part、主题节点、控件类或抽象区域。Customization使用Root、Selector或SelectorAndTheme。- 只记录进入生成式 descriptor 的稳定语义区域;用户不应依赖的内部节点只进入 Composition Model 或 Customization Boundaries,不能标记为公开 Semantic Part。
- 表格、Control 声明、AXAML marker 和生成 descriptor 不一致时必须验证失败,不能只修改文档消除差异。
Since、CrossVisualRoot或RuntimeCreated影响使用和验证边界时,必须在稳定性或实现说明中明确记录;CrossVisualRoot不自动推导 Theme 属性,RuntimeCreated不免除运行时 selector 测试。
Part 表之后必须逐 Part 说明:
- Part 在哪些模板、状态或 owner 生命周期中存在。
- 适合定制的属性,以及布局型 Setter 需要验证的 owner 尺寸、shape、裁剪和 Measure/Arrange 边界。
- 伪类、属性状态、替代实现与 cardinality 的关系。
- 哪些内部节点、Name、
PART_*、用户内容子树或子 ControlTemplate 明确不属于该 Part。 - Selector 示例使用 owner 与 descriptor 的完整
SelectorRoute,并以x:SetterTargetType提供类型上下文。复杂 Part 可以 包含多个/template/和>;不得用普通 logical descendant 缩写 route。 - 删除、改名、类型收窄、cardinality 变化和模板替换时的兼容性与验证要求。
Abstract AXAML Structure 必须遵守:
- 只能由生成器从真实
ControlTheme/ControlTemplate抽取。 - 生成器通过
implementation.md的源码索引定位*Theme.axaml,再读取模板节点。 - 不允许根据
Semantic Parts表、控件分类或控件名称生成伪 XML。 - 不允许输出
SemanticPart这类并不存在于 AXAML 模板中的占位节点。 - 控件没有可定位的 ControlTheme 模板时,该章节只说明未生成结构,并链接 Template Parts、主题文件和源码索引。
- 如果需要稳定抽象结构,必须先在控件源文档和源码索引中明确对应 ControlTheme / ControlTemplate 来源,而不是手工修改生成产物。
Composition Model 必须描述 public 控件与内部协作对象之间的运行时组合关系。它的第一信息源是控件源码目录下的 Themes/ 文件夹:
- 优先阅读同一控件家族的独立
*Theme.axaml叶子,并使用生成的 ControlTheme asset manifest 校验 owner、引用的 Control identity 和 Semantic Part Theme 关系。 - 从多个
ControlTheme中识别 public control、internal control、item container、adorner、presenter、popup host、motion actor、template part 和跨主题组合关系;不得依赖只用于聚合的*Themes.axaml。 implementation.md、源码索引、C# 创建逻辑、CreateContainerForItemOverride()、OnApplyTemplate和PART_只作为解释与校验补充。- 不允许仅凭控件名称、控件分类或通用模式发明内部协作节点。
Composition Model 解决以下场景:
- public 控件本身
ControlTheme很薄,但行为由内部容器、presenter、adorner、popup host、motion actor 或 item container 完成。 - 控件结构分散在多个主题文件、C# 创建逻辑、item container 生成、adorner 挂载或数据对象中。
- Agent 只阅读
Semantic Parts和Abstract AXAML Structure时,会低估控件结构复杂度,进而误导用户直接依赖内部类型或错误理解状态流。
Composition Model 至少包含:
## Composition Model
### 控件角色图
```text
<PublicControl>
-> <InternalControlOrPresenter> (<theme source>)
-> <ElementType>#<TemplatePartName> (<stability>)
-> <ChildElementType>#<ChildName> (<stability>)
```
### 协作节点
| 节点 | 类型 | 来源 | 生命周期 owner | 影响的 public API | 稳定性 | Agent 使用边界 |
| --- | --- | --- | --- | --- | --- | --- |
| ... | ... | ... | ... | ... | public / template-stable / internal-observable / private | ... |
控件角色图 必须是模板层级树,不是节点清单。生成器应按真实 ControlTemplate XML 父子关系输出结构:ControlTheme target 是角色入口,模板视觉节点以 ElementType#Name 表示;没有 Name 的节点只输出 ElementType。同一个 ControlTheme 中的 template part、presenter、motion actor、adorner indicator 和布局节点不得被打平成同级节点。存在多个模板变体时可以输出多个根树,但必须保持每个变体内部的父子关系。
稳定性要求:
public表示用户可直接使用和依赖的 public 控件、数据对象或 API。template-stable表示稳定 template part、ControlTheme key 或主题节点,可用于主题维护但不能随意改名。internal-observable表示内部协作对象,影响用户可观察行为;Agent 可以用它理解结构,但不能指导用户直接依赖。private表示私有实现细节,默认不作为公开文档内容;如必须出现,只能用于说明不可依赖边界。
不同控件族的组合结构重点:
| 控件族 | 代表控件 | 文档重点 |
|---|---|---|
| Shell / Overlay | Drawer、Modal、Notification、Message、PopupConfirm | public control、container、mask、surface、motion、close/action 区。 |
| Adorner / Decorator | Badge、Watermark | decorated target、adorner、indicator、motion actor、offset、placement。 |
| Items / Container | Breadcrumb、Steps、Menu、ListView、TabControl | owner control、item data、item container、separator、trigger、selection/navigation flow。 |
| Popup Input | Select、Cascader、DatePicker、TimePicker、ComboBox、AutoComplete | input shell、popup host、panel、item presenter、selection/value sync。 |
| Presenter / Family | ProgressBar、Skeleton、Card、Descriptions | public API 到内部 presenter、visual unit 或家族子控件的映射。 |
没有额外运行时组合层的控件也应明确说明:该控件主要由 public 控件和 ControlTheme 模板直接表达,没有额外内部协作对象。生成器不得因缺少复杂结构而发明组合节点。
implementation.md 结构
implementation.md 描述特定控件的内部实现原理,用于帮助维护者理解源码结构、状态流转、生命周期和关键算法。它不替代代码注释,不记录临时实现过程,也不作为用户 API 文档。
implementation.md 必须按以下结构书写:
# <Control> <平台>实现原理
1. 实现定位
2. 源码文件结构
3. 核心类职责
4. 状态与数据流
5. 组合结构模型
6. 生命周期与模板接入
7. 交互与事件处理
8. 内部算法与关键流程
9. 资源、性能与 AOT 边界
10. 维护不变量
11. 测试与验证
章节要求:
- 实现定位:说明本文档覆盖的内部实现范围,以及哪些细节仍应直接阅读源码。
- 源码文件结构:说明控件相关
.cs、.axaml、Token、helper、handler、内部 view 的职责边界。 - 核心类职责:描述主要类、内部接口、handler、presenter、decorator、数据节点等协作关系。
- 状态与数据流:描述 public API、internal state、effective state、ItemsSource、Children、selection、checked、expanded、filter 等状态如何流动。
- 组合结构模型:优先基于控件
Themes/文件夹描述 public 控件、内部协作控件、item container、adorner、popup host、motion actor、presenter、数据对象和 template part 的运行时关系。 - 生命周期与模板接入:描述构造、初始化、加载、卸载、template part 获取、事件订阅释放、container 准备和资源绑定规则。
- 交互与事件处理:描述 pointer、keyboard、focus、context menu、drag/drop、motion、popup 等内部事件路径。
- 内部算法与关键流程:描述维护者必须理解的遍历、布局、状态回放、同步、缓存、渲染等关键流程,不逐行复述代码。
- 资源、性能与 AOT 边界:描述动态资源、事件订阅、binding、缓存、异步任务、反射或生成器相关约束。
- 维护不变量:列出重构、优化和修 bug 时不能破坏的内部行为顺序、状态一致性、生命周期释放和主题契约。
- 测试与验证:列出对应测试、Gallery 走查点、AOT 或发布验证要求。
要求:
- 只写当前实现原理,不写历史过程;历史变化进入
changelog.md。 - 不把私有方法逐个改写成说明书;只记录维护者必须知道的稳定结构、关键路径和不变量。
- 不重复
overview.md的设计语言、API 模型和公共契约;必要时只引用它们作为实现入口。 - 不重复
token.md的 Token 分类和语义;实现中使用 Token 的路径可以链接token.md。 - 当控件实现较简单时,也应保留该文档,并用简短章节说明实现没有额外内部模型,避免维护者误判文档缺失。
implementation.md 的“组合结构模型”章节应使用稳定的角色图与协作节点表。维护要求:
- 组合节点必须优先来自控件
Themes/文件夹中的ControlTheme、template part、内部主题控件和主题聚合关系。 - C# 源码中的动态创建、item container 生成、adorner 挂载和 popup host 管理用于补充主题文件无法表达的运行时关系。
- 不把 internal 类型写成用户可直接使用的 API。
- 对于 internal 但用户可观察的结构,使用
internal-observable并说明 Agent 只能用于理解行为和维护边界。 - 对于 template part 或 ControlTheme key,使用
template-stable并说明变更需要同步主题、实现和文档。 - 对于简单控件,明确说明没有额外组合层,不允许为了补齐章节发明内部节点。
token.md 结构
token.md 只记录控件专属 Token 内容,不重复全局 Token 系统规则。通用 Token 分层、命名、计算、Theme Variables、预设色规则统一链接 AtomUI 控件 Token 设计规范。
token.md 必须按以下结构书写:
# <Control> Token 设计
1. 定位
2. Token 分类
3. 控件专项模型中的 Token 使用
4. 控件家族影响
5. 兼容性要求
6. 验证策略
要求:
- Token 分类必须按控件语义组织,而不是按代码顺序机械罗列。
- Token 文档必须说明哪些主题和控件家族引用这些 Token。
- 不允许把实例状态、交互状态或
EffectiveXxx状态写成 Token。 - 不允许在控件 Token 中展开颜色、variant、状态的组合 Token。
- 没有专属 Token 的控件不需要创建
token.md,但overview.md中仍应说明其 Theme 是否直接使用 SharedToken。
如果控件没有专属 token.md,overview.md 必须明确说明:
- 该控件没有专属 Token;或
- 该控件复用家族 Token;或
- 该控件直接使用 SharedToken / 主题资源。
changelog.md 结构
每个控件必须维护控件级 changelog。
格式:
# <Control> Changelog
本文档记录 <Control> 控件级设计、API、主题契约、Token 和实现结构的变化。
它不替代仓库根目录 CHANGELOG.md,也不作为正式版本发布说明。
## YYYY-MM-DD
- Docs
- ...
- API
- ...
- Theme
- ...
- Token
- ...
记录范围:
- API 模型变化。
- 主题契约变化。
- Token 分类、语义或边界变化。
- template part、伪类、状态模型变化。
- 控件家族协同规则变化。
- 文档结构、实现文档边界和重要设计决策变化。
不记录:
- 临时讨论。
- 纯格式化。
- 无长期维护价值的实现细节。
- 正式 release changelog 条目。
链接规则
控件目录内文档必须互相链接:
overview.md链接implementation.md、token.md和changelog.md。没有token.md时只链接implementation.md和changelog.md。implementation.md链接overview.md、changelog.md,并在涉及控件专属 Token 时链接token.md。- 存在
semantic-part.md时,overview.md和implementation.md必须链接它;semantic-part.md必须在首段链接回overview.md和implementation.md。 - 存在
<topic>-design.md时,overview.md和implementation.md必须链接该专项设计文档;专项设计文档 必须在首段链接回overview.md和implementation.md。 token.md链接overview.md、implementation.md、changelog.md和 AtomUI 控件 Token 设计规范。changelog.md不解释当前设计,只记录变化。
分类入口文档必须链接控件目录:
- [Button 桌面版架构设计](button/overview.md)
- [Button 桌面版实现原理](button/implementation.md)
- [Button Token 设计](button/token.md)
- [Button Changelog](button/changelog.md)
分类入口应保持控件列表完整、顺序稳定,并按控件目录链接主要维护文档。
审查标准
控件文档 review 时按以下标准检查:
- 是否描述最新状态,而不是历史过程。
- 是否明确公共 API、事件、方法和兼容边界。
- 是否有清晰的状态模型。
- 是否说明模板职责和不可破坏的 template part。
- 是否有独立
implementation.md描述控件内部实现原理、源码职责边界、生命周期和维护不变量。 overview.md是否避免承载过重实现细节。- 是否把通用规则放到全局规范,而不是控件文档重复。
- 是否维护控件级
changelog.md。 - 是否包含分层验证策略。
- 是否存在“未来”“后续”“演进方向”等不适合架构文档的表述。
- 控件公开 Semantic Part 时,是否存在
semantic-part.md,并且overview.md只保留支持摘要、implementation.md只保留节点映射。 semantic-part.md是否完整列出每个 public owner 的 Part,并逐 Part 说明职责、存在条件、状态/cardinality、定制和排除边界。implementation.md是否提供稳定源码索引、状态流、生命周期和 AOT 边界。- 存在专项设计文档时,是否遵循本文“控件专项设计文档”章节,并且只描述最终设计,没有混入 Issue 调查、 候选方案或实现状态。
- 结构复杂控件的
implementation.md是否基于Themes/文件夹提供 Composition Model,并明确 internal 协作对象的稳定性和 Agent 使用边界。 token.md是否能解释 Token 语义;没有token.md的控件是否在overview.md明确说明原因。- Template Part、伪类、主题资源和 Token 是否描述完整。
- 控件文档、源码 public surface、Token 类型和 Gallery ShowCase 示例是否对应。
验证要求
控件文档改动至少验证:
git diff --check
同时检查:
- 新增文档没有尾随空白。
- 所有相对链接存在。
- 分类入口文档已更新。
- 只改文档时,不应误改控件实现代码或主题文件。