Commit 3a842f4f authored by edy's avatar edy

docs(ui): add client ui ux execution plan

parent bd61e8e6
# 客户端 UI/UX 整改执行计划
> **For agentic workers:** REQUIRED SUB-SKILL: Use `superpowers:subagent-driven-development` (recommended) or `superpowers:executing-plans` to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** 基于当前客户端代码事实,把 renderer 收敛成更稳定、更专业、更易维护的 AI 桌面工作台。
**Architecture:** 不重写业务链路,不改 Electron IPC 合约。先固化事实基线和样式边界,再逐步压薄 `App.tsx`、收敛 CSS 覆盖、补齐工作台交互和可访问性。
**Tech Stack:** Electron renderer, Vite, React 19, TypeScript, plain CSS modules via `apps/ui/src/styles.css`, existing smoke hooks.
---
## 1. 当前事实基线
### 代码结构
- `apps/ui/src/App.tsx` 当前约 1674 行,仍承担顶层状态编排、视图切换、会话控制、设置 props 组装、smoke hooks 和启动遮罩。
- `apps/ui/src/styles.css` 已是入口文件,只 import `apps/ui/src/styles/*.css`
- 主样式分散在 `base.css``components.css``shell.css``chat.css``settings.css``plugins.css``knowledge.css``tasks.css``automation.css``theme-openclaw.css`
- 聊天主工作区已拆到 `features/chat/ConversationWorkspaceView.tsx`,但 props 数量过多,说明页面边界仍不够稳定。
- 通用 UI 组件已存在:`Button``IconButton``Panel``ScrollArea``StatusChip``Tabs`
### UI/UX 基线
- 产品类型:AI 生产力桌面客户端,核心体验应接近运营工作台,而不是营销页或普通聊天 demo。
- 当前优势:两栏骨架稳定、聊天/附件/流式状态完整、部分 focus 和 `aria-live` 已存在。
- 当前风险:CSS 多层覆盖、视觉蓝紫/玻璃/渐变偏多、移动断点不完整、导航密集但缺少 skip link、部分页面仍有 emoji 或手写 SVG 图标。
- 重点约束:继续保留 `conversation-shell``conversation-main-layout``conversation-content-area``conversation-panel`,不得破坏 smoke helpers 依赖的 DOM 和 selector。
## 2. 执行原则
- 不做一次性重写,每个阶段必须独立通过 typecheck/build。
- 优先修维护风险,再修视觉观感。
- 不改 `packages/shared-types` IPC 契约,除非单独立项。
- 不删除或隐藏现有 UI 控件,除非先确认 smoke helpers 和 renderer test 不依赖。
- 修改 `App.tsx` 时只用小 patch,避免中文编码损坏;修改后检查无 UTF-8 BOM。
- 工作台视觉以灰白为主、蓝色为状态和关键操作辅助,减少紫色渐变、彩色发光和过强阴影。
## 3. Phase 1 - 建立 UI 回归基线
**目标:** 先形成可复测基线,避免后续 UI 调整凭主观判断推进。
**Files:**
- Modify: `docs/2026-05-25-client-ui-ux-execution-plan.md`
- Read-only reference: `apps/ui/src/App.tsx`
- Read-only reference: `apps/ui/src/styles.css`
- Read-only reference: `apps/ui/src/styles/*.css`
- Read-only reference: `apps/ui/test/*.test.ts`
- [ ] **Step 1: 记录当前核心文件规模**
Run:
```sh
wc -l apps/ui/src/App.tsx apps/ui/src/styles.css apps/ui/src/styles/*.css
```
Expected:
- 记录 `App.tsx` 行数。
- 记录每个 CSS 文件行数。
- 如果 `theme-openclaw.css``shell.css``components.css` 仍是最大样式文件,后续 CSS 收口优先从这三处开始。
- [ ] **Step 2: 记录核心布局类定义位置**
Run:
```sh
rg -n "^\\.(shell|sidebar|main-shell|content-area|conversation-panel|message-list|composer-shell)\\b|\\.conversation-shell \\." apps/ui/src/styles/*.css
```
Expected:
- 输出所有核心类定义位置。
- 标出基础定义、聊天覆盖、主题覆盖三类来源。
- 不在本阶段删除样式,只形成清单。
- [ ] **Step 3: 跑基础验证**
Run:
```sh
corepack pnpm --filter @qjclaw/ui typecheck
corepack pnpm build
```
Expected:
- 两个命令通过。
- 如果失败,先修复当前失败,不进入 Phase 2。
- [ ] **Step 4: 保存基线截图**
Start app:
```sh
corepack pnpm dev
```
Capture these views manually or with Playwright:
- Chat home
- Expert chat
- Task panel
- Automation tasks
- Knowledge
- Settings
Expected:
- 每个页面有桌面宽度截图。
- 至少补一张窄宽度截图,确认 `min-width: 960px` 的实际行为。
## 4. Phase 2 - 收敛 CSS 骨架和视觉 token
**目标:** 让核心布局类只有清晰的基础层和主题层,减少后续 UI 回归。
**Files:**
- Modify: `apps/ui/src/styles/base.css`
- Modify: `apps/ui/src/styles/components.css`
- Modify: `apps/ui/src/styles/shell.css`
- Modify: `apps/ui/src/styles/chat.css`
- Modify: `apps/ui/src/styles/theme-openclaw.css`
- [ ] **Step 1: 建立 token 边界**
In `apps/ui/src/styles/theme-openclaw.css`, keep all product-level theme variables under:
```css
.shell.openclaw-theme {
--revamp-canvas: #f5f7fa;
--revamp-surface: #ffffff;
--revamp-surface-soft: #f8fafc;
--revamp-text: #0f172a;
--revamp-text-muted: #475569;
--revamp-text-soft: #64748b;
--revamp-blue: #2563eb;
--revamp-blue-strong: #1d4ed8;
--revamp-blue-soft: #eff6ff;
--revamp-border: rgba(148, 163, 184, 0.24);
--revamp-border-strong: rgba(148, 163, 184, 0.38);
--revamp-shadow: 0 14px 32px rgba(15, 23, 42, 0.06);
--revamp-shadow-soft: 0 8px 18px rgba(15, 23, 42, 0.04);
}
```
Expected:
- Purple variables may remain only where still referenced by legacy expert-specific styles.
- New or touched styles use the gray/blue token set above.
- [ ] **Step 2: Reduce duplicate core layout definitions**
Keep responsibilities:
- `base.css`: reset, root tokens, font, body.
- `components.css`: generic reusable components only.
- `shell.css`: base shell layout and non-theme structural behavior.
- `chat.css`: conversation-specific structure only under `.conversation-shell`.
- `theme-openclaw.css`: final product skin and current gray/blue visual theme.
Expected:
- No new global `.message-list` or `.composer-shell` visual overrides outside the intended layer.
- Conversation-only changes remain scoped under `.conversation-shell ...`.
- [ ] **Step 3: Remove obvious visual noise**
In touched rules:
- Replace heavy color shadows with `var(--revamp-shadow-soft)` or border-only states.
- Avoid new `translateY` hover movement.
- Keep card radius at or below existing app norms unless the rule already requires larger panels.
- Do not add decorative orbs, bokeh, or unrelated gradients.
Expected:
- Left sidebar and workspace feel calmer.
- Active/hover/focus states remain visible.
- [ ] **Step 4: Validate after CSS edits**
Run:
```sh
corepack pnpm --filter @qjclaw/ui typecheck
corepack pnpm build
```
Expected:
- Both pass.
- `git diff -- apps/ui/src/styles.css apps/ui/src/styles/*.css` shows targeted CSS changes only.
## 5. Phase 3 - 压薄 App.tsx 的 UI 编排
**目标:** 降低 `App.tsx` 的维护风险,但不碰 stream 主链路和 smoke action 协议。
**Files:**
- Modify: `apps/ui/src/App.tsx`
- Modify: `apps/ui/src/features/chat/ConversationWorkspaceView.tsx`
- Modify: `apps/ui/src/features/settings/SettingsPanels.tsx`
- Create or modify focused hooks only under existing `apps/ui/src/features/*`
- [ ] **Step 1: 拆出纯 props 组装**
Move only pure prop-building logic from `App.tsx` into focused helpers or hooks when all inputs are already available.
Candidate boundaries:
- Conversation workspace props.
- Settings panel props.
- Sidebar derived labels and entries.
Expected:
- No behavior change.
- No IPC calls move across ownership boundaries in this step.
- `App.tsx` line count decreases, but line count is not the success metric; clearer ownership is.
- [ ] **Step 2: Keep high-risk flows in place**
Do not move these during this phase:
- stream request lifecycle
- `__QJC_SMOKE__`
- `__QJC_SMOKE_ACTIONS__`
- composer submit/cancel
- session creation/closing
- startup overlay retry/export actions
Expected:
- Existing smoke tests do not need selector or action rewrites.
- [ ] **Step 3: Reduce oversized component props**
For `ConversationWorkspaceView`, group related props into typed objects only when ownership is obvious:
- `status`
- `emptyState`
- `messages`
- `composer`
- `actions`
Expected:
- Component call site becomes easier to read.
- Existing child component props stay unchanged unless required.
- [ ] **Step 4: Validate App.tsx encoding and tests**
Run:
```sh
/usr/bin/python3 -c "from pathlib import Path; p=Path('apps/ui/src/App.tsx'); b=p.read_bytes(); print(b[:3]); assert b[:3] != b'\\xef\\xbb\\xbf'"
git diff -- apps/ui/src/App.tsx
corepack pnpm --filter @qjclaw/ui typecheck
```
Expected:
- First command prints bytes that are not UTF-8 BOM.
- Diff contains no mojibake and no unrelated Chinese copy changes.
- UI typecheck passes.
## 6. Phase 4 - 修正核心工作流 UI/UX
**目标:** 优先改善用户每天会反复使用的界面:聊天、任务、自动化、设置。
**Files:**
- Modify: `apps/ui/src/features/chat/ChatComposer.tsx`
- Modify: `apps/ui/src/features/chat/MessageList.tsx`
- Modify: `apps/ui/src/features/tasks/TaskPanelView.tsx`
- Modify: `apps/ui/src/features/automation/AutomationTasksView.tsx`
- Modify: `apps/ui/src/features/settings/SettingsPanels.tsx`
- Modify: matching CSS files under `apps/ui/src/styles/`
- [ ] **Step 1: Chat composer**
Requirements:
- Keep Enter send and Shift+Enter newline behavior.
- Keep attachment upload button and drag-drop.
- Keep resize handle.
- Ensure disabled state remains readable.
- Ensure focus state uses one consistent blue ring.
Expected:
- Composer does not resize the main shell unexpectedly.
- Attachment chip text truncates cleanly.
- Submit button remains icon-first with accessible label.
- [ ] **Step 2: Message list**
Requirements:
- Keep user messages right-aligned and assistant messages left-aligned.
- Keep assistant markdown card readable at long line lengths.
- Keep copy/delete action buttons keyboard reachable.
- Keep streaming trace `aria-live` behavior.
Expected:
- Long Chinese, English, URLs, and code blocks do not break layout.
- Message actions do not shift message height when appearing.
- [ ] **Step 3: Task panel icon cleanup**
Replace visible emoji used as UI icons with existing icon components or local SVG components.
Known target:
- `apps/ui/src/features/tasks/TaskPanelView.tsx`: package icon in the content output heading.
Expected:
- No visible emoji icons remain in primary tool controls or headings.
- Existing Chinese text remains unchanged except for necessary label updates.
- [ ] **Step 4: Automation tasks density**
Requirements:
- Keep list, detail, form, and run history usable without window-level scroll confusion.
- Filter buttons and edit/create actions must have clear active and disabled states.
- Error state must use `role="alert"` or visible announced equivalent.
Expected:
- The page reads as an operational tool, not a card-heavy marketing layout.
- Long task prompts truncate or wrap predictably.
- [ ] **Step 5: Settings hierarchy**
Requirements:
- Keep config source toggle visible and keyboard reachable.
- Secret reveal and copy controls must stay accessible.
- Save/reset/edit buttons must communicate disabled state clearly.
- Tabs must preserve `aria` semantics from existing `Tabs` component.
Expected:
- Users can scan required vs optional config groups quickly.
- Editing one section does not visually imply other sections are editing.
- [ ] **Step 6: Validate key workflows**
Run:
```sh
corepack pnpm --filter @qjclaw/ui typecheck
corepack pnpm build
```
If touched flow has existing source tests, also run:
```sh
node --test apps/ui/test/taskPanelViewSource.test.ts
node --test apps/ui/test/settingsPanelsSource.test.ts
node --test apps/ui/test/chatCancelSource.test.ts
```
Expected:
- Typecheck and build pass.
- Relevant source tests pass.
## 7. Phase 5 - 可访问性和响应式补齐
**目标:** 解决 UI-ux-pro-max 指出的高优先级问题:键盘导航、skip link、错误提示、图片 alt、响应式边界。
**Files:**
- Modify: `apps/ui/src/App.tsx`
- Modify: `apps/ui/src/features/shell/AppSidebar.tsx`
- Modify: `apps/ui/src/features/shell/Sidebar.tsx`
- Modify: `apps/ui/src/styles/base.css`
- Modify: `apps/ui/src/styles/shell.css`
- Modify: `apps/ui/src/styles/theme-openclaw.css`
- [ ] **Step 1: Add skip link**
Add a visually hidden but focus-visible skip link near the top of the shell:
```tsx
<a className="skip-link" href="#main-content">跳到主内容</a>
```
Add id to main content:
```tsx
<main id="main-content" className={...}>
```
Expected:
- First Tab focuses skip link.
- Pressing Enter moves focus target to main content.
- [ ] **Step 2: Add skip link styles**
Add CSS:
```css
.skip-link {
position: fixed;
top: 10px;
left: 10px;
z-index: 10000;
padding: 8px 12px;
border-radius: 8px;
background: #ffffff;
color: #1d4ed8;
border: 1px solid rgba(37, 99, 235, 0.38);
transform: translateY(-140%);
}
.skip-link:focus-visible {
transform: translateY(0);
outline: 2px solid rgba(37, 99, 235, 0.56);
outline-offset: 2px;
}
```
Expected:
- Hidden by default.
- Visible only when focused.
- [ ] **Step 3: Confirm nav tab order**
Manual validation:
- Tab order starts at skip link.
- Then window controls if focusable.
- Then sidebar primary navigation.
- Then page/workspace content.
- Then composer or page actions.
Expected:
- No keyboard trap.
- No hidden active control receives focus unless intentionally screen-reader-only.
- [ ] **Step 4: Define desktop responsive contract**
Current shell uses `min-width: 960px`. Keep that if the product is desktop-only, but document it in CSS comments and acceptance notes.
Expected:
- At widths below 960px, behavior is intentional: either horizontal app viewport constraint or a later mobile-specific plan.
- Do not pretend mobile is supported unless the shell actually supports it.
- [ ] **Step 5: Validate accessibility basics**
Manual checks:
- Error messages announce via `role="alert"` or `aria-live`.
- Meaningful images have alt text; decorative images use `alt=""`.
- Buttons with icon-only visuals have `aria-label`.
- Heading hierarchy per page starts with one clear `h1` or equivalent page title.
Expected:
- No obvious keyboard-only blocker in chat, settings, task panel, automation tasks.
## 8. Final Acceptance Checklist
- [ ] `corepack pnpm --filter @qjclaw/ui typecheck` passes.
- [ ] `corepack pnpm build` passes.
- [ ] Relevant source tests pass for touched views.
- [ ] `App.tsx` has no UTF-8 BOM.
- [ ] `git diff -- apps/ui/src/App.tsx` shows no Chinese mojibake.
- [ ] Chat, experts, tasks, automation, knowledge, settings render with correct height and scrolling.
- [ ] Left sidebar remains left column; right workspace remains full work area.
- [ ] No core smoke selector or `__QJC_SMOKE_ACTIONS__` contract is removed.
- [ ] No visible emoji remains in primary tool controls after Phase 4.
- [ ] Focus-visible states are visible in sidebar, composer, tabs, settings controls, and message actions.
## 9. Suggested Commit Sequence
1. `docs(ui): add client ui ux execution plan`
2. `refactor(ui): document and reduce shell style overlap`
3. `refactor(ui): reduce app renderer prop assembly`
4. `fix(ui): polish chat workspace interactions`
5. `fix(ui): align task automation settings workbench ui`
6. `fix(ui): add renderer keyboard navigation affordances`
Each commit should include the validation commands run in the commit body or PR description.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment