From df617176810b31527d83ae9145c571e0b347abee Mon Sep 17 00:00:00 2001 From: zhangkunshi Date: Sun, 19 Apr 2026 22:30:11 +0800 Subject: [PATCH] =?UTF-8?q?feat(sprint-6):=20HTML=20=E5=8F=AF=E4=BA=A4?= =?UTF-8?q?=E4=BA=92=E5=8E=9F=E5=9E=8B=20+=20=E6=A8=A1=E5=9D=97=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=E6=98=A0=E5=B0=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Phase 2 Sprint 6 ⑥ 进一步产出 —— 把 wireframes 升级为可点开的 HTML 原型,加"原型↔模块↔Swift 文件"映射表,作为 Sprint 7 的 权威实施源。 新建 docs/design/ui/prototype/: - index.html 导航中心(10 张卡片,点开预览) - styles.css 共享 design tokens(颜色/字号/间距) - 01-10.html 10 个原型页面 原型覆盖: - 01 主视图三栏 (sidebar + chat + artifact 真实布局) - 02 首次启动向导 (4 步互动,可点步骤跳转) - 03 设置页 (4 tab,toggle 可点) - 04 斜杠命令面板 (Spotlight 风格 + 10 个 CLI 子命令) - 05 Artifact 全屏详情 (大纲 + 内容 + 版本对比 UI) - 06 供应商切换 (浮层 + 二次确认 + 上下文重塑) - 07 全局搜索 ⌘K (分组结果 + 高亮) - 08 会话右键菜单 (收藏/分组/多选/删除) - 09 空状态合集 (6 种空态并排展示) - 10 环境状态栏 (全绿/警告/错误/加载/tooltip) 新建 prototype-modules-map.md: - 原型 ↔ 功能模块 对照 (8 大模块) - 原型 ↔ Swift 文件 对照 (16 个文件的改动量) - 按角色 (产品/开发/测试/运维) 反查用什么原型 - Sprint 7 验收表 (每原型 1-3 个验收点) - Sprint 7 改动量估算 (80% 实现 + 20% 延后) 文档联动: - docs/design/ui/README.md 推荐 prototype/ 为首选入口 - README.md 最新进展加 HTML 原型链接 验证: - check-links 断链 0 (594 个相对链接) - markdown-lint 仅 cjk-spacing nit 警告 - 用浏览器打开 prototype/index.html 可完整导览 10 张 --- README.md | 2 +- docs/design/ui/README.md | 8 +- .../ui/prototype/01-main-three-pane.html | 173 ++++++ docs/design/ui/prototype/02-setup-wizard.html | 276 ++++++++++ docs/design/ui/prototype/03-settings.html | 293 +++++++++++ .../prototype/04-slash-command-palette.html | 197 +++++++ .../prototype/05-artifact-panel-expanded.html | 179 +++++++ .../ui/prototype/06-provider-switcher.html | 193 +++++++ .../ui/prototype/07-search-overlay.html | 175 +++++++ .../08-conversation-context-menu.html | 214 ++++++++ docs/design/ui/prototype/09-empty-states.html | 190 +++++++ .../ui/prototype/10-env-status-bar.html | 178 +++++++ docs/design/ui/prototype/index.html | 141 +++++ .../ui/prototype/prototype-modules-map.md | 202 +++++++ docs/design/ui/prototype/styles.css | 491 ++++++++++++++++++ 15 files changed, 2908 insertions(+), 4 deletions(-) create mode 100644 docs/design/ui/prototype/01-main-three-pane.html create mode 100644 docs/design/ui/prototype/02-setup-wizard.html create mode 100644 docs/design/ui/prototype/03-settings.html create mode 100644 docs/design/ui/prototype/04-slash-command-palette.html create mode 100644 docs/design/ui/prototype/05-artifact-panel-expanded.html create mode 100644 docs/design/ui/prototype/06-provider-switcher.html create mode 100644 docs/design/ui/prototype/07-search-overlay.html create mode 100644 docs/design/ui/prototype/08-conversation-context-menu.html create mode 100644 docs/design/ui/prototype/09-empty-states.html create mode 100644 docs/design/ui/prototype/10-env-status-bar.html create mode 100644 docs/design/ui/prototype/index.html create mode 100644 docs/design/ui/prototype/prototype-modules-map.md create mode 100644 docs/design/ui/prototype/styles.css diff --git a/README.md b/README.md index 1020331..8cf8c2f 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ [![npx](https://img.shields.io/badge/npx-epcode-orange)](./tools/cli/) [![License](https://img.shields.io/badge/license-MIT-green)]() -> 📍 **最新进展**: Phase 1 已完成(v0.6.0 · 5 Sprint · 整体完成度 98%)。Phase 2 启动 · Sprint 6 ⑥ UI/UX 设计稿首发(10 wireframes + 5 interaction flows)。 +> 📍 **最新进展**: Phase 1 已完成(v0.6.0 · 5 Sprint · 整体完成度 98%)。Phase 2 启动 · Sprint 6 ⑥ UI/UX 设计稿完整首发(**[🎨 11 个 HTML 原型](./docs/design/ui/prototype/)** + 10 wireframes + 5 flows + 映射表)。 > > - 🧰 [统一 CLI · epcode](./tools/cli/) · 10 个子命令,零依赖 `npx epcode --help` > - 🌐 **[文档站 · epcode-ai.github.io/ep-code-ai](https://epcode-ai.github.io/ep-code-ai/)** ✅ 已上线 · 首页以 4 接入模式为一等公民 diff --git a/docs/design/ui/README.md b/docs/design/ui/README.md index 37516cf..387d967 100644 --- a/docs/design/ui/README.md +++ b/docs/design/ui/README.md @@ -6,9 +6,11 @@ > > **观看顺序**: > 1. 本文(原则 + 索引) -> 2. [wireframes/](./wireframes/) — 10 张静态页面线框图(ASCII) -> 3. [interaction-flows/](./interaction-flows/) — 5 个关键交互流程图(Mermaid) -> 4. [cross-platform-constraints.md](./cross-platform-constraints.md) — 三平台一致性约束 +> 2. **🎨 [prototype/](./prototype/) — 可交互 HTML 原型(打开 index.html,点击预览)** ⭐ 推荐先看这个 +> 3. [wireframes/](./wireframes/) — 10 张静态页面线框图(ASCII,含元素说明) +> 4. [interaction-flows/](./interaction-flows/) — 5 个关键交互流程图(Mermaid) +> 5. [cross-platform-constraints.md](./cross-platform-constraints.md) — 三平台一致性约束 +> 6. [prototype/prototype-modules-map.md](./prototype/prototype-modules-map.md) — 原型↔模块↔Swift 文件 映射 --- diff --git a/docs/design/ui/prototype/01-main-three-pane.html b/docs/design/ui/prototype/01-main-three-pane.html new file mode 100644 index 0000000..d2c4539 --- /dev/null +++ b/docs/design/ui/prototype/01-main-three-pane.html @@ -0,0 +1,173 @@ + + + + +01 · 主视图三栏 · EP Code AI + + + + +
+ 🎨 原型 01 / 10 · 主视图三栏 + ← 返回导航 · 下一页 → +
+ +
+ + +
+ EP Code AI + + + +
+ + +
+ + + + +
+
+
+
需求评审 - 离职流程 📌 ⋮
+
Anthropic Claude · opus · 156k / 200k tokens
+
+
+ +
+ +
+
+
11:32
+
+

帮我把这个 PRD 拆成 user story

+ 📎 prd-v1.2.md · 132 行 +
+
+
👤
+
+ + +
+
🤖
+
+
11:33 · 思考 12s · 输出 2.3k tokens
+
+

已读 prd-v1.2.md(132 行)。识别出 8 个用户场景,按 INVEST 原则拆成 8 条 user story:

+
    +
  1. 员工提交离职申请
  2. +
  3. HR 审核基本资料
  4. +
  5. 上级签字确认
  6. +
  7. 财务核算结算
  8. +
  9. IT 注销账号
  10. +
  11. 行政回收物品
  12. +
  13. 员工确认 off-boarding
  14. +
  15. 归档完成通知
  16. +
+

已生成 → user-stories.md(右侧已添加)

+
+
+
+ + +
+
+
11:36
+
+ [输入中...] +
+
+
👤
+
+
+ +
+
+ + + + ⌘↵ 发送 +
+ +
+
+ + +
+
📦 Artifacts (2)
+ +
+
+ ▾ prd-v1.2.md +
+
📄 132 行 · 2KB · 生成于 11:34
+
+ +
+
+ ▾ user-stories.md +
+
📋 8 条 · 4KB · 生成于 11:35
+
+ +
+ + +
+
+
+ + +
+ ✅ 环境正常 · Node v20 / Claude Code v1.2.3 + Anthropic · 240ms +
+
+ + + diff --git a/docs/design/ui/prototype/02-setup-wizard.html b/docs/design/ui/prototype/02-setup-wizard.html new file mode 100644 index 0000000..1193b4d --- /dev/null +++ b/docs/design/ui/prototype/02-setup-wizard.html @@ -0,0 +1,276 @@ + + + + +02 · 首次启动向导 · EP Code AI + + + + + +
+ 🎨 原型 02 / 10 · 首次启动向导 + ← 返回 · 上页 · 下页 → +
+ +
+
+ +
+ Setup · 第 2 步 / 共 4 步 + ✕ 跳过 +
+ +
+ 1. 欢迎 + 2. 环境检查 + 3. 供应商 + 4. 完成 +
+ + + + + +
+

🔍 正在检查运行环境...

+ +
+ Node.js + v20.10.0 + 满足 +
+
+ npm + v10.2.3 + OK +
+
+ git + v2.42.0 + OK +
+
+ ⚠️Claude Code + + 未安装 +
+
+ + 运行 npm install -g @anthropic-ai/claude-code +
+
+ Xcode CLT + + 未检测到 +
+
+ 终端运行: xcode-select --install + +
+ +
+ [▼ 详细日志] +
+
+ + + + + + + + +
+
+ + + + + diff --git a/docs/design/ui/prototype/03-settings.html b/docs/design/ui/prototype/03-settings.html new file mode 100644 index 0000000..aecb66c --- /dev/null +++ b/docs/design/ui/prototype/03-settings.html @@ -0,0 +1,293 @@ + + + + +03 · 设置页 · EP Code AI + + + + + +
+ 🎨 原型 03 / 10 · 设置页 + ← 返回 · 上页 · 下页 → +
+ +
+
+
+

设置

+ +
+ +
+
+ + + + +
+ +
+ +
+

General · 通用

+ +

外观

+
+
主题
浅色 / 深色 / 跟随系统
+ +
+
+
字号
+ +
+ +

会话

+
+
自动命名
让 AI 根据首条消息生成会话名
+
+
+
+
自动归档
30 天未活动自动归档
+
+
+ +

通知

+
+
AI 回复完成
+
+
+ +

数据

+
+
导出会话
导出全部为 .zip
+ +
+
+
清空本地数据
不可恢复
+ +
+
+ + +
+

Provider · 供应商管理

+ +
+ 已配置 2 个 + +
+ +
+
+ ● Anthropic 官方 (默认) + +
+
+ sk-ant-····xxxx · 余额 $42.18 +
+
+ 默认模型: claude-opus-4 +
+
✅ 连接 220ms
+
+ +
+
+ ○ AWS Bedrock + +
+
+ arn:aws:iam:... · us-east-1 +
+
⚠️ 上次失败(1h 前)
+
+
+ + +
+

Shortcuts · 快捷键

+ + + +

会话

+
新建会话⌘N
+
关闭当前会话⌘W
+
重命名当前会话⌘R
+ +

导航

+
全局搜索⌘K
+
设置⌘,
+
切换供应商⌘⇧P
+ +

输入

+
命令面板/固定
+
发送消息⌘↵
+ + +
+ + +
+

Experimental ⚗️

+

⚠️ 以下功能不稳定,启用前请知悉风险

+ +
+
AI 长上下文优化(256k → 1M)
beta · 可能更慢、更贵
+
+
+
+
多模态输入(图片/PDF)
alpha · 部分供应商不支持
+
+
+
+
命令面板模糊搜索
beta · 已开启
+
+
+
+
离线模式(本地模型)
概念验证 · 需 16GB+ 内存
+
+
+
+
+
+ + +
+
+ + + + + diff --git a/docs/design/ui/prototype/04-slash-command-palette.html b/docs/design/ui/prototype/04-slash-command-palette.html new file mode 100644 index 0000000..b3716a7 --- /dev/null +++ b/docs/design/ui/prototype/04-slash-command-palette.html @@ -0,0 +1,197 @@ + + + + +04 · 斜杠命令面板 · EP Code AI + + + + + +
+ 🎨 原型 04 / 10 · 斜杠命令面板 + ← 返回 · 上页 · 下页 → +
+ +
+ +
+
+
+ / + +
+ +
+
🔥 最近使用 (2)
+
+
+ /prd <file> +
PRD 结构校验 + 可测性打分
+
+
+
+
+ /adr index +
重建 ADR 索引
+
+
+
+ +
+
📋 全部命令 (10)
+
+
+ /init <mode> +
按接入模式起项目
+
+ +
+
+
+ /adopt --level=N +
模式 C 渐进启用
+
+
+
+
+ /migrate +
模式 B 反向生成 API 契约
+
+
+
+
+ /check +
跑全部校验
+
+
+
+
+ /metrics [--since] +
生成四场景度量看板
+
+
+
+
+ /linkage <type> +
跨场景联动
+
+
+
+
+ /incident <action> +
故障处理
+
+
+
+
+ /jira <action> +
Jira 集成
+
+
+
+ + +
+
+ +
+ 💡 提示: 选中 /init 后按 ↵ 会进入参数补齐界面(见 wireframe-04 第 3 段) +
+ + + diff --git a/docs/design/ui/prototype/05-artifact-panel-expanded.html b/docs/design/ui/prototype/05-artifact-panel-expanded.html new file mode 100644 index 0000000..44cb909 --- /dev/null +++ b/docs/design/ui/prototype/05-artifact-panel-expanded.html @@ -0,0 +1,179 @@ + + + + +05 · Artifact 全屏 · EP Code AI + + + + + +
+ 🎨 原型 05 / 10 · Artifact 全屏详情 + ← 返回 · 上页 · 下页 → +
+ +
+ +
+
+ ◀ 返回会话 +
+
prd-v1.2.md
+
132 行 · 2.1KB
+
+
+
+ + +
+
+ +
+ ◀ 在 2 个 Artifact 中切换 ▶ +
+ + 📜 历史 (3) +
+
+ +
+
+
🗂 大纲
+
▾ 1. 概述
+
1.1 背景
+
1.2 目标
+
▾ 2. 用户与场景
+
2.1 角色
+
2.2 主流程
+
▾ 3. 功能需求
+
3.1 功能清单
+
3.2 验收标准
+
▶ 4. 非功能需求
+
▶ 5. 数据规则
+
▶ 6. 交互设计
+
▶ 7. 风险
+
▶ 8. 变更历史
+ +
+ 📊 元数据
+ 生成: 11:34
+ 修订: 4 次
+ 来源: 会话「需求评审」 +
+
+ +
+1# PRD - 离职流程 v1.2 +2 +3## 1. 概述 +4 +5### 1.1 背景 +6公司目前离职流程涉及 5 个部门(HR / 财务 / IT / +7上级 / 行政),平均处理时长 7-10 工作日,员工反馈 +8断点多。 +9 +10### 1.2 目标 +11- 端到端处理时长 ≤ 3 工作日 +12- 关键步骤透明可追溯 +13- 员工 NPS ≥ 60 +14 +15## 2. 用户与场景 +16 +17... +
+
+ + + +
+ + + diff --git a/docs/design/ui/prototype/06-provider-switcher.html b/docs/design/ui/prototype/06-provider-switcher.html new file mode 100644 index 0000000..cdc4dfd --- /dev/null +++ b/docs/design/ui/prototype/06-provider-switcher.html @@ -0,0 +1,193 @@ + + + + +06 · 供应商切换 · EP Code AI + + + + + +
+ 🎨 原型 06 / 10 · 供应商切换浮层 + ← 返回 · 上页 · 下页 → +
+ + +
+
⚡ 切换供应商
+ +
+
当前会话
+
+ +
+ Anthropic 官方 +
opus · 156k / 200k tok 已用
+
+
+
+ +
+
可切换到
+
+ +
+ AWS Bedrock +
anthropic.claude-opus-4-v1
+
+ 220ms +
+
+ +
+ Google Vertex +
claude-opus-4@vertex
+
+ 未测 +
+
+ +
+ 第三方代理 +
claude-3-opus (proxy.example.com)
+
+ 失败 +
+
+ +
+ ⚠️ 切换会丢失当前会话的上下文 +
+ 新供应商无法看到历史消息 +
+ +
+ + +
+ + +
+ + +
+

⚠️ 切换确认

+

你正在切换供应商: Anthropic 官方 → AWS Bedrock

+

影响:

+ + +
+ 仍要继续? 输入 切换 确认 +
+ + +
+ + +
+
+ + + diff --git a/docs/design/ui/prototype/07-search-overlay.html b/docs/design/ui/prototype/07-search-overlay.html new file mode 100644 index 0000000..4877c1b --- /dev/null +++ b/docs/design/ui/prototype/07-search-overlay.html @@ -0,0 +1,175 @@ + + + + +07 · 全局搜索 · EP Code AI + + + + + +
+ 🎨 原型 07 / 10 · 全局搜索 ⌘K + ← 返回 · 上页 · 下页 → +
+ +
+ +
+ +
+ + + diff --git a/docs/design/ui/prototype/08-conversation-context-menu.html b/docs/design/ui/prototype/08-conversation-context-menu.html new file mode 100644 index 0000000..e068e14 --- /dev/null +++ b/docs/design/ui/prototype/08-conversation-context-menu.html @@ -0,0 +1,214 @@ + + + + +08 · 会话右键菜单 · EP Code AI + + + + + +
+ 🎨 原型 08 / 10 · 会话右键菜单 / 收藏 / 分组 / 多选 + ← 返回 · 上页 · 下页 → +
+ +
+ + +
+
+ + + + + +
+ + +
+
⭐ 加入收藏
+
📌 置顶
+
✏ 重命名⌘R
+
+
📂 移到分组
+
+
📋 复制链接
+
📤 导出会话
+
+
📊 查看统计token/时长
+
🔄 重置上下文
+
+
🗑 删除⌘⌫
+
+
+ + +
+

多选模式 (⌘ 点击)

+
+ +
+ +
+ 📦 已选 2 项 + +
+ +

新建分组浮窗

+
+

新建分组

+
+
名称
+ +
+
+
颜色
+
+ + + + + + +
+
+
+ + +
+
+ +

删除二次确认

+
+

⚠️ 删除会话

+

会话「需求评审 - 离职流程」和它的 6 条消息将被删除

+
+
Artifact 处理?
+ + +
+
+ + +
+
+
+ +
+ + + diff --git a/docs/design/ui/prototype/09-empty-states.html b/docs/design/ui/prototype/09-empty-states.html new file mode 100644 index 0000000..fd0ea57 --- /dev/null +++ b/docs/design/ui/prototype/09-empty-states.html @@ -0,0 +1,190 @@ + + + + +09 · 空状态合集 · EP Code AI + + + + + +
+ 🎨 原型 09 / 10 · 空状态合集 + ← 返回 · 上页 · 下页 → +
+ +
+

空状态合集

+

每个空态都要告诉用户"为什么没有 + 下一步做什么"

+
+ +
+ + +
+
9.1 首次使用 · 无任何会话
+
+
👋
+
开始你的第一个会话
+
Claude 会在这里和你协作
+ +
+ 或者: 📚 看 5 分钟教程 +
+
+
+ + +
+
9.2 有会话 · 没选中
+
+
📂
+
选择一个会话
+
点左侧列表,或使用快捷键:
+
+
⌘N 新建会话
+
⌘K 全局搜索
+
/ 命令面板
+
+
+
+ + +
+
9.3 新会话 · 没发消息
+
+
+
新会话
+
发一条消息开始,或试试:
+
+
💡 把 PRD 拆成 user story
+
💡 review 这段代码
+
💡 整理故障复盘
+
💡 生成度量周报
+
+
+
+ + +
+
9.4 搜索无结果
+
+
😶
+
没找到 "xxxyyyzzz"
+
+ 试试:
+ • 减少关键词长度
+ • 切换搜索类型
+ • 用模糊搜索: fuz/ +
+ +
+
+ + +
+
9.5 网络断开 / API 失败
+
+
📡
+
连接失败
+
历史消息正常显示,新消息暂存本地
+
+ ❌ 12:01 发送失败: 网络超时(10s) +
+
+ + + +
+
+
+ + +
+
9.7 供应商未配置
+
+
⚠️
+
未配置供应商
+
需要 AI 供应商才能发消息
+
+ + +
+
+ (仍可用 /check /adr /metrics 等本地命令) +
+
+
+ +
+ + + diff --git a/docs/design/ui/prototype/10-env-status-bar.html b/docs/design/ui/prototype/10-env-status-bar.html new file mode 100644 index 0000000..52f6fef --- /dev/null +++ b/docs/design/ui/prototype/10-env-status-bar.html @@ -0,0 +1,178 @@ + + + + +10 · 环境健康状态栏 · EP Code AI + + + + + +
+ 🎨 原型 10 / 10 · 环境健康状态栏 + ← 返回 · 上页 +
+ +
+ +

环境健康状态栏

+
永远在主视图最底部 24-32px。一眼能看出环境健康 + 网络状态。
+ + +
+
✅ 10.1 全绿状态
+
+ ✅ 环境正常 · Node v20 / Claude Code v1.2.3 + Anthropic · 240ms +
+
+ + +
+
⚠️ 10.2 警告状态(某项失败但可降级)
+
+ ⚠️ Claude Code 缺失 + Anthropic · 240ms +
+
+ + +
+
❌ 10.3 严重异常(关键操作禁用)
+
+ ❌ 环境损坏 + 断网 · +
+
+ + +
+
⏳ 10.4 加载中
+
+ ⏳ 检查环境中... + ⏳ 测连接中... +
+
+ + +
+
🔎 10.5 hover 环境区域 · 弹详情
+
+
+
环境检查
+
✅ Node.jsv20.10.0
+
✅ npmv10.2.3
+
✅ gitv2.42.0
+
✅ Claude Codev1.2.3
+
上次检查: 1 分钟前
+ +
+
+ ✅ 环境正常 · Node v20 / Claude Code v1.2.3 +
+
+
+ + +
+
📢 10.6 通知降级为应用内 banner(系统通知被禁时)
+ +
+ ❌ 环境损坏 + 断网 +
+
+ + +
+
🎨 配色对照
+
+
--color-success
#00C853
+
--color-warning
#FFB300
+
--color-error
#D50000
+
--color-text-muted
#6B7280
+
+
+ +
+ + + diff --git a/docs/design/ui/prototype/index.html b/docs/design/ui/prototype/index.html new file mode 100644 index 0000000..6284382 --- /dev/null +++ b/docs/design/ui/prototype/index.html @@ -0,0 +1,141 @@ + + + + +EP Code AI · Prototype + + + + + + + +

核心页面

+
+ +
01
+

主视图三栏

+

侧边栏会话列表 · 中栏聊天 · 右栏 Artifact

+
+ +
02
+

首次启动向导

+

4 步: Welcome → 环境检查 → 供应商 → 完成

+
+ +
03
+

设置页

+

4 个 tab: General / Provider / Shortcuts / Experimental

+
+ +
04
+

斜杠命令面板

+

/ 触发 · 模糊搜索 · 参数补齐

+
+ +
05
+

Artifact 全屏详情

+

大纲 · 版本对比 · 元数据

+
+
+ +

交互细节

+
+ +
06
+

供应商切换浮层

+

新会话切 / 会话内切 + 上下文重塑预警

+
+ +
07
+

全局搜索 ⌘K

+

会话 / Artifact / 命令 / 消息 · 分组结果

+
+ +
08
+

会话右键菜单

+

收藏 · 分组 · 多选 · 导出

+
+ +
09
+

空状态合集

+

首次 / 无选中 / 新会话 / 搜索无结果 / 断网

+
+ +
10
+

环境健康状态栏

+

全绿 / 警告 / 错误 · hover 详情

+
+
+ +

交互流程(Mermaid)

+

+ 5 个关键交互流程图见 interaction-flows/(在 GitHub / 文档站可直接预览 Mermaid)。 +

+ + + diff --git a/docs/design/ui/prototype/prototype-modules-map.md b/docs/design/ui/prototype/prototype-modules-map.md new file mode 100644 index 0000000..41e3f4b --- /dev/null +++ b/docs/design/ui/prototype/prototype-modules-map.md @@ -0,0 +1,202 @@ +# 原型 ↔ 模块 ↔ 功能 映射 + +> 每张原型图对应哪些**功能模块**,覆盖什么**用户任务**,Sprint 1-5 的哪些**工具**会被用到,以及当前 `app/ClaudeCodeHistory/` 哪些 **Swift 文件**负责实现。 +> +> 这份映射是 Sprint 7 macOS Beta 开发的**权威对照表**。 + +--- + +## 一、全景表 + +| # | 原型 | 核心模块 | 功能范围 | 对应 Swift 文件 | 复用 Sprint 1-5 能力 | +|---|------|---------|---------|---------------|---------------------| +| 01 | [主视图三栏](./01-main-three-pane.html) | 会话列表 + 聊天 + Artifact | 核心工作区 | `ContentView.swift`
`SidebarView.swift`
`ChatView.swift`
`ArtifactPanel.swift` | - | +| 02 | [首次启动向导](./02-setup-wizard.html) | 引导 + 环境检查 + 供应商配置 | 首次启动流程 | `SetupWizardView.swift`
`EnvironmentChecker.swift`
`ProviderManager.swift` | `platforms/*/scripts/check-environment.*` | +| 03 | [设置页](./03-settings.html) | 偏好设置 + 供应商管理 + 快捷键 | 配置中心 | `SettingsView.swift`
`AppSettings.swift`
`ProviderManager.swift` | - | +| 04 | [斜杠命令面板](./04-slash-command-palette.html) | 命令调用 + 参数补齐 | 快速操作 | (新增组件) | `tools/cli/commands/*` 全部 10 个 | +| 05 | [Artifact 全屏](./05-artifact-panel-expanded.html) | 文档/代码详情 + 版本对比 + 导出 | 产出管理 | `ArtifactPanel.swift`
`ArtifactDetector.swift` | - | +| 06 | [供应商切换](./06-provider-switcher.html) | 多供应商 + 上下文处理 | 会话中切换 | `ProviderManager.swift` | - | +| 07 | [全局搜索](./07-search-overlay.html) | 跨类型搜索 | 快速查找 | (新增组件)
`ConversationStore.swift` 需加索引 | - | +| 08 | [会话右键菜单](./08-conversation-context-menu.html) | 收藏 / 分组 / 多选 / 删除 | 会话管理 | `SidebarView.swift`
`FavoritesManager.swift`
`ConversationStore.swift` | - | +| 09 | [空状态合集](./09-empty-states.html) | 引导 + 提示 + 错误恢复 | 兜底与教育 | 分散在上述各组件 | - | +| 10 | [环境状态栏](./10-env-status-bar.html) | 持久化健康提示 | 全局状态监控 | `EHUBInfoBar.swift` (需扩展)
`EnvironmentChecker.swift` | `platforms/*/scripts/check-environment.*` | + +--- + +## 二、按功能模块逆向汇总 + +### 2.1 会话管理模块 + +- **涵盖原型**: 01 主视图 · 08 右键菜单 · 09 空状态 +- **关键用户任务**: + - 新建会话(⌘N / 空状态按钮 / `+ 新会话`) + - 切换会话(侧边栏点击 / ⌘K 搜索) + - 收藏会话(右键菜单 / 拖拽) + - 分组管理(右键菜单 → 移到分组) + - 删除 / 归档(右键菜单 + 二次确认) + - 多选批量操作(⌘ 点击 + 多选底栏) +- **数据存储**: 本地 SQLite(`ConversationStore.swift`)+ 搜索索引(FTS5) +- **Sprint 1-5 复用**: 无直接复用,但输出可以被 `tools/metrics/` 统计 + +### 2.2 聊天与 AI 交互模块 + +- **涵盖原型**: 01 主视图 · 09 空状态 +- **关键用户任务**: + - 发送消息(⌘↵) + - 附件上传(📎 按钮) + - 模型切换(⚡ 按钮,会话内) + - 接收流式回复(AI 消息逐字显示) + - 取消生成(停止按钮,生成中可见) +- **依赖**: `ClaudeProcessManager.swift`(启停 Claude Code 进程) +- **Sprint 1-5 复用**: 消息内容可发送到 `epcode prd` / `epcode jira sync` 做后处理 + +### 2.3 Artifact 管理模块 + +- **涵盖原型**: 01 主视图(右栏)· 05 全屏详情 +- **关键用户任务**: + - 自动识别代码 / Markdown / JSON + - 切换 Artifact(◀▶ 按钮或点击卡片) + - 大纲导航(标题树跳转) + - 版本对比(v2 ↔ v3 diff) + - 导出(.md / .pdf / .html / .zip) + - 跳转到生成时对话 +- **检测策略**: `ArtifactDetector.swift` 按长度 + 结构门槛 +- **Sprint 1-5 复用**: 导出的 Artifact 可被 `epcode linkage` 脚本消费(如测试报告 → 发布计划) + +### 2.4 环境与供应商模块 + +- **涵盖原型**: 02 首次向导 · 03 设置 Provider tab · 06 供应商切换 · 09 供应商未配置空态 · 10 环境状态栏 +- **关键用户任务**: + - 首次环境检查 + 一键修复(SetupWizard 步骤 2) + - 配置多供应商(Anthropic / Bedrock / Vertex / 代理) + - 测试连接 + - 会话内切换供应商(含上下文重塑警告) + - 持久化健康监控(底部状态栏) +- **依赖**: `EnvironmentChecker.swift` + `ProviderManager.swift` +- **Sprint 1-5 复用**: `platforms/macos/scripts/check-environment.sh` 的检查逻辑被 GUI 封装 + +### 2.5 命令系统模块 + +- **涵盖原型**: 04 斜杠命令面板 +- **关键用户任务**: + - `/` 快速调用 10 个 CLI 子命令 + - 模糊搜索命令 + - 参数补齐(表单式) + - 最近使用 / 收藏 +- **实现**: 新增 `SlashCommandPalette.swift` 组件,扫描 `tools/cli/commands/*.js` 的 JSDoc 建命令注册表 +- **Sprint 1-5 复用**: **全部 10 个 `epcode` 子命令** 在 GUI 里完全可用: + - `/init ` · `/adopt` · `/migrate` · `/check` · `/prd` · `/adr` · `/metrics` · `/incident` · `/linkage` · `/jira` + +### 2.6 搜索模块 + +- **涵盖原型**: 07 全局搜索 ⌘K +- **关键用户任务**: + - 跨会话 / Artifact / 命令 / 消息 搜索 + - 最近访问快速进入 + - 分组展示 + 筛选 +- **实现**: SQLite FTS5 本地索引 + 新增 `SearchOverlay.swift` + +### 2.7 设置与偏好模块 + +- **涵盖原型**: 03 设置页 +- **关键用户任务**: + - 外观(主题 / 字号 / 字体) + - 会话偏好(自动命名 / 归档 / 保留) + - 通知开关 + - 快捷键自定义 + - 实验性功能开关 + - 数据导出 / 清空 +- **实现**: `SettingsView.swift` 需重构为 4 tab 布局 + `AppSettings.swift` 扩展 schema + +### 2.8 状态与错误处理模块 + +- **涵盖原型**: 09 所有空态 · 10 状态栏 +- **关键用户任务**: + - 环境健康监控 + - 网络 / API 异常兜底 + - 错误重试 / 恢复 + - 用户引导(新用户 / 搜索无结果等) + +--- + +## 三、按用户角色视角 + +### 3.1 新用户首次打开应用 + +主线: `02 向导` → `09.1 首次空态` → `01 主视图 + 09.3 新会话空态` → 发出第一条消息 + +### 3.2 老用户日常使用 + +主线: `01 主视图` ↔ `07 ⌘K 搜索` ↔ `04 / 命令` ↔ `05 Artifact 详情` + +### 3.3 产品经理 + +高频: `04 /prd 命令` · `01 主视图(写 PRD)` · `05 Artifact 全屏(改 PRD)` + +### 3.4 开发 + +高频: `01 主视图(代码讨论)` · `04 /adr /check 命令` · `05 Artifact(看生成代码)` + +### 3.5 测试 + +高频: `04 /prd /linkage regression /linkage release-plan` · `05 Artifact(看测试报告)` + +### 3.6 运维 / SRE + +高频: `04 /incident /metrics /linkage release-plan` · `03 设置(Runbook 相关偏好)` · `10 状态栏` + +--- + +## 四、Sprint 7 实现影响估算 + +| Swift 文件 | 现状 | 设计稿要求 | 改动量 | Sprint 7 是否处理 | +|----------|------|----------|--------|-----------------| +| `ContentView.swift` | 有三栏雏形 | 顶栏 + 状态栏 + 主 | 中 | ✅ | +| `SidebarView.swift` | 有列表 | 分组 + 收藏 + 右键菜单 + 多选 | 大 | ✅ | +| `ChatView.swift` | 有基础 | 附件 + 模型徽章 + token 计数 + 流式 | 中 | ✅ | +| `ArtifactPanel.swift` | 有列表 | 全屏详情 + 大纲 + 版本对比 | 中 | ⚠️ 只做基础版,版本对比延后 | +| `ArtifactDetector.swift` | 有雏形 | 支持 Markdown 文档 + 流式增量 | 中 | ✅ | +| `SetupWizardView.swift` | 有步骤 1-2 | 加步骤 3 供应商 + 步骤 4 完成 | 中 | ✅ | +| `EnvironmentChecker.swift` | 检测 | 加一键修复入口 | 中 | ✅ | +| `ProviderManager.swift` | 单供应商 | 多供应商 + 切换浮层 | 大 | ✅ | +| `SettingsView.swift` | 单页 | 4 tab + 表单 | 大 | ✅ | +| `AppSettings.swift` | 基础 | 扩展 schema(快捷键/实验性等) | 中 | ✅ | +| `EHUBInfoBar.swift` | 简单 | 扩展为完整状态栏 + tooltip | 中 | ✅ | +| `ConversationStore.swift` | 存储 | 加 FTS5 搜索索引 + 分组表 | 中 | ✅ | +| `FavoritesManager.swift` | 基础 | 对接分组 | 小 | ✅ | +| (新增) `SlashCommandPalette.swift` | - | 命令面板 + 参数表单 | 大 | ✅ | +| (新增) `SearchOverlay.swift` | - | ⌘K 搜索 | 大 | 🟡 基础版,无筛选 | +| (新增) `CommandRegistry.swift` | - | 扫描 tools/cli/commands/ 建注册表 | 中 | ✅ | + +**总体估算**: +- macOS Beta(Sprint 7): 实现约 **80%** 设计稿功能,版本对比和搜索筛选延后到 v0.7 +- Linux/Windows 实现(Sprint 8): 基于 macOS 移植 + 跨平台栈决策 + +--- + +## 五、快速验收表 + +Sprint 7 验收时,每个原型对应 1-3 个验收用例: + +| # | 原型 | 关键验收点 | +|---|------|----------| +| 01 | 主视图 | ✅ 发送消息能收到回复 · ✅ Artifact 自动出现在右栏 · ✅ 状态栏显示环境 | +| 02 | 向导 | ✅ 4 步可以完整过 · ✅ 跳过后能从设置重开 · ✅ 环境检查准确 | +| 03 | 设置 | ✅ 4 tab 切换正常 · ✅ 改主题立即生效 · ✅ 快捷键冲突检测 | +| 04 | 命令面板 | ✅ `/` 触发 · ✅ 10 个 CLI 子命令全部能跑 · ✅ 参数表单正确 | +| 05 | Artifact 全屏 | ✅ 大纲跳转正确 · ✅ 导出 .md 可用(.pdf 可延后) · ⚠️ 版本对比可延后 | +| 06 | 切换供应商 | ✅ 新会话切换无 bug · ✅ 会话内切换有警告 · ✅ 上下文重塑可用 | +| 07 | 全局搜索 | ✅ ⌘K 弹出 · ✅ 能搜到会话 · ⚠️ 筛选模式可延后 | +| 08 | 右键菜单 | ✅ 收藏 / 分组 / 删除 正常 · ⚠️ 多选可延后 | +| 09 | 空状态 | ✅ 每种空态都有 CTA · ✅ 错误状态有恢复按钮 | +| 10 | 状态栏 | ✅ 三色态切换正确 · ✅ hover 弹详情 · ✅ 修复按钮可用 | + +--- + +## 六、文档联动 + +- 方法论: [docs/chapters/](../../../chapters/)(不受本设计稿影响) +- 线框详情: [docs/design/ui/wireframes/](../wireframes/)(本映射的源头) +- 交互流程: [docs/design/ui/interaction-flows/](../interaction-flows/)(补充静态页面看不到的状态变化) +- 跨平台约束: [docs/design/ui/cross-platform-constraints.md](../cross-platform-constraints.md) +- 发布流程: [RELEASE_PROCESS.md](../../../../RELEASE_PROCESS.md)(macOS Beta 走此流程) diff --git a/docs/design/ui/prototype/styles.css b/docs/design/ui/prototype/styles.css new file mode 100644 index 0000000..900a406 --- /dev/null +++ b/docs/design/ui/prototype/styles.css @@ -0,0 +1,491 @@ +/* EP Code AI · Prototype Design Tokens + * + * 跨 10 个页面共享的样式。改这里一处,所有页面同步更新。 + */ + +:root { + /* Primary palette */ + --color-primary: #2962ff; + --color-primary-dark: #0039cb; + --color-primary-light: #82b1ff; + --color-primary-lightest: #eef3ff; + + /* Semantic */ + --color-success: #00c853; + --color-warning: #ffb300; + --color-error: #d50000; + + /* Neutrals */ + --color-text: #1a1a1a; + --color-text-muted: #6b7280; + --color-border: #e5e7eb; + --color-bg: #ffffff; + --color-bg-alt: #f9fafb; + --color-bg-hover: #f3f4f6; + + /* Dark theme (auto when prefers-color-scheme: dark) */ + --color-sidebar-bg: #fafafa; + + /* Typography */ + --font-ui: -apple-system, BlinkMacSystemFont, "Segoe UI", Cantarell, sans-serif; + --font-mono: "JetBrains Mono", Consolas, Menlo, monospace; + --fs-xs: 11px; + --fs-sm: 12px; + --fs-md: 13px; + --fs-lg: 15px; + --fs-xl: 18px; + --fs-2xl: 24px; + --fs-3xl: 32px; + + /* Spacing (4px grid) */ + --sp-1: 4px; + --sp-2: 8px; + --sp-3: 12px; + --sp-4: 16px; + --sp-5: 20px; + --sp-6: 24px; + --sp-8: 32px; + --sp-10: 40px; + --sp-12: 48px; + + /* Border radius */ + --radius-sm: 4px; + --radius-md: 6px; + --radius-lg: 10px; + --radius-xl: 16px; + + /* Shadow */ + --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05); + --shadow-md: 0 4px 12px rgba(0, 0, 0, 0.08); + --shadow-lg: 0 12px 24px rgba(0, 0, 0, 0.12); + + /* Layout */ + --sidebar-width: 240px; + --artifact-width: 320px; + --statusbar-height: 24px; + --topbar-height: 40px; +} + +@media (prefers-color-scheme: dark) { + :root { + --color-text: #e5e7eb; + --color-text-muted: #9ca3af; + --color-border: #374151; + --color-bg: #1a1a1a; + --color-bg-alt: #0f0f0f; + --color-bg-hover: #27272a; + --color-sidebar-bg: #0f0f0f; + --color-primary-lightest: #1a1a2e; + } +} + +/* Reset */ +* { margin: 0; padding: 0; box-sizing: border-box; } + +html, body { + height: 100%; + font-family: var(--font-ui); + font-size: var(--fs-md); + color: var(--color-text); + background: var(--color-bg); + -webkit-font-smoothing: antialiased; +} + +code, .code, pre { + font-family: var(--font-mono); + font-size: var(--fs-sm); +} + +a { color: var(--color-primary); text-decoration: none; } +a:hover { text-decoration: underline; } + +/* ============ Layout · 主视图三栏 ============ */ + +.app { + display: grid; + grid-template-rows: var(--topbar-height) 1fr var(--statusbar-height); + height: 100vh; + background: var(--color-bg); +} + +.topbar { + display: flex; + align-items: center; + gap: var(--sp-3); + padding: 0 var(--sp-4); + border-bottom: 1px solid var(--color-border); + background: var(--color-bg-alt); + font-weight: 600; +} +.topbar .brand { font-size: var(--fs-lg); } +.topbar .spacer { flex: 1; } + +.main { + display: grid; + grid-template-columns: var(--sidebar-width) 1fr var(--artifact-width); + height: 100%; + overflow: hidden; +} +.main.no-artifact { + grid-template-columns: var(--sidebar-width) 1fr; +} + +.sidebar { + background: var(--color-sidebar-bg); + border-right: 1px solid var(--color-border); + overflow-y: auto; + display: flex; + flex-direction: column; +} + +.chat { + display: flex; + flex-direction: column; + overflow: hidden; + background: var(--color-bg); +} + +.artifact-panel { + border-left: 1px solid var(--color-border); + background: var(--color-bg-alt); + overflow-y: auto; + padding: var(--sp-4); +} + +.statusbar { + display: flex; + align-items: center; + justify-content: space-between; + padding: 0 var(--sp-4); + border-top: 1px solid var(--color-border); + background: var(--color-bg-alt); + font-size: var(--fs-xs); + color: var(--color-text-muted); +} +.statusbar.ok { color: var(--color-success); } +.statusbar.warn { color: var(--color-warning); } +.statusbar.error { color: var(--color-error); } + +/* ============ Sidebar items ============ */ + +.sidebar-search { + padding: var(--sp-3); + border-bottom: 1px solid var(--color-border); +} +.sidebar-search input { + width: 100%; + padding: var(--sp-2) var(--sp-3); + border: 1px solid var(--color-border); + border-radius: var(--radius-md); + background: var(--color-bg); + font-size: var(--fs-md); + color: var(--color-text); +} + +.sidebar-group { + padding: var(--sp-2) 0; +} +.sidebar-group-title { + font-size: var(--fs-xs); + color: var(--color-text-muted); + padding: var(--sp-1) var(--sp-4); + text-transform: uppercase; + letter-spacing: 0.5px; +} +.conversation { + display: flex; + align-items: center; + gap: var(--sp-2); + padding: var(--sp-2) var(--sp-4); + cursor: pointer; + font-size: var(--fs-md); + border-left: 3px solid transparent; +} +.conversation:hover { background: var(--color-bg-hover); } +.conversation.active { + background: var(--color-primary-lightest); + border-left-color: var(--color-primary); + font-weight: 500; +} +.conversation-dot { + width: 6px; height: 6px; border-radius: 50%; + background: var(--color-text-muted); + flex-shrink: 0; +} +.conversation.active .conversation-dot { background: var(--color-primary); } + +.sidebar-footer { + margin-top: auto; + padding: var(--sp-3); + border-top: 1px solid var(--color-border); +} + +/* ============ Chat ============ */ + +.chat-header { + padding: var(--sp-3) var(--sp-4); + border-bottom: 1px solid var(--color-border); + display: flex; + align-items: center; + gap: var(--sp-3); +} +.chat-title { + font-size: var(--fs-lg); + font-weight: 600; +} +.chat-meta { + font-size: var(--fs-xs); + color: var(--color-text-muted); +} +.chat-body { + flex: 1; + overflow-y: auto; + padding: var(--sp-6); + display: flex; + flex-direction: column; + gap: var(--sp-6); +} + +.message { + display: flex; + gap: var(--sp-3); + max-width: 720px; +} +.message-avatar { + width: 28px; height: 28px; + border-radius: 50%; + display: flex; align-items: center; justify-content: center; + background: var(--color-primary-lightest); + font-size: var(--fs-lg); + flex-shrink: 0; +} +.message-body { flex: 1; } +.message-time { + font-size: var(--fs-xs); + color: var(--color-text-muted); + margin-bottom: var(--sp-1); +} +.message-content { line-height: 1.6; } +.message-content p { margin-bottom: var(--sp-2); } +.message-content pre { + background: var(--color-bg-alt); + padding: var(--sp-3); + border-radius: var(--radius-md); + overflow-x: auto; + border: 1px solid var(--color-border); +} +.attachment { + display: inline-flex; + align-items: center; + gap: var(--sp-2); + padding: var(--sp-1) var(--sp-3); + background: var(--color-bg-hover); + border-radius: var(--radius-md); + font-size: var(--fs-sm); + margin-top: var(--sp-2); +} + +.chat-input { + padding: var(--sp-3) var(--sp-4); + border-top: 1px solid var(--color-border); + display: flex; + flex-direction: column; + gap: var(--sp-2); +} +.chat-input-toolbar { + display: flex; + gap: var(--sp-3); + font-size: var(--fs-sm); + color: var(--color-text-muted); +} +.chat-input-toolbar .kbd { + margin-left: auto; +} +.chat-input textarea { + width: 100%; + min-height: 44px; + padding: var(--sp-2) var(--sp-3); + border: 1px solid var(--color-border); + border-radius: var(--radius-md); + font-family: var(--font-ui); + font-size: var(--fs-md); + resize: vertical; + background: var(--color-bg); + color: var(--color-text); +} + +.kbd { + padding: 2px 6px; + background: var(--color-bg-hover); + border: 1px solid var(--color-border); + border-radius: var(--radius-sm); + font-family: var(--font-mono); + font-size: var(--fs-xs); + color: var(--color-text-muted); +} + +/* ============ Buttons ============ */ + +.btn { + display: inline-flex; + align-items: center; + justify-content: center; + gap: var(--sp-2); + padding: var(--sp-2) var(--sp-4); + border-radius: var(--radius-md); + border: 1px solid var(--color-border); + background: var(--color-bg); + font-size: var(--fs-md); + font-weight: 500; + cursor: pointer; + color: var(--color-text); + font-family: inherit; +} +.btn:hover { background: var(--color-bg-hover); } +.btn.primary { + background: var(--color-primary); + color: white; + border-color: var(--color-primary); +} +.btn.primary:hover { background: var(--color-primary-dark); } +.btn.ghost { border: none; } +.btn.sm { padding: var(--sp-1) var(--sp-3); font-size: var(--fs-sm); } +.btn.lg { padding: var(--sp-3) var(--sp-6); font-size: var(--fs-lg); } +.btn:disabled { + opacity: 0.4; + cursor: not-allowed; +} + +/* ============ Artifacts ============ */ + +.artifact-title { + font-size: var(--fs-lg); + font-weight: 600; + margin-bottom: var(--sp-4); +} +.artifact-card { + padding: var(--sp-3); + margin-bottom: var(--sp-3); + border: 1px solid var(--color-border); + border-radius: var(--radius-md); + background: var(--color-bg); + cursor: pointer; +} +.artifact-card:hover { border-color: var(--color-primary); } +.artifact-card-title { + font-weight: 600; + margin-bottom: var(--sp-1); + display: flex; + align-items: center; + gap: var(--sp-2); +} +.artifact-card-meta { + font-size: var(--fs-xs); + color: var(--color-text-muted); +} + +/* ============ Modal / Overlay ============ */ + +.overlay { + position: fixed; + inset: 0; + background: rgba(0, 0, 0, 0.4); + display: flex; + align-items: center; + justify-content: center; + z-index: 100; +} + +.modal { + background: var(--color-bg); + border-radius: var(--radius-lg); + box-shadow: var(--shadow-lg); + width: 600px; + max-width: 90vw; + max-height: 85vh; + overflow: hidden; + display: flex; + flex-direction: column; +} +.modal-header { + padding: var(--sp-4); + border-bottom: 1px solid var(--color-border); + display: flex; + align-items: center; + justify-content: space-between; +} +.modal-title { font-size: var(--fs-lg); font-weight: 600; } +.modal-body { padding: var(--sp-5); overflow-y: auto; flex: 1; } +.modal-footer { + padding: var(--sp-4); + border-top: 1px solid var(--color-border); + display: flex; + justify-content: flex-end; + gap: var(--sp-3); +} + +/* ============ Form fields ============ */ + +.field { margin-bottom: var(--sp-4); } +.field-label { + display: block; + font-size: var(--fs-sm); + font-weight: 500; + margin-bottom: var(--sp-2); +} +.field-hint { + font-size: var(--fs-xs); + color: var(--color-text-muted); + margin-top: var(--sp-1); +} +.field input, .field select, .field textarea { + width: 100%; + padding: var(--sp-2) var(--sp-3); + border: 1px solid var(--color-border); + border-radius: var(--radius-md); + font-size: var(--fs-md); + font-family: inherit; + background: var(--color-bg); + color: var(--color-text); +} + +/* ============ Badges / Status ============ */ + +.badge { + display: inline-flex; + align-items: center; + gap: 4px; + padding: 2px 8px; + border-radius: var(--radius-sm); + font-size: var(--fs-xs); + font-weight: 500; +} +.badge.ok { background: #e8f5e9; color: var(--color-success); } +.badge.warn { background: #fff8e1; color: var(--color-warning); } +.badge.error { background: #ffebee; color: var(--color-error); } + +.dot { + display: inline-block; + width: 8px; height: 8px; border-radius: 50%; + background: var(--color-success); + margin-right: var(--sp-1); +} +.dot.warn { background: var(--color-warning); } +.dot.error { background: var(--color-error); } + +/* ============ Navigation banner ============ */ + +.proto-banner { + position: fixed; + top: 0; left: 0; right: 0; + padding: var(--sp-2) var(--sp-4); + background: var(--color-primary); + color: white; + font-size: var(--fs-xs); + display: flex; + align-items: center; + justify-content: space-between; + z-index: 200; +} +.proto-banner a { color: white; text-decoration: underline; } +body.with-banner .app { padding-top: 32px; }