mirror of
https://github.com/multica-ai/multica.git
synced 2026-07-26 20:45:37 +02:00
* refactor(ui): unify collection page patterns * refactor(agents): redesign agent detail workbench (#5263) * refactor(agents): redesign agent detail workbench * refactor(agents): refine capability and settings surfaces * refactor(agents): rebuild general settings form * refactor(agents): refine overview and settings * refactor(agents): redesign custom args editor * docs(ui): record consistency audit
364 lines
18 KiB
Markdown
364 lines
18 KiB
Markdown
# Multica UI 一致性问题与页面模式层治理
|
||
|
||
> Status: Draft
|
||
> Owner: TBD
|
||
> Last updated: 2026-07-11
|
||
> Related implementation: [PR #5263](https://github.com/multica-ai/multica/pull/5263)
|
||
|
||
## TL;DR
|
||
|
||
Multica 当前的主要 UI 问题不是缺少颜色 token、Button 或 Card,而是缺少一层被明确命名、文档化和持续执行的 **Page Pattern Layer(页面模式层)**。
|
||
|
||
现有基础大致分成三层:
|
||
|
||
1. `packages/ui/styles/` 已经提供颜色、surface、间距等设计 token。
|
||
2. `packages/ui/components/` 已经提供 Button、Input、Card、Tabs、Empty 等基础组件。
|
||
3. `packages/views/` 中也已经出现 `CollectionPageHeader`、`CollectionPageState`、`SettingsTab`、`SettingsSection`、`SettingsCard`、`SettingsRow` 等页面模式的早期实现。
|
||
|
||
但第三层仍然是局部的、未完成的:没有覆盖所有主要页面类型,没有清晰的使用边界,也没有 review checklist 或迁移计划。因此业务页面仍然会自行决定标题、导航、卡片、分割线、表单、空状态和保存反馈,最终形成“基础组件相同,但页面体验不同”的局面。
|
||
|
||
Agent 详情页重构是页面模式层的一次试点,不应停留在单页优化。下一步应该把其中可复用的结构提炼为明确的页面模式,再逐步迁移其他页面。
|
||
|
||
---
|
||
|
||
## 1. 文档目的
|
||
|
||
本文档用于:
|
||
|
||
- 记录本轮 UI review 中发现的问题,避免问题只存在于对话和截图中。
|
||
- 明确 UI 不一致的架构根因,而不是继续逐页修补 CSS。
|
||
- 区分 Design Token、基础组件、页面模式和业务页面各自的职责。
|
||
- 记录 Agent 详情页试点中已经处理或仍需验证的事项。
|
||
- 给出下一阶段 UI 治理的优先级、验收标准和开放问题。
|
||
|
||
本文档不是新的视觉规范。颜色、字体、surface、间距和基础交互仍以 [`docs/design.md`](./design.md) 为准。
|
||
|
||
---
|
||
|
||
## 2. 核心判断:缺失的是页面模式层
|
||
|
||
### 2.1 当前 UI 分层
|
||
|
||
| 层级 | 回答的问题 | 当前载体 | 当前状态 |
|
||
| --- | --- | --- | --- |
|
||
| Design Token | 颜色、间距、圆角、阴影应该是什么 | `packages/ui/styles/`、`docs/design.md` | 基本完整 |
|
||
| UI Primitive | Button、Input、Card、Tabs 如何表现 | `packages/ui/components/` | 基本完整 |
|
||
| Page Pattern | 页面标题、分区、导航、列表、设置表单、状态页如何组合 | `packages/views/layout/`、`packages/views/settings/components/settings-layout.tsx` 等 | **局部存在,但未固化** |
|
||
| Business Page | Agent、Issue、Runtime 等具体业务如何呈现 | `packages/views/<domain>/` | 大量自行组合 |
|
||
|
||
Token 和 Primitive 只能保证局部视觉相似,不能自动保证页面一致。它们不会回答以下问题:
|
||
|
||
- 列表页标题、数量、描述和主操作应该放在哪里?
|
||
- 设置页应该用卡片还是平铺?一行可以放几个设置?
|
||
- 二级导航应该横向还是纵向?什么时候需要 URL 深链?
|
||
- Detail 页面如何区分状态概览、工作记录和配置?
|
||
- Empty、Loading、Error、Not Found 是否共享尺寸和文案结构?
|
||
- 可编辑列表是持续显示多个 Input,还是列表 + 单个 composer?
|
||
- 保存状态、未保存提醒和离开保护如何统一?
|
||
|
||
如果这些问题没有标准答案,每个业务页面就会重新设计一次。
|
||
|
||
### 2.2 根因
|
||
|
||
当前问题可以概括为:
|
||
|
||
> 底层 token 和基础组件已经比较完整,但中间的“页面模式层”没有被明确固化,也没有被持续执行。
|
||
|
||
具体表现为:
|
||
|
||
1. **模式没有被命名。** 开发者知道有 Card、Tabs 和 Empty,但不知道当前页面属于 Collection、Settings 还是 Workbench Detail。
|
||
2. **模式没有完整覆盖。** Collection 和 Settings 已经有早期抽象,Detail、Editable List、Inspector、Split Pane 等仍主要由页面自行实现。
|
||
3. **模式没有使用边界。** 什么时候用 Card、什么时候只用 spacing、什么时候允许 divider,仍依赖个人判断。
|
||
4. **模式没有持续执行。** 缺少新页面 checklist、视觉回归样例和跨页面 review,局部 PR 很容易重新引入平行实现。
|
||
5. **复用多停留在 JSX。** 相似页面会复制布局 class,而不是复用带语义的页面组件;一旦规范变化,需要逐页修改。
|
||
|
||
---
|
||
|
||
## 3. 已发现的问题
|
||
|
||
### 3.1 全局问题
|
||
|
||
| 类别 | 当前问题 | 影响 |
|
||
| --- | --- | --- |
|
||
| 页面 Header | 标题高度、左右 padding、数量、描述和操作区组合不一致 | 页面切换时节奏跳变 |
|
||
| 二级导航 | 同类配置有的横向、有的纵向,有的只存在本地 state | 信息架构和深链行为不稳定 |
|
||
| Section 分组 | Card、divider、背景色和纯 spacing 混用,缺少明确优先级 | 页面过重或分组不清 |
|
||
| 表单布局 | 单行单项、双列设置、label/value 比例和保存区位置不一致 | 扫读和操作成本增加 |
|
||
| 列表编辑 | 有的持续显示 Input,有的用 dialog,有的就地编辑 | 同类操作需要重新学习 |
|
||
| 状态页面 | Empty、Loading、Error、Not Found 各自实现 | 图标、留白、文案和操作不一致 |
|
||
| 保存反馈 | Toast、inline status、disabled button、dirty guard 组合不统一 | 用户无法稳定判断是否已保存 |
|
||
| 内容约束 | 长描述、代码、ID 和用户输入的换行/截断策略不统一 | 容易溢出或出现密集文本墙 |
|
||
| 响应式与无障碍 | icon-only action、focus、移动端折叠依赖页面自行处理 | 容易产生不可访问或小屏失效的页面 |
|
||
|
||
### 3.2 Agent 详情页问题记录
|
||
|
||
状态说明:
|
||
|
||
- **已实现**:当前 Agent 详情页重构分支已有对应实现。
|
||
- **试点中**:已在 Agent 页面采用,但尚未抽象或推广为全局模式。
|
||
- **待验证**:需要在合并前进行完整视觉或交互回归。
|
||
- **开放**:仍需要产品或架构决策。
|
||
|
||
| 区域 | 问题 | 处理方向 | 状态 |
|
||
| --- | --- | --- | --- |
|
||
| 整体信息架构 | 原详情页更像后端字段检查器,观察、工作和配置混在一起 | 重组为 Overview、Work、Capabilities、Settings | 试点中 |
|
||
| 二级导航 | Capabilities 与 Settings 的二级选项使用横向菜单,扩展后拥挤 | 桌面端采用稳定的纵向 section nav,并保持 URL 深链 | 已实现 |
|
||
| Integrations | 本地 feature flag 默认关闭,Capabilities 中缺少 Integrations | 根据系统配置显示 Integrations,并纳入 Capabilities | 已实现 |
|
||
| Overview / Attention | “Tasks Need Attention”价值不明确、优先级过高 | 无明确干预价值时移除,不制造伪告警 | 已实现 |
|
||
| Overview / Recent Work | 条目过少;Issue 维度还是 Session 维度没有明确 | 增加可见条目;产品语义见开放问题 §8.1 | 试点中 |
|
||
| Overview / Skills | 多个 skill 时 divider 与下方横线粘连 | 优先用 spacing 分组,避免连续 divider | 待验证 |
|
||
| Instructions | System Prompt 被设计成单行 Input | 使用支持长文本、Markdown 和合理高度的 Textarea | 已实现 |
|
||
| MCP | 描述过长,缺少换行和信息层级,呈现为密集文本墙 | 缩短主文案,把说明拆成辅助信息并约束宽度 | 已实现 |
|
||
| General | 信息展示感强,不像配置页;Visibility 等交互不顺手 | 使用标准 Settings section/row,明确 label、description、control | 试点中 |
|
||
| Settings 分组 | 页面缺少稳定分组,或使用不符合 surface 规范的 Card | 独立设置组使用白色 SettingsCard;组间使用 section spacing | 已实现 |
|
||
| Settings 行布局 | 一行放两个 setting,扫读和响应式表现差 | 默认单行单项;除非字段天然组成一个原子输入 | 已实现 |
|
||
| Access | Shared 等权限不是简单 toggle,现有交互不能表达复杂规则 | Access 独立为 Settings 子 Tab,使用专门权限模型 | 试点中 |
|
||
| Details | Owner、Created、Updated 等只读元数据被放进 Settings | 从可编辑设置中移出,放到 Overview 或 inspector | 已实现 |
|
||
| Environment | 当前结构可暂时保留 | 后续迁移到统一 editable key-value pattern | 开放 |
|
||
| Custom Args | 横线过多;每个参数永久显示为 Input;新增一项就增加一个输入框和 divider | 改为有序 token 列表;只有新增/编辑项进入 composer;独立命令预览 | 已实现 |
|
||
|
||
### 3.3 Custom Args 暴露出的通用模式问题
|
||
|
||
Custom Args 并不只是一个局部样式问题,它暴露了 “Editable List” 页面模式缺失:
|
||
|
||
- 数据在静止状态下应该首先是列表,不是表单。
|
||
- 编辑态应该是临时状态,不应该让所有条目永久显示为 Input。
|
||
- 新增操作应该把内容加入列表,而不是无限扩张表单结构。
|
||
- 参数顺序有语义,应明确显示顺序。
|
||
- 每个列表项对应一个 argv token;包含空格的 token 不应被前端自行拆分。
|
||
- 命令预览属于结果反馈,应和编辑列表分开呈现。
|
||
|
||
这个模式未来可以复用于:Custom Args、Environment Variables、Webhook Headers、Repository Rules、Token/Secret 列表等,但不同数据类型需要保留各自的验证和敏感信息策略。
|
||
|
||
---
|
||
|
||
## 4. 建议固化的页面模式
|
||
|
||
### 4.1 Collection Page
|
||
|
||
适用于 Agents、Projects、Skills、Runtimes、Squads、Autopilots 等实体集合。
|
||
|
||
应统一:
|
||
|
||
- Header 的 icon、title、count、description 和 actions。
|
||
- 列表/网格容器的 page padding 和滚动策略。
|
||
- Empty、Loading、Error、No Results 状态。
|
||
- 主操作在小屏下的收缩方式。
|
||
- 筛选、搜索和视图切换的位置。
|
||
|
||
现有基础:
|
||
|
||
- `packages/views/layout/collection-page.tsx`
|
||
- `CollectionPageHeader`
|
||
- `CollectionPageHeaderAction`
|
||
- `CollectionPageState`
|
||
|
||
下一步不是再造一套组件,而是补齐使用文档、样例和迁移覆盖。
|
||
|
||
### 4.2 Settings Page
|
||
|
||
适用于 Workspace Settings、Account Settings、Agent Settings 和其他配置型页面。
|
||
|
||
应统一:
|
||
|
||
- `SettingsTab → SettingsSection → SettingsCard → SettingsRow` 的层级。
|
||
- 默认单行单项;复杂 compound control 必须说明原因。
|
||
- label、description 和 control 的宽度与对齐。
|
||
- auto-save 与 explicit save 两种模式的反馈。
|
||
- dirty state、离开保护、error 和 success 状态。
|
||
- 权限不足时的只读表现。
|
||
|
||
现有基础:
|
||
|
||
- `packages/views/settings/components/settings-layout.tsx`
|
||
- `SettingsTab`
|
||
- `SettingsSection`
|
||
- `SettingsCard`
|
||
- `SettingsRow`
|
||
- `SettingsSaveState`
|
||
|
||
需要决定这些组件是否继续归属于 Settings domain,还是迁移到更通用的 `packages/views/layout/`。
|
||
|
||
### 4.3 Workbench Detail Page
|
||
|
||
适用于 Agent、Runtime、Squad、Member 等同时包含身份、状态、历史和配置的详情页。
|
||
|
||
应统一:
|
||
|
||
- Identity header:名称、状态、关键 metadata 和主操作。
|
||
- 一级导航:Overview、Work/Activity、Capabilities、Settings。
|
||
- 二级导航:当选项超过 2–3 个或文案较长时使用纵向 section nav。
|
||
- Overview 只呈现判断和行动所需的信息,不复制全部字段。
|
||
- Settings 只放可编辑配置;只读 metadata 不混入设置。
|
||
- URL 必须反映 tab/section 状态,支持刷新和分享。
|
||
- 不为不存在的健康度或进度制造伪指标。
|
||
|
||
Agent 详情页是此模式的第一个试点,但不能直接把 Agent 业务组件当作全局抽象。应先识别 Runtime、Squad、Member 的共同结构,再定义最小公共 API。
|
||
|
||
### 4.4 Editable List
|
||
|
||
适用于用户维护一个有序或无序的小型配置集合。
|
||
|
||
默认交互:
|
||
|
||
1. 静止状态显示列表项。
|
||
2. 点击 Add 后只出现一个 composer。
|
||
3. 点击 Edit 后只让目标项进入编辑态。
|
||
4. Enter 提交,Escape 取消;新增/编辑时焦点进入输入区。
|
||
5. 删除先更新本地 draft;外部持久化由统一 Save 或 auto-save 策略负责。
|
||
6. 空状态仍保留清晰的主操作。
|
||
7. 长值必须支持截断、换行或展开查看。
|
||
|
||
不应把所有 Editable List 都抽成一个万能业务组件。可以共享布局、状态和 action slot,但验证、字段结构和安全策略留在 domain 层。
|
||
|
||
### 4.5 Page State
|
||
|
||
所有页面至少需要明确以下状态:
|
||
|
||
- Initial loading
|
||
- Background refreshing
|
||
- Empty
|
||
- No search results
|
||
- Permission denied
|
||
- Not found
|
||
- Recoverable error
|
||
- Fatal error
|
||
|
||
这些状态应复用一致的尺寸、语气和 action 位置,但不能用同一条空状态文案覆盖不同原因。
|
||
|
||
---
|
||
|
||
## 5. 组件归属原则
|
||
|
||
| 内容 | 推荐位置 | 约束 |
|
||
| --- | --- | --- |
|
||
| 无业务语义的原子组件 | `packages/ui/` | 不得依赖 `@multica/core` |
|
||
| 跨 domain 的页面模式 | `packages/views/layout/` | 只定义布局、slot 和交互契约 |
|
||
| 某类页面的共享模式 | `packages/views/<domain-or-pattern>/` | 允许有限业务语义,但不得绑定平台路由 |
|
||
| 具体业务页面 | `packages/views/<domain>/` | 组合模式并负责数据、权限和文案 |
|
||
| Next.js / Electron 接线 | app platform layer | 不进入 shared views |
|
||
|
||
判断一个结构是否应该抽取时,优先问:
|
||
|
||
1. 它表达的是视觉细节,还是稳定的页面语义?
|
||
2. 第二个真实使用者是谁?
|
||
3. 抽取后能否减少业务页面对 spacing、divider、responsive class 的重复决策?
|
||
4. 是否能通过 slot 保持业务差异,而不是制造大量 boolean prop?
|
||
|
||
---
|
||
|
||
## 6. 下一步实施计划
|
||
|
||
### Phase 0:建立基线
|
||
|
||
- [ ] 为 Collection、Settings、Workbench Detail、Editable List、Page State 各补一个 canonical example。
|
||
- [ ] 建立页面清单,标记每个页面当前采用的模式和偏差。
|
||
- [x] 给 `docs/design.md` 增加本文件入口。
|
||
- [ ] 确认 Agent 详情页试点的视觉和交互验收结果。
|
||
|
||
### Phase 1:固化现有模式
|
||
|
||
- [ ] 补齐 Collection Page 的 loading、filter toolbar 和 responsive 规范。
|
||
- [ ] 明确 Settings explicit-save / auto-save 两套状态契约。
|
||
- [ ] 从 Agent 详情页提炼最小 Workbench Detail shell,而不是复制整页。
|
||
- [ ] 提炼 Editable List 的布局契约,并用第二个真实页面验证抽象。
|
||
- [ ] 为 pattern components 增加结构和无障碍测试。
|
||
|
||
### Phase 2:迁移高频页面
|
||
|
||
建议优先级:
|
||
|
||
1. Agents / Skills / Runtimes / Projects 等 collection 页面。
|
||
2. Workspace Settings 与 Agent Settings。
|
||
3. Runtime / Squad / Member detail 页面。
|
||
4. Environment、Custom Args 和其他 editable configuration lists。
|
||
|
||
每次迁移应是小 PR,不在同一 PR 中同时改变业务行为和全局视觉规范。
|
||
|
||
### Phase 3:持续执行
|
||
|
||
- [ ] 在 PR template 中加入 Page Pattern checklist。
|
||
- [ ] 新页面必须声明采用的 page pattern;偏离时说明原因。
|
||
- [ ] 给 canonical examples 增加 light/dark、中文/英文和窄屏视觉回归。
|
||
- [ ] 定期删除迁移后遗留的平行组件和重复 class 组合。
|
||
- [ ] 将审计从一次性项目变成每个季度的 UI consistency review。
|
||
|
||
---
|
||
|
||
## 7. 验收标准
|
||
|
||
页面模式层达到可用状态,需要同时满足:
|
||
|
||
1. 新页面可以先选择页面模式,再填充业务内容,而不是从空白 `<div>` 开始。
|
||
2. 同类页面的 header、导航、section、empty/error 和 action 位置一致。
|
||
3. 业务页面不再重复决定基础 padding、divider、card 和保存反馈。
|
||
4. 模式组件支持 keyboard、focus、overflow、responsive 和 i18n 长文案。
|
||
5. light/dark、中文/英文、desktop/web 至少有 canonical visual coverage。
|
||
6. 模式允许业务差异,但偏差是显式决定,不是无意复制。
|
||
7. 新抽象至少由两个真实页面验证,避免只为单页包装 JSX。
|
||
|
||
---
|
||
|
||
## 8. 开放问题
|
||
|
||
### 8.1 Agent Recent Work 使用 Issue 还是 Session 维度
|
||
|
||
需要先确认该区块回答的问题:
|
||
|
||
- 如果回答“这个 Agent 最近交付了什么”,Issue/Task 是更接近用户心智的单位。
|
||
- 如果回答“这个 Agent 最近每次执行发生了什么”,Session 是更准确的诊断单位。
|
||
|
||
建议不要在同一个平铺列表中混合两个粒度。可以默认使用 Issue/Task 维度,把最新 Session 状态作为行内 metadata;完整 Session 历史留在 Work 页面。
|
||
|
||
### 8.2 Settings pattern 的归属
|
||
|
||
当前实现位于 `packages/views/settings/components/settings-layout.tsx`,但 Agent Settings 已经复用它。需要决定:
|
||
|
||
- 保持当前位置,把 Settings 当作共享 pattern package;或
|
||
- 迁移到 `packages/views/layout/settings-*`,让归属与实际用途一致。
|
||
|
||
在迁移前不要再创建第二套 Settings layout。
|
||
|
||
### 8.3 Card 与 flat section 的边界
|
||
|
||
默认遵循 `docs/design.md` 的容器优先级:spacing → 单条 divider → 背景变化 → Card。
|
||
|
||
建议补充的判断是:
|
||
|
||
- 独立设置组、可整体操作的信息块可以使用 Card。
|
||
- 连续阅读内容、元数据清单和普通列表不应每项一张 Card。
|
||
- Card 内不要再通过多层 border 制造“卡片套卡片”。
|
||
|
||
### 8.4 Detail pattern 的最小公共部分
|
||
|
||
Agent、Runtime、Squad 和 Member 的详情页并不完全相同。抽象前需要确认真正共享的是 shell、header、navigation 和 section layout,还是还包括 inspector。原则上优先抽取稳定外壳,业务内容通过 slot 注入。
|
||
|
||
---
|
||
|
||
## 9. 新页面 Review Checklist
|
||
|
||
- [ ] 这个页面属于哪一种 page pattern?
|
||
- [ ] 是否复用了现有 Header、Section、State 和 Action 模式?
|
||
- [ ] 是否出现了业务页面自定义的 Card、divider 或 empty state?为什么?
|
||
- [ ] 设置是否默认单行单项?复合字段是否真的是一个原子输入?
|
||
- [ ] URL 是否反映 tab、filter、pagination 或 section 等可分享状态?
|
||
- [ ] Loading、Empty、Error、Permission 和 Not Found 是否被分别处理?
|
||
- [ ] 长文案、长 ID、用户输入和窄屏是否不会溢出?
|
||
- [ ] icon-only button 是否有 accessible name?键盘 focus 是否可见?
|
||
- [ ] light/dark 和至少一种 CJK locale 是否完成视觉检查?
|
||
- [ ] 是否新增了一个只服务当前页面、但其实表达通用模式的本地组件?
|
||
|
||
---
|
||
|
||
## 10. 相关文件
|
||
|
||
- [`docs/design.md`](./design.md)
|
||
- `packages/ui/styles/tokens.css`
|
||
- `packages/ui/components/`
|
||
- `packages/views/layout/collection-page.tsx`
|
||
- `packages/views/layout/page-header.tsx`
|
||
- `packages/views/settings/components/settings-layout.tsx`
|
||
- `packages/views/agents/components/agent-detail-page.tsx`
|
||
- `packages/views/agents/components/agent-overview-pane.tsx`
|
||
- `packages/views/agents/components/tabs/custom-args-tab.tsx`
|