Aira UI 开源复用审计:哪些不应再造,哪些必须保留自研
- 状态:Completed Research
- 日期:2026-09-01
- 文档版本:1.1.0
- 调研范围:React 工作台、无障碍原语、分栏/停靠、图标、特征树、大列表、3D 拾取、组件开发、浏览器测试、状态、Worker、存储与协作
- 实施入口:Aira UI Workbench 技术实施计划
- 结论:直接复用通用 UI 基础设施;条件满足后再引入性能与复杂工作台库;不替换 Aira 已有的显式协议、模型身份、事务与证据链
2026-09-26 选型复核:React Aria Components 作为深度定制底座
Section titled “2026-09-26 选型复核:React Aria Components 作为深度定制底座”本节是本次复核裁决;下文 9 月 1 日的采用清单不代表当前已安装依赖。当前 apps/web/package.json 与 pnpm-lock.yaml 锁定 react-aria-components@1.21.1,文件菜单、对话框、工作台输入区及部分画布 HUD 已实际使用;CSS 由 Aira tokens 控制。当前 Web 清单没有 react-resizable-panels。选型复核后已将既有依赖从 1.20.0 升至稳定版 1.21.1;未新增 UI 原语库或测试框架。
推荐:继续使用 React Aria Components,围绕 Aira 的任务与画布体验深度定制。 这是结合现有代码与官方能力的工程选型,不是用户实验或性能排名。两名 Antigravity 研究员分别检查现有集成与候选,另设独立反方审核;初稿中“98/100”“对 Canvas 更快”“RAC 没有 Virtualizer”等无证据或错误判断不采纳。
| 候选 | 可核对能力与取舍 | 本次裁决 |
|---|---|---|
| React Aria Components | 无预设样式与状态样式 API、组合定制、Tree 和 Virtualizer;Apache-2.0。项目已有接线与 tokens,但这不证明应用级可访问性已达标。 | 主选;先复用已有原语与状态投影。官方最新文档不自动等于锁定版本全部 API,接入新组件前核对 1.21.1 导出。 |
| Base UI | 无样式、开放组合 API,支持 React 17+ 与 Vite。具备同样值得评估的定制基础,不能凭旧印象称为 alpha 库。 | 第一备选;只有在同一实际交互中证明 RAC 有具体缺口且其适配总成本更低时替换。 |
| Radix Primitives | 无样式原语及键盘、焦点和 ARIA 支持。它不等于 shadcn,也不要求项目采用 shadcn 的样式。 | 可用备选;目前没有证据足以抵消现有菜单、浮层、表单及 CSS 状态迁移成本。替换成本是重新接线和验收,不是必须自研 ARIA。 |
| shadcn/ui | 开放源码组件分发与定制方式,与行为原语库不在同一层级。 | 可借鉴布局与组件组合;不额外引入一套等价原语与视觉状态体系。 |
| Mantine / MUI | 成套组件可服务表单和管理页面;本次未做其 bundle、Canvas 事件或渲染对照。 | 不选为工作台主底座;无依据宣称其必然更慢或不能用于 CAD。 |
深度定制的职责:沿用现有 CSS tokens,统一焦点、密度、文字和证据状态;以现有 Menu/Dialog/Popover 承担通用行为,将任务纠正、候选核对、保持条件做成同一权威状态的界面投影;模型树的展示集合只保存展开/焦点等 UI 状态。世界坐标锚定、对象身份、授权、候选事务和几何检查仍由 Aira 负责,不放入组件库状态,不为换皮建立第二执行器。优先通过公开 API 和组合定制;只有可复现的上游缺口才考虑补丁或 fork。
采用验收:在既有产品路径实操 390×350 与桌面视口、菜单/输入/画布快捷键隔离、嵌套浮层 Escape 与焦点返回、读屏名称与状态、暗色高对比及减弱动画;对树用固定数据和设备记录 DOM 数、交互延迟及内存,不能把虚拟化能力当作已测性能。这些采用判据必须逐项实测;尚未执行的项目保持 unknown,当前结果见 ACTIVE_TASK.md。UI 库选择也不证明原生 Aira Interface 的能力对等已经完成。
官方接入依据为 Adobe react-aria skill 的 Menu、Modal、Tabs、TextField、Disclosure 与 Toolbar 组件指南,并核对锁定版本导出。Orca 浏览器已恢复访问;具体构建及交互验收状态只见 ACTIVE_TASK.md,不将官方组件的能力声明视作应用级验收通过。
1. 首轮执行结论(2026-09-01)
Section titled “1. 首轮执行结论(2026-09-01)”首轮建议进入 UI worktree 的依赖只有五组:
- React Aria Components:无样式、可组合、可访问的交互原语;
react-resizable-panels:工作台分栏、折叠和布局尺寸持久化;- Lucide React:统一图标;
- Storybook React Vite:用 fixture 独立完成组件和状态矩阵;
- Playwright + axe-core:U1 接入真实流程后做浏览器、键盘和可访问性回归。
以下库有价值,但只在真实问题出现后 spike:TanStack Virtual、three-mesh-bvh、Floating UI、
FlexLayout、Headless Tree。它们不应成为 U0 开工前置条件。
以下能力暂不引入通用库:全局状态、IndexedDB、Worker RPC、CRDT、React Three Fiber 和另一套 Candidate/Revision 状态机。Aira 在这些边界已有经过验证、且承载产品语义的实现;替换会增加迁移风险, 不属于“避免重复制作”。
2. 审计原则
Section titled “2. 审计原则”候选库必须回答六个问题:
- 它是否解决与 Aira 无关、行业已充分解决的通用问题?
- 是否与 React 19、Vite、TypeScript 和当前 Three.js 适配方式兼容?
- 是否允许 Aira 保留自己的视觉语言和状态所有权?
- 是否会复制现有 Core、Worker、storage 或 viewer 的真相来源?
- 是否有明确的许可证、活跃维护和可退出边界?
- 是否现在就有可复现的问题和验收用例,而不是“以后可能用到”?
本审计使用项目现状与上游官方文档/仓库作为依据。星标、下载量和 demo 观感不单独构成采用理由; 在正式安装时仍需锁定精确版本、执行构建与许可证清单检查。
3. 当前项目中不应重复制作的通用能力
Section titled “3. 当前项目中不应重复制作的通用能力”| 问题 | 结论 | 候选 |
|---|---|---|
| 键盘、焦点、ARIA、国际化交互细节 | 直接复用 | React Aria Components |
| 桌面工作台固定分栏与折叠 | 直接复用 | react-resizable-panels |
| 常用工具和状态图标 | 直接复用 | Lucide React |
| 组件 fixture、状态矩阵和隔离开发 | 直接复用 | Storybook React Vite |
| 真实浏览器交互、截图、trace | U1 直接复用 | Playwright |
| 自动可访问性规则 | U1 直接复用 | axe-core |
| 超长 history / evidence / tree 的 DOM 控制 | 有规模证据后复用 | TanStack Virtual |
| 复杂 mesh 的 raycast / spatial query | 有 profiling 证据后复用 | three-mesh-bvh |
| 画布虚拟点锚定浮层 | 需求出现后 spike | Floating UI |
| 自由停靠、tab、popout | 产品需求出现后 spike | FlexLayout |
4. 直接采用候选
Section titled “4. 直接采用候选”4.1 React Aria Components:采用行为,不采用整套视觉系统
Section titled “4.1 React Aria Components:采用行为,不采用整套视觉系统”React Aria 提供无样式的 components/hooks,目标包括 可访问性、键盘交互、焦点管理、国际化和组合;源代码位于 Adobe React Spectrum 仓库,采用 Apache-2.0 许可证。
适合 Aira 的部分:
- Button、ToggleButton、Tooltip、Dialog、Menu、Popover;
- TextField、NumberField、ComboBox;
- Tabs、Toolbar、GridList/Tree 的交互行为;
- overlay 焦点圈、dismiss、键盘导航和 screen reader 语义。
采用边界:
- Aira 自己维护 CSS variables、密度、颜色、圆角和 CAD 视觉层级;
- 不引入 React Spectrum 的完整视觉主题来覆盖品牌;
- 不把 React Aria collection/state 当作 feature graph 或 Revision truth;
- Tree 首版只解决浏览、选择、展开和键盘;拖拽排序必须先定义模型语义。
这能避免团队重新实现最容易“看起来能用、边缘情况却很多”的焦点与键盘系统,同时保留完全自定义外观。
4.2 react-resizable-panels:首版工作台布局
Section titled “4.2 react-resizable-panels:首版工作台布局”react-resizable-panels 是 MIT 许可的 React 分栏组件,
覆盖 horizontal/vertical panel group、resize handle、折叠和布局持久化等工作台常见能力。
建议用于:
- 左侧 activity/context、中央 viewport、右侧 inspector;
- 底部 task/history/evidence dock;
- 面板最小/最大尺寸、折叠、键盘可操作分隔线;
- 用户级布局尺寸持久化。
不用于:
- U0 就实现 Visual Studio 式任意停靠;
- 存储业务状态;
- 让 layout model 决定 feature/task 的生命周期。
首版固定骨架更容易形成稳定信息架构。如果实际用户后来需要 draggable tab、popout 和自由布局,再评估 FlexLayout。
4.3 Lucide React:统一图标,不自画基础 icon set
Section titled “4.3 Lucide React:统一图标,不自画基础 icon set”Lucide 提供一致的 SVG icon set 和 React 包;主许可为 ISC, 从 Feather 派生的部分保留 MIT 声明,详见其 LICENSE。
建议:
- 以命名 import 使用,避免整包进入 bundle;
- 通过统一
Iconwrapper 固定 stroke、尺寸、aria-hidden和状态色; - 图标只辅助文字与 tooltip,不能单独编码 validation/certificate 的唯一含义;
- Aira 独有的 SemanticRef、field、certificate 图形可保留少量自研 glyph。
4.4 Storybook React Vite:支持“先搭完 UI”,不是提前测性能
Section titled “4.4 Storybook React Vite:支持“先搭完 UI”,不是提前测性能”Storybook 的 React Vite 集成 可在 Vite/React 项目中隔离开发和记录组件;上游 Storybook 仓库 采用 MIT 许可。
U0 应用方式:
- 用 fixtures 表达 empty/loading/running/invalid/conflict/cancelled/committed;
- 独立审阅 panel 密度、selection chip、Candidate diff、证据展开和窄屏状态;
- 记录交互 contract,而不是依赖开发者记忆复现状态;
- UI 骨架稳定前不在 stories 中建立毫秒 Gate。
Storybook 不成为生产状态容器,也不复制真实 Worker/Core。fixture 必须通过与 production view model 相同的 snapshot 类型进入组件。
4.5 Playwright + axe-core:U1 后建立功能与可访问性护栏
Section titled “4.5 Playwright + axe-core:U1 后建立功能与可访问性护栏”Playwright 提供跨浏览器自动化并采用 Apache-2.0 许可;官方支持 视觉对比 和 Trace Viewer。axe-core 采用 MPL-2.0,可自动检查常见可访问性规则。
建议覆盖:
- viewer 点击、selection chip、AI scope、Candidate、commit/discard/cancel;
- stale result、Revision 切换、失效 SemanticRef、worker error;
- 键盘遍历、focus return、dialog/menu dismiss、panel resize;
- shell 与 overlay 的稳定 screenshot;
- axe-core 自动扫描,再补人工键盘和 screen reader 审阅。
不应把 3D canvas 的逐像素截图当作几何正确性的唯一证据。浏览器测试断言 UI 状态、选择映射和 transaction 结果;几何正确性继续由现有 Core/Worker/Certificate 测试负责。
实施结果(K4):
- 精确锁定
@playwright/test@1.62.1与@axe-core/playwright@4.13.0,只进入 devDependencies; - 用 production Chromium route 断言真实 viewer hit、SemanticRef、Candidate/Revision display source、CAS commit、discard、invalid geometry 与 IndexedDB reload;
- axe 扫描 ready 与 Candidate review 两个状态,serious/critical violation 为 0;
- 保留 trace/screenshot/video 作为失败诊断,不把 canvas 像素当作几何证书;
- K5 已用 production controller 的窄时序 gate 与独立真实 Session 完成 cancel、stale result 和 CAS conflict;没有人为放慢 worker,也没有引入第二套浏览器测试框架。
5. 按条件验证候选
Section titled “5. 按条件验证候选”5.1 TanStack Virtual:列表确实变大后再加
Section titled “5.1 TanStack Virtual:列表确实变大后再加”TanStack Virtual 是 headless 的 list/grid virtualizer; 源码 采用 MIT 许可。
适用信号:
- feature tree、history、evidence 或 task list 出现大量 DOM 节点;
- Chrome profile 证明 layout/paint 或 React commit 由列表规模主导;
- 需要动态行高、overscan 和 scroll-to-item。
U0 fixture 数量很小时直接渲染更简单。虚拟化会增加焦点、screen reader、拖拽和滚动定位复杂度,不能仅因“CAD 以后会很大”就预装。
5.2 three-mesh-bvh:只加速拾取,不成为语义真相
Section titled “5.2 three-mesh-bvh:只加速拾取,不成为语义真相”three-mesh-bvh 采用 MIT 许可,为 Three.js mesh 提供加速
raycast、spatial query、序列化和 Worker 生成等能力。
适用信号:
- 真实 mesh 规模下 Raycaster 成为可测量瓶颈;
- selection/lasso 需要大量空间查询;
- BVH 构建和内存成本低于它节省的交互成本。
集成边界:
- BVH 绑定
RenderPacket/geometry cache 和内容 hash; - Worker 构建,缓存可丢弃;
- triangle/face index 必须经现有映射得到
SemanticRef; - BVH 命中不能直接生成 Patch、Revision 或持久身份。
5.3 Floating UI:只处理 React Aria/CSS 无法覆盖的画布锚点
Section titled “5.3 Floating UI:只处理 React Aria/CSS 无法覆盖的画布锚点”Floating UI React 可定位 tooltip、popover 和 floating element; 项目 采用 MIT 许可,并支持 virtual elements/custom platform,适合把 3D selection 投影后的屏幕点作为锚点。
只有在以下需求出现时 spike:
- contextual toolbar 必须跟随画布虚拟坐标;
- 需要 collision、flip、shift、arrow 和 viewport 边界处理;
- React Aria overlay 与 CSS Anchor Positioning 无法完成目标。
若引入,它只负责 geometry positioning;焦点、dismiss 和可访问性仍保持一个明确 owner,避免两套 overlay 系统互相争夺。
5.4 FlexLayout:真实自由停靠需求出现后再评估
Section titled “5.4 FlexLayout:真实自由停靠需求出现后再评估”flexlayout-react 采用 MIT 许可,提供 tab、dock、floating window、popout
和持久布局模型;其 CHANGELOG 显示项目仍在更新并包含 React 19 相关适配。
它的能力明显强于首版所需,也意味着更大的 layout state、拖拽、可访问性和主题集成成本。裁决:
- U0/U1 使用
react-resizable-panels; - 只有用户研究证明固定工作台妨碍专业工作流时,才用真实 Aira 面板做 FlexLayout spike;
- spike 必须验证键盘、screen reader、popout 生命周期、项目恢复和布局版本迁移;
- layout JSON 只保存 UI 偏好,绝不保存模型状态。
react-mosaic-component 也提供 tiling window manager,但首版没有采用
两套 docking 候选的理由;其 window-manager ownership 和 drag stack 对当前目标偏重。
5.5 大型特征树:先 React Aria Tree,再评估 Headless Tree
Section titled “5.5 大型特征树:先 React Aria Tree,再评估 Headless Tree”React Aria Components 已包含 Tree 行为与 drag-and-drop 实现入口,见 Tree 源码。
若未来需要十万级节点、复杂 DnD 和 virtualization,可评估 MIT 许可的 Headless Tree。它提供 headless tree features,但当前公开定位仍包含 beta 阶段信号,因此不应作为 U0 默认基础。
React Arborist 同时提供 virtualization、拖拽、键盘和 selection, 能力完整,但也引入另一套 tree state model。当前不采用;若 React Aria + TanStack Virtual 无法满足再做对照 spike。
5.6 命令面板与拖拽
Section titled “5.6 命令面板与拖拽”cmdk(MIT)可实现 accessible command menu,但 U0 已有 React Aria ComboBox/Menu。只有 grouped fuzzy command UX 明显不足时再 spike,避免重复 collection/focus 系统。- Pragmatic Drag and Drop(Apache-2.0)是可选的通用 DnD 基础。只有 feature reorder、跨面板拖放有明确语义,且 React Aria/FlexLayout 无法覆盖时才进入;不与第二个通用 DnD 库并存。
6. 暂不引入或不替换
Section titled “6. 暂不引入或不替换”6.1 Zustand / XState:不复制核心状态机
Section titled “6.1 Zustand / XState:不复制核心状态机”Zustand 是小型 React store, XState 是 event-driven state machine/actor 工具,二者均采用 MIT 许可。
它们并非质量不足,而是当前 ownership 不合适:Candidate、Revision、task 和 validation 状态已经由 Core/Session 定义。
UI 首版用 WorkbenchViewModel + useSyncExternalStore 投影即可。只有 App 拆分后仍出现清晰的 UI-only 复杂状态问题,
才重新评估;即使引入也不能成为第二个 transaction truth。
6.2 Dexie:不替换已测试的项目存储
Section titled “6.2 Dexie:不替换已测试的项目存储”Dexie 是 Apache-2.0 的 IndexedDB wrapper,具备事务、查询和响应式扩展。
但 Aira 已有 AiraProjectStore、schema 与恢复测试。为了 API 更方便而迁移 authoritative project storage 会扩大数据迁移和兼容风险。
裁决:保留现有 store;少量 UI 偏好用简单、版本化的 preference port。只有存储查询复杂度成为真实瓶颈时再做 migration RFC。
6.3 Comlink:保留显式 Worker 协议
Section titled “6.3 Comlink:保留显式 Worker 协议”Comlink(Apache-2.0)可将 Web Worker 暴露为 RPC proxy,也提供 transfer
辅助。Aira 已有 typed worker protocols、transferable RenderPacket、取消、预算、版本和 evidence 边界;这些显式边界本身是可靠性资产。
用通用 proxy 包装会让消息、取消和资源所有权更隐蔽。裁决:不替换现有 Worker 协议;可以借鉴其 transfer patterns,但不增加第二种 RPC 风格。
6.4 Yjs / Automerge:不把 CRDT 放进几何真相
Section titled “6.4 Yjs / Automerge:不把 CRDT 放进几何真相”Yjs 和 Automerge 都提供 local-first/CRDT 文档能力,但它们不能自动解决 CAD feature identity、几何可用性、约束冲突和 certificate validity。
裁决:不让 CRDT 合并 authoritative AMIR/Revision。未来可以把 presence、cursor、comment、shared selection 作为单独协作层; 模型合并仍走 typed Patch、CAS、ConflictedRevision 和显式 resolve。
6.5 React Three Fiber / Drei:不重写现有 viewer ownership
Section titled “6.5 React Three Fiber / Drei:不重写现有 viewer ownership”Aira 已有命令式 Three.js adapter、RenderPacket 生命周期、OrbitControls 和 Raycaster。为了组件风格统一迁移到另一套 scene reconciler 会同时改变资源生命周期、worker packet 接入和 selection mapping,收益不足。
继续复用 Three.js 自带的 OrbitControls、 Raycaster;需要 gizmo 时可评估 TransformControls,但 gizmo 只产生 preview command,不能直接改写模型真相。
6.6 完整视觉设计系统与 HTTP mock
Section titled “6.6 完整视觉设计系统与 HTTP mock”- 不采用 MUI、Ant Design 或其他完整视觉系统覆盖 Aira 的高密度 CAD 语言;React Aria 提供行为,Aira 自己提供 tokens/CSS。
- MSW 适合 HTTP/API mocking,但当前 UI 主要连接 local Core、Worker 和 ports; fixture view model 更贴近真实边界。以后出现 gateway/cloud API 时再引入。
7. 必须保留项目自研的部分
Section titled “7. 必须保留项目自研的部分”“不重复造轮子”不等于把产品差异化外包。以下能力没有通用 UI 库可以正确替代:
RenderPacketpick result → stableSemanticRef的映射与失效规则;- selection chip 的 Revision、scope、entity kind、applicability 和 ambiguity 表达;
- 人工/AI 共用的
preview → validate → commit编排; - Candidate diff、ConflictedRevision、certificate 和 evidence 的 UI 投影;
- task branch、防 stale publish、取消、超时和 authoritative commit 边界;
- WorkbenchViewModel 与现有 Core/Session/Worker/Store 的适配器;
- 近似 preview 和 authoritative result 的质量标识;
- CAD 专用 feature tree 语义、参数适用性和历史恢复规则。
这些部分应保持窄、可测试、typed,并尽量建立在现有 contract 上,而不是创建 UI 专属的平行模型。
8. 许可证与进入顺序
Section titled “8. 许可证与进入顺序”| 候选 | 上游许可证 | 当前裁决 | 最早阶段 |
|---|---|---|---|
| React Aria Components | Apache-2.0 | 采用 | U0 |
react-resizable-panels |
MIT | 采用 | U0 |
| Lucide | ISC + 部分 MIT | 采用 | U0 |
| Storybook | MIT | 采用(dev) | U0 |
Playwright 1.62.1 |
Apache-2.0 | 已采用(dev) | U1/K4 |
@axe-core/playwright 4.13.0 |
MPL-2.0 | 已采用(dev) | U1/K4 |
| TanStack Virtual | MIT | 条件采用 | P0/P1 |
three-mesh-bvh |
MIT | 条件采用 | P0/P1 |
| Floating UI | MIT | spike | 明确画布浮层需求后 |
| FlexLayout | MIT | spike | 明确自由停靠需求后 |
| Headless Tree | MIT | spike | 大型树需求后 |
许可证结论是上游当前公开信息的研究记录,不替代发布前的依赖清单和法律审核。安装时应:
- 锁定精确版本和 integrity;
- 记录直接/传递依赖许可证;
- 执行 production build、bundle diff 和浏览器 smoke test;
- 记录 wrapper/adapter 作为退出边界;
- 不在同一提交中同时引入多个重叠基础库。
9. 建议的首轮复用实验
Section titled “9. 建议的首轮复用实验”首轮依赖现已按以下顺序执行;后续仍沿用相同进入纪律:
- 用 React Aria +
react-resizable-panels+ Lucide 做纯 fixture 的 WorkbenchShell; - 用 Storybook 枚举 selection、Candidate、validation、history 和 evidence 状态;
- 完成一条真实 Exact Fillet selection-grounded 垂直切片;
- 接入 Playwright + axe-core;真实主流程、丢弃、invalid、reload、scope ownership、actor parity、 production cancel/stale/CAS conflict、键盘/focus 与自动 axe 已完成;
- U3 完成后建立性能 corpus;只有测量指向列表或 raycast 时,才分别试 TanStack Virtual 或
three-mesh-bvh; - 只有真实用户工作流要求自由停靠或超大型可拖拽树时,才打开 FlexLayout/Headless Tree spike。
10. 最终裁决
Section titled “10. 最终裁决”Aira 可以大量避免重复开发,但复用边界必须按“通用交互基础设施外购,模型语义与可靠性内建”划分:
- 可访问性、面板、图标、stories、浏览器自动化不值得自研;
- virtualization、BVH、floating 和 docking 值得在问题被测量或产品需求成立后复用;
- Worker 协议、IndexedDB 项目真相、Three viewer ownership、SemanticRef、typed Patch、Candidate/Revision 和证据链不应为了技术栈流行度而替换。
这样既减少重复制作,也避免用一个通用框架覆盖 Aira 最有价值的工程资产。