diff --git a/.factory/mcp.json b/.factory/mcp.json index 29585572e..b17d05dcf 100644 --- a/.factory/mcp.json +++ b/.factory/mcp.json @@ -3,6 +3,10 @@ "shadcn": { "command": "npx", "args": ["-y", "shadcn@latest", "mcp"] + }, + "workflow": { + "command": "pnpm", + "args": ["agent:mcp"] } } } diff --git a/AGENTS.md b/AGENTS.md index 99b141d6b..bb4c4abb7 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,152 +1,113 @@ -# AI 开发元原则 +# AI 开发元原则 (AI-Native Workflow 3.0) -1. 本文档定义 AI 开发的**元意识** — 如何思考、如何工作的方法论。 -2. 项目具体知识(技术栈、API、业务概念)请查阅 `docs/white-book/`。 +1. **Schema-first**: 一切服务与数据结构设计,始于 Schema (Zod) 定义。 +2. **Issue-Driven**: 每一个改动都对应一个 Issue,每一个执行都对应一个 PR。 +3. **Full-Lifecycle**: 从 `investigate` 到 `document`,全流程自动化。 +项目具体知识(技术栈、API、业务概念)请查阅 `docs/white-book/`。 --- -## 元意识(自检与自更新) +## pnpm agent 工具体系 -AI 必须具备以下自检与自更新能力,并在工作中显式执行: +我们不再手动执行 git 命令,而是通过 `pnpm agent` 驱动全生命周期。 -1. **进度自检**:随时能说明当前在做什么、卡点在哪里、下一步是什么。 -2. **知识自更新**:用户提供新知识或纠正时,先更新 `docs/white-book/`,再继续任务。 -3. **项目自管理**:用 Roadmap/Issue/Worktree/PR 管理工作流,保证可追踪、可回滚。 -4. **最佳实践自维护**:发现可复用规律,及时更新白皮书或最佳实践提示。 +### 核心工作流 ---- - -## pnpm agent 工具(AI 启动入口) - -**每次新上下文启动必须执行:** - -```bash -pnpm agent readme -``` - -`pnpm agent readme` 是白皮书导览入口,白皮书具体路径与阅读建议以该命令输出为准。 -最佳实践文件位于 `docs/white-book/00-必读/best-practices.md`,由 `pnpm agent practice` 维护。 +| 阶段 | 命令 | 作用 | +|------|------|------| +| **1. 调查** | `pnpm agent investigate analyze --type --topic "..."` | 分析需求,阅读白皮书,生成 RFC | +| **2. 启动** | `pnpm agent task start --type --title "..."` | 创建 Issue/Branch/Worktree/Draft PR | +| **3. 同步** | `pnpm agent task sync "..."` | 将本地进度同步到 GitHub Issue | +| **4. 检查** | `pnpm agent review verify` | 运行 Lint/Typecheck/Test | +| **5. 提交** | `pnpm agent task submit` | 推送代码,标记 PR 为 Ready | +| **6. 文档** | `pnpm agent document sync` | 检查变更,推荐白皮书更新 | -常用命令: +### 辅助工具 ```bash -pnpm agent readme # 启动入口(索引 + 知识地图 + 最佳实践) -pnpm agent --help # 查看帮助 -pnpm agent roadmap current # 当前 Roadmap -pnpm agent toc # 白皮书目录 -pnpm agent chapter <路径> # 读取白皮书章节 -pnpm agent practice list # 最佳实践列表 -pnpm agent practice add "<内容>" -pnpm agent practice remove <序号|内容> -pnpm agent practice update <序号> "<内容>" -pnpm agent claim # 领取任务 -pnpm agent worktree create --branch --base main -pnpm agent worktree list -pnpm agent worktree delete +pnpm agent readme # 白皮书导览 +pnpm agent search "keyword" # 搜索白皮书 +pnpm agent chapter # 阅读章节 +pnpm agent roadmap current # 查看当前任务 ``` --- -## 角色化工作流程(多场景) +## 角色化工作流程 -### 1) 新上下文启动(必做) +### 1) 需求澄清 (Investigate) -```bash -pnpm agent readme -pnpm agent roadmap current -pnpm agent toc -pnpm agent chapter 00-必读 -``` - -完成后自检: -- 当前任务目标是否清晰? -- 是否需要读更多白皮书章节? -- 是否需要查看 openspec 规范? - -### 2) 继续未完成任务(接手/续写) +**场景**: 收到模糊需求,或需要进行架构设计。 ```bash -pnpm agent readme -pnpm agent roadmap current -pnpm agent worktree list -# 进入已有 worktree,检查 git status / 进度 -``` - -自检:确认已有 worktree 的分支、PR 状态、CI 状态是否需要处理。 +# 1. 分析需求 & 查阅白皮书 +pnpm agent investigate analyze --type service --topic "New Auth Service" -### 3) 需求澄清 / 方案设计(产品/架构角色) - -```bash -pnpm agent readme -pnpm agent toc -pnpm agent chapter <需求相关章节> +# 2. (可选) 搜索更多资料 +pnpm agent search "authentication" ``` -- 若涉及新能力/架构变更,先查看 `openspec/AGENTS.md` 并走提案流程。 -- 记录结论到白皮书或 openspec 变更中。 +### 2) 任务开发 (Task Loop) -### 4) 实现开发(工程师角色) +**场景**: 开始编码实现。 ```bash -pnpm agent readme -pnpm agent claim -pnpm agent worktree create issue- --branch feat/issue- --base main -cd .git-worktree/issue- -pnpm agent chapter <路径> -# 开发 + 测试 -pnpm dev -pnpm test -pnpm typecheck +# 1. 启动任务 (自动环境准备) +pnpm agent task start --type service --title "Implement Auth Service" +# -> 输出: cd .git-worktree/issue-123 + +# 2. 进入开发环境 +cd .git-worktree/issue-123 + +# 3. 开发循环 +# ... coding ... +pnpm agent task sync "- [x] Schema defined" +# ... coding ... +pnpm agent review verify ``` -```bash -# 提交与 PR - git add -A - git commit -m "feat/fix: 描述" - git push -u origin - gh pr create --title "标题" --body "Closes #" --base main -``` +### 3) 完工交付 (Submit) -### 5) Bug 修复 / 回归(维护者角色) +**场景**: 代码完成,准备 Review。 ```bash -pnpm agent readme -pnpm agent roadmap current -pnpm agent worktree create fix- --branch fix/ --base main -``` - -- 先复现并记录原因。 -- 必要时更新白皮书,说明修复背景与影响。 +# 1. 最后一次检查 +pnpm agent review checklist --type service +pnpm agent review verify -### 6) 评审 / 质量保证(Reviewer 角色) - -```bash -pnpm agent readme -pnpm agent chapter <测试/规范相关章节> +# 2. 提交 & 触发 CI +pnpm agent task submit ``` -- 关注回归风险、测试覆盖、接口兼容性。 -- 有问题先写明事实,再给出修复建议。 +### 4) 维护者 (Reviewer/Integrator) -### 7) 合并收尾(集成角色) +**场景**: Review 代码或合并 PR。 ```bash -gh pr checks --watch +# 1. 检查文档一致性 +pnpm agent document sync + +# 2. 合并 PR (使用 gh cli) gh pr merge --squash --delete-branch -pnpm agent worktree delete ``` -合并门禁(必须执行): -- **在合并之前必须询问用户**,并明确告知当前工作目录(worktree 路径)。 -- 用户 review 确认后才允许执行合并。 +--- + +## 任务类型 (Type) + +- `ui`: 组件库、UI 交互 (自动关联 Storybook 检查) +- `service`: 业务逻辑、API (自动关联 Unit Test 检查) +- `page`: 页面路由、导航 (自动关联 Router 配置) +- `hybrid`: 混合开发 (通用模板) --- ## 重要提醒 -- 白皮书是唯一权威来源:用户补充/纠正知识,必须先更新 `docs/white-book/`。 -- 不允许在主目录直接开发,所有代码必须在 `.git-worktree/` 中进行。 +- **白皮书是唯一权威**: 开发前必读相关章节 (`investigate` 会自动推荐)。 +- **严禁主目录开发**: 必须使用 `task start` 创建的 Worktree。 +- **Schema-first**: 服务开发必须先定义 `types.ts`。 diff --git a/CHAT.md b/CHAT.md index 78f283282..9ea4ac752 100644 --- a/CHAT.md +++ b/CHAT.md @@ -1163,5 +1163,74 @@ worktree new task: --- 将 WalletTab 中的下半部分:关于某个地址某个网络中的资产列表和交易列表,封装成一套组件。我要在 stories 中看到这套组件,并绑定真实的 chainProvider。 -提供两个 stories 测试,一个是 `bfmeta:bCfAynSAKhzgKLi3BXyuh5k22GctLR72j` ;一个是 `eth:bCfAynSAKhzgKLi3BXyuh5k22GctLR72j` +提供两个 stories 测试,一个是 `biochain-bfmeta:b9gB9NzHKWsDKGYFCaNva6xRnxPwFfGcfx` ;一个是 `eth-eth:0x75a6F48BF634868b2980c97CcEf467A127597e08` 我要确保能看到真实的数据。 + +--- + +使用 walletapi 继续完善我们的底层 api 的支持,比如实现 tronwallet-v1/ethwallet-v1/btcwallet-v1,并用它来作为我们的 fallback方案。 +参考:`/Users/kzf/Dev/bioforestChain/legacy-apps/libs/wallet-base/services/wallet/bitcoin`/`/Users/kzf/Dev/bioforestChain/legacy-apps/libs/wallet-base/services/wallet/ethereum`/`/Users/kzf/Dev/bioforestChain/legacy-apps/libs/wallet-base/services/wallet/binance`/`/Users/kzf/Dev/bioforestChain/legacy-apps/libs/wallet-base/services/wallet/tron` + +1. getMethod 返回的是一个能自动 fallback 的函数,比如一个函数有多个 provider,那么 Provider1 失败(`比如 response.ok()===false,或者其它错误结构`),自动使用 Provider2 进行重试 + 1. 优先使用第三方,失败就 fallback 到 `*wallet-v1`, + 2. 基于 default-chains.json 中 api 的配置顺序:破坏性更新!将 api 字段改成数组 apis。 +2. 完善测试,在 walletaddressportfolio 中补充测试各种 provider(独立对 Provider 进行测试): + 1. 比如在 real-data-ethereum 中,同时提供所有支持的 provider + 2. 然后在测试中,确保至少有一个 Provider 真确显示出了非空的交易列表、非 0 的资产 +3. 这是我的 trongrid-api-key: c2c43cea-d490-4ba8-bab1-2ebf4ce81bae,我们可以优先使用 无 APIKEY 的 trongrid 免费接口,失败了再用有 api-key 的接口,再失败了再回退成使用 tronwallet-v1 +4. 先办法优化请求的调用次数,比如说这个方案:默认情况下余额和交易列表都是独立地去拉取,比如说 60s 轮询一次,但这会导致并发问题,可以优化成,如果余额变动了,那么交易列表再去触发拉取,否则交易列表的默认拉取时间是 5 分钟。 + 1. 以上这个方案我只是举一个粗糙的例子,这种代码实现可能会导致很多问题。这里我给出一些优化上的原则,不可以违背这些原则: + 2. 不可以为了优化而影响代码的可靠性和可维护性。比如我上面的例子,具体要实现的时候,得从 fetch 函数入手:通过篡改 fetch 函数,来得知余额变更,否则优先返回列表缓存。这样的好处是这些优化策略都是可以动态插拔的,不会影响业务。 + 3. 还有一些链,可能出块比较慢,那么需要可以等区块变更了,再去做后续的拉取。这里的核心逻辑是:将“轮询”封装成“订阅”,基于订阅机制去做按需更新 + 4. 每种策略要足够独立,通过交叉优化来逐步改进 +5. 更新白皮书 + +/Users/kzf/.factory/specs/2026-01-05-walletapi-fallback-providers-ordered-apis-request-optimization.md +/Users/kzf/.factory/specs/2026-01-06-merge-walletapi-fallback-worktree-to-main.md + +这是我的 etherscan-api-key: UN6TIKGANUFRYYPNSD1SCHRAZ3NABF52XS,KXX7MGJR3U6IEZNSY1ESMCXWUGX6Z8QEU6,TMMTZHU2XN2YM2A5YIXTXA9EKJS1GPC3GD +每次会话随机锁定其中一个,要能自动根据`,`分隔 api-key,然后随机选中其中一个(应用启动后,随机选中一次不会再变) +这种随机选中 api-key 的逻辑,也在 trongrid 适用。 + +--- + +1. 基于 spec 文件: /Users/kzf/.factory/specs/2026-01-05-option-b1-evm-hash-token.md 开始进行 review +2. 参考这份 spec,给出一份关于binance、tron、bitcoin 等优化方案: /Users/kzf/.factory/specs/2026-01-05-other-network-better-trs-list.md + +--- + +更新完成交易列表,我们需要更新交易详情页,请你给我一份详细的交易详情页的更新计划 + +/Users/kzf/.factory/specs/2026-01-05-update-transaction-detail-page-provider-schema.md +/Users/kzf/.factory/specs/2026-01-06-chain-adapter-ssot-guard-at-the-gate-safeparse-transactions.md + +--- + +我打开 storybook,发现大量的警告: + +``` +Use of an unknown prop (creditcard) in the Icons component. The Icons component is deprecated. Please use the @storybook/icons component directly. For more informations, see the migration notes at https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#icons-is-deprecat +``` + +--- + +刚才你已经成功将 tron 的两个接口都修复了,并学会了使用测试驱动开发(#173)。 +接下来,我需要你开始修复其它接口: + +1. eth: https://eth.blockscout.com/api 预期是交易和资产都能查询到;目前是能查询到交易但是资产错误显示0。 +2. eth: https://ethereum-rpc.publicnode.com 预期是资产能查询到,不支持交易查询;目前是能查询资产,但是交易查询一直 loading。 +3. eth: https://api.etherscan.io/v2/api 预期是交易和资产都能查询到;目前是能查询到交易但是资产错误显示0。 +4. bnb: https://bsc-rpc.publicnode.com 预期是资产能查询到,不支持交易查询;目前是能查询资产,但是交易查询一直 loading。 +5. bsc: https://api.etherscan.io/v2/api 预期是交易和资产都能查询到;目前是能查询到交易但是资产错误显示0。 + +walletapi相关的接口: + +6. eth: https://walletapi.bfmeta.info/wallet/eth 预期是交易和资产都能查询到;但是目前资产错误显示0,交易显示`Invalid API response` + 参考文件: /Users/kzf/Dev/bioforestChain/legacy-apps/libs/wallet-base/services/wallet/ethereum/ethereum.service.ts +7. tron: https://walletapi.bfmeta.info/wallet/tron 预期是交易和资产都能查询到;但是目前资产错误请求了`http://STORYBOOK_HOST/wallet/getaccount`,交易界面显示`Upstream API error`,我看网络面板是看到参数填写错误 + 参考文件: /Users/kzf/Dev/bioforestChain/legacy-apps/libs/wallet-base/services/wallet/tron/tron.service.ts +8. bitcoin: https://walletapi.bfmeta.info/wallet/btc 预期是交易和资产都能查询到;但是目前资产和交易都错误请求了`https://walletapi.bfmeta.info/wallet/btc/blockbook`,并且界面上没有正确显示错误信息 +9. bsc: https://walletapi.bfmeta.info/wallet/bsc 预期是交易和资产都能查询到;目前是能查询资产,但是显示没有交易记录(查询了`https://walletapi.bfmeta.info/wallet/bsc/trans/normal/history`,然后返回:`{"success":true,"result":{"status":"0","message":"NOTOK","result":[]}}`) + 参考文件: /Users/kzf/Dev/bioforestChain/legacy-apps/libs/wallet-base/services/wallet/binance/binance.service.ts + +/Users/kzf/.factory/specs/2026-01-06-api-walletapi.md diff --git a/CLAUDE.md b/CLAUDE.md index d5721de57..d3b8caa2a 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,19 +1,44 @@ -## ⚠️ 开始开发前 +## ⚠️ 开始开发前 (AI-Native Workflow) + +**Schema-first & Issue-Driven Development** + +### 1. 需求分析 (Investigate) +在正式开工前,先分析需求并查阅相关白皮书: ```bash -# 1. 获取索引(最佳实践 + 知识地图) -pnpm agent readme +# 生成 RFC 草稿和白皮书推荐 +pnpm agent investigate analyze --type --topic "需求描述" +``` -# 2. 查看当前任务 -pnpm agent roadmap current +### 2. 任务启动 (Task Start) +**严禁**手动创建 Issue/Branch/Worktree,必须使用自动化工作流: -# 3. 查阅白皮书必读章节 -pnpm agent chapter 00-必读 +```bash +# 自动创建 Issue -> Branch -> Worktree -> Draft PR +pnpm agent task start --type --title "Task Title" ``` -完整工作流和命令速查见 [AGENTS.md](./AGENTS.md) +### 3. 开发循环 (Develop Loop) +进入生成的 Worktree 目录后: + +```bash +# 同步进度到 Issue +pnpm agent task sync "- [x] Step 1 done" + +# 质量检查 (Pre-commit) +pnpm agent review verify +``` + +### 4. 完工提交 (Submit) + +```bash +# 推送代码并标记 PR 为 Ready +pnpm agent task submit +``` + +完整指南见 [AGENTS.md](./AGENTS.md) --- @@ -45,42 +70,22 @@ Keep this managed block so 'openspec update' can refresh the instructions. | 文档 | 路径 | 用途 | |-----|------|------| -| **白皮书** | `docs/white-book/` | 完整技术文档 | -| **mpay 原始代码** | `/Users/kzf/Dev/bioforestChain/legacy-apps/apps/mpay/` | 参考实现 | - -**优先级**: 白皮书 > mpay 原始代码 +| **白皮书** | `docs/white-book/` | 唯一权威技术文档 (Schema-first) | +| **Workflow** | `scripts/agent-flow/` | 自动化工作流源码 | ## 技术栈 - React 19 + Vite 7 - Stackflow (导航) + TanStack (Query + Store + Form) - shadcn/ui + Tailwind CSS 4.x -- Zod 4.x + i18next +- Zod 4.x (Schema-first) + i18next - Storybook 10.x + Vitest 4.x ## 开发原则 -- **参考而非复制** mpay 代码 -- **质疑原始实现**(可能有 Bug 或过时模式) -- **现代化改进**(TypeScript 类型安全、函数组件) - -## Git Worktree 工作流 - -所有编码工作必须在 `.git-worktree/` 目录下进行: - -```bash -pnpm agent worktree create issue-28 --branch feat/issue-28 -cd .git-worktree/issue-28 -# 开发... -gh pr create --body "Closes #28" -``` - -## 注意事项 - -- 所有组件必须有 Storybook story -- 所有业务逻辑必须有单元测试 -- 使用 TypeScript 严格模式 -- PR 描述使用 `Closes #issue编号` 自动关联任务 -- 合并前必须告知当前 worktree 路径并征求用户确认 +1. **Schema-first**: 先定义 `types.ts` 和 Zod Schema,再写实现。 +2. **Issue-Driven**: 没有 Issue 就没有代码。 +3. **Worktree-Only**: 所有开发必须在 `.git-worktree/` 下进行。 +4. **Test-Driven**: 业务逻辑必须有测试,UI 必须有 Storybook。 diff --git a/deno.lock b/deno.lock new file mode 100644 index 000000000..c917e6011 --- /dev/null +++ b/deno.lock @@ -0,0 +1,308 @@ +{ + "version": "5", + "specifiers": { + "jsr:@std/fs@*": "1.0.21", + "jsr:@std/internal@^1.0.12": "1.0.12", + "jsr:@std/path@*": "1.1.4", + "jsr:@std/path@^1.1.4": "1.1.4" + }, + "jsr": { + "@std/fs@1.0.21": { + "integrity": "d720fe1056d78d43065a4d6e0eeb2b19f34adb8a0bc7caf3a4dbf1d4178252cd", + "dependencies": [ + "jsr:@std/internal", + "jsr:@std/path@^1.1.4" + ] + }, + "@std/internal@1.0.12": { + "integrity": "972a634fd5bc34b242024402972cd5143eac68d8dffaca5eaa4dba30ce17b027" + }, + "@std/path@1.1.4": { + "integrity": "1d2d43f39efb1b42f0b1882a25486647cb851481862dc7313390b2bb044314b5", + "dependencies": [ + "jsr:@std/internal" + ] + } + }, + "workspace": { + "packageJson": { + "dependencies": [ + "npm:@axe-core/playwright@^4.11.0", + "npm:@base-ui/react@1", + "npm:@bfchain/util@5", + "npm:@bfmeta/sign-util@^1.3.10", + "npm:@bnqkl/server-util@^1.3.4", + "npm:@bnqkl/wallet-sdk@~0.23.8", + "npm:@bnqkl/wallet-typings@~0.23.8", + "npm:@fontsource-variable/dm-sans@^5.2.8", + "npm:@fontsource-variable/figtree@^5.2.10", + "npm:@fontsource/dm-mono@^5.2.7", + "npm:@fontsource/dm-serif-display@^5.2.8", + "npm:@gamepark/avataaars@3", + "npm:@inquirer/prompts@^8.0.2", + "npm:@noble/curves@^2.0.1", + "npm:@noble/hashes@^2.0.1", + "npm:@noble/secp256k1@3", + "npm:@number-flow/react@~0.5.10", + "npm:@plaoc/plugins@^1.1.9", + "npm:@playwright/test@^1.57.0", + "npm:@radix-ui/react-avatar@^1.1.11", + "npm:@radix-ui/react-dialog@^1.1.15", + "npm:@radix-ui/react-slot@^1.2.4", + "npm:@scure/base@2", + "npm:@scure/bip32@^2.0.1", + "npm:@scure/bip39@^2.0.1", + "npm:@stackflow/core@^1.3.0", + "npm:@stackflow/plugin-basic-ui@^1.18.1", + "npm:@stackflow/plugin-history-sync@^1.8.1", + "npm:@stackflow/plugin-renderer-basic@^1.1.13", + "npm:@stackflow/react@^1.11.1", + "npm:@storybook/addon-docs@^10.1.4", + "npm:@storybook/addon-vitest@^10.1.4", + "npm:@storybook/react-vite@^10.1.4", + "npm:@storybook/react@^10.1.4", + "npm:@storybook/test@^8.6.14", + "npm:@tabler/icons-react@^3.36.0", + "npm:@tailwindcss/vite@4", + "npm:@tanstack/ai@^0.0.3", + "npm:@tanstack/react-query@^5.90.12", + "npm:@tanstack/react-router@^1.140.0", + "npm:@tanstack/react-store@0.8", + "npm:@testing-library/jest-dom@^6.9.1", + "npm:@testing-library/react@^16.3.0", + "npm:@testing-library/user-event@^14.6.1", + "npm:@types/big.js@^6.2.2", + "npm:@types/lodash@^4.17.21", + "npm:@types/node@^24.10.1", + "npm:@types/qrcode@^1.5.6", + "npm:@types/react-dom@19", + "npm:@types/react@19", + "npm:@types/semver@^7.7.1", + "npm:@types/yargs@^17.0.35", + "npm:@vitejs/plugin-react@^5.1.1", + "npm:@vitest/browser-playwright@^4.0.15", + "npm:@vitest/browser@^4.0.15", + "npm:@vitest/coverage-istanbul@^4.0.15", + "npm:@vitest/coverage-v8@^4.0.15", + "npm:@zumer/snapdom@^2.0.1", + "npm:big.js@^7.0.1", + "npm:bip39@^3.1.0", + "npm:buffer@^6.0.3", + "npm:class-variance-authority@~0.7.1", + "npm:clsx@^2.1.1", + "npm:detect-port@^2.1.0", + "npm:dotenv@^17.2.3", + "npm:eslint-plugin-i18next@^6.1.3", + "npm:fake-indexeddb@^6.2.5", + "npm:i18next@^25.7.1", + "npm:idb@^8.0.3", + "npm:jsdom@^27.2.0", + "npm:jsqr@^1.4.0", + "npm:lodash@^4.17.21", + "npm:motion@^12.23.26", + "npm:oxlint@^1.32.0", + "npm:playwright@^1.57.0", + "npm:prettier-plugin-tailwindcss@~0.7.2", + "npm:prettier@^3.7.4", + "npm:qrcode.react@^4.2.0", + "npm:qrcode@^1.5.4", + "npm:react-dom@19", + "npm:react-error-boundary@6", + "npm:react-i18next@^16.4.0", + "npm:react-inspector@9", + "npm:react@19", + "npm:rollup-plugin-visualizer@^6.0.5", + "npm:semver@^7.7.3", + "npm:shadcn@^3.6.1", + "npm:sharp@~0.34.5", + "npm:ssh2-sftp-client@^12.0.1", + "npm:storybook@^10.1.4", + "npm:swiper@^12.0.3", + "npm:tailwind-merge@^3.4.0", + "npm:tailwindcss@4", + "npm:turbo@^2.7.1", + "npm:tw-animate-css@^1.4.0", + "npm:typescript@~5.9.3", + "npm:vaul@^1.1.2", + "npm:viem@^2.43.3", + "npm:vite-plugin-commonjs@~0.10.4", + "npm:vite-plugin-mkcert@^1.17.9", + "npm:vite@^7.2.7", + "npm:vitepress@^1.6.4", + "npm:vitest@^4.0.15", + "npm:yargs@18", + "npm:zod@^4.1.13" + ] + }, + "members": { + "miniapps/forge": { + "packageJson": { + "dependencies": [ + "npm:@base-ui/react@1", + "npm:@playwright/test@^1.49.1", + "npm:@radix-ui/react-avatar@^1.1.11", + "npm:@radix-ui/react-separator@^1.1.8", + "npm:@radix-ui/react-slot@^1.2.4", + "npm:@storybook/addon-docs@^10.1.4", + "npm:@storybook/addon-vitest@^10.1.4", + "npm:@storybook/react-vite@^10.1.4", + "npm:@storybook/react@^10.1.4", + "npm:@tailwindcss/vite@^4.1.0", + "npm:@testing-library/jest-dom@^6.6.3", + "npm:@testing-library/react@16", + "npm:@types/react-dom@19", + "npm:@types/react@19", + "npm:@vitejs/plugin-react@5", + "npm:@vitest/browser-playwright@^4.0.15", + "npm:@vitest/browser@^4.0.15", + "npm:class-variance-authority@~0.7.1", + "npm:clsx@^2.1.1", + "npm:eslint-plugin-i18next@^6.1.3", + "npm:framer-motion@^12.23.26", + "npm:i18next@^25.2.1", + "npm:jsdom@^26.1.0", + "npm:lucide-react@0.562", + "npm:oxlint@^1.32.0", + "npm:playwright@^1.57.0", + "npm:react-dom@19", + "npm:react-i18next@^15.5.2", + "npm:react@19", + "npm:storybook@^10.1.4", + "npm:tailwind-merge@^3.4.0", + "npm:tailwindcss@^4.1.0", + "npm:typescript@^5.9.3", + "npm:vite-plugin-mkcert@^1.17.9", + "npm:vite-tsconfig-paths@^5.1.0", + "npm:vite@^7.3.0", + "npm:vitest@4" + ] + } + }, + "miniapps/teleport": { + "packageJson": { + "dependencies": [ + "npm:@base-ui/react@1", + "npm:@bnqkl/metabox-core@0.5.2", + "npm:@bnqkl/wallet-typings@0.23.8", + "npm:@playwright/test@^1.49.1", + "npm:@radix-ui/react-avatar@^1.1.11", + "npm:@radix-ui/react-select@^2.2.6", + "npm:@radix-ui/react-separator@^1.1.8", + "npm:@radix-ui/react-slot@^1.2.4", + "npm:@storybook/addon-docs@^10.1.4", + "npm:@storybook/addon-vitest@^10.1.4", + "npm:@storybook/react-vite@^10.1.4", + "npm:@storybook/react@^10.1.4", + "npm:@tailwindcss/vite@^4.1.0", + "npm:@tanstack/react-query@^5.90.12", + "npm:@testing-library/jest-dom@^6.6.3", + "npm:@testing-library/react@16", + "npm:@types/react-dom@19", + "npm:@types/react@19", + "npm:@vitejs/plugin-react@5", + "npm:@vitest/browser-playwright@^4.0.15", + "npm:@vitest/browser@^4.0.15", + "npm:class-variance-authority@~0.7.1", + "npm:clsx@^2.1.1", + "npm:eslint-plugin-i18next@^6.1.3", + "npm:framer-motion@^12.23.26", + "npm:i18next@^25.2.1", + "npm:jsdom@^26.1.0", + "npm:lucide-react@0.562", + "npm:oxlint@^1.32.0", + "npm:playwright@^1.57.0", + "npm:react-dom@19", + "npm:react-i18next@^15.5.2", + "npm:react@19", + "npm:storybook@^10.1.4", + "npm:tailwind-merge@^3.4.0", + "npm:tailwindcss@^4.1.0", + "npm:typescript@^5.9.3", + "npm:vite-plugin-mkcert@^1.17.9", + "npm:vite-tsconfig-paths@^5.1.0", + "npm:vite@^7.3.0", + "npm:vitest@4" + ] + } + }, + "packages/bio-sdk": { + "packageJson": { + "dependencies": [ + "npm:jsdom@^26.1.0", + "npm:typescript@^5.9.3", + "npm:vite-plugin-dts@^4.5.4", + "npm:vite@^7.3.0", + "npm:vitest@4" + ] + } + }, + "packages/create-miniapp": { + "packageJson": { + "dependencies": [ + "npm:@inquirer/prompts@^7.5.0", + "npm:@types/node@^22.15.21", + "npm:@types/yargs@^17.0.33", + "npm:chalk@^5.4.1", + "npm:execa@^9.5.2", + "npm:oxlint@^1.32.0", + "npm:tsup@^8.5.0", + "npm:typescript@^5.9.3", + "npm:yargs@18" + ] + } + }, + "packages/e2e-tools": { + "packageJson": { + "dependencies": [ + "npm:typescript@^5.9.3", + "npm:vitest@4" + ] + } + }, + "packages/flow": { + "packageJson": { + "dependencies": [ + "npm:@modelcontextprotocol/sdk@1", + "npm:typescript@^5.7.0", + "npm:vitest@3", + "npm:zod@^3.24.0" + ] + } + }, + "packages/i18n-tools": { + "packageJson": { + "dependencies": [ + "npm:typescript@^5.9.3", + "npm:vitest@4" + ] + } + }, + "packages/keyapp-sdk": { + "packageJson": { + "dependencies": [ + "npm:react@19", + "npm:typescript@^5.9.3", + "npm:vitest@4" + ] + } + }, + "packages/plugin-navigation-sync": { + "packageJson": { + "dependencies": [ + "npm:flatted@^3.3.1", + "npm:history@^5.3.0", + "npm:urlpattern-polyfill@^10.1.0" + ] + } + }, + "packages/theme-tools": { + "packageJson": { + "dependencies": [ + "npm:typescript@^5.9.3", + "npm:vitest@4" + ] + } + } + } + } +} diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts index ef9823831..55b6b8816 100644 --- a/docs/.vitepress/config.ts +++ b/docs/.vitepress/config.ts @@ -26,6 +26,11 @@ export default defineConfig({ // webapp/storybook 目录由 CI 动态生成,忽略死链接检查 ignoreDeadLinks: [/\.\/webapp/, /\.\/webapp-dev/, /\.\/storybook/], + // 将 README.md 重写为 index.md (VitePress 默认入口) + rewrites: { + 'white-book/:path*/README.md': 'white-book/:path*/index.md', + }, + head: [ ['link', { rel: 'icon', type: 'image/webp', href: '/logos/logo-64.webp' }], ['meta', { name: 'theme-color', content: '#667eea' }], diff --git a/docs/.vitepress/sidebar-white-book.ts b/docs/.vitepress/sidebar-white-book.ts index 763532a2b..e60b8b0f9 100644 --- a/docs/.vitepress/sidebar-white-book.ts +++ b/docs/.vitepress/sidebar-white-book.ts @@ -14,6 +14,7 @@ interface FileMeta { /** * 从文件/目录名解析排序和显示名称 * 例如: "01-产品篇" -> { order: 1, name: "产品篇" } + * 例如: "01-Kernel-Ref" -> { order: 1, name: "Kernel-Ref" } * 例如: "Button.md" -> { order: 500, name: "Button" } */ function parseFileName(fileName: string, isDir: boolean): FileMeta { @@ -30,12 +31,17 @@ function parseFileName(fileName: string, isDir: boolean): FileMeta { } // 特殊处理:附录放最后 - if (baseName === '附录') { - return { order: 999, name: '附录', isDir, collapsed: true } + if (baseName === '附录' || baseName === '99-Appendix') { + return { order: 998, name: baseName.replace('99-', ''), isDir, collapsed: true } } - // index 文件不单独显示 - if (baseName === 'index') { + // 特殊处理:文档指南 + if (baseName === '99-Documentation-Guide') { + return { order: 999, name: 'Documentation-Guide', isDir, collapsed: true } + } + + // index/README/00-Index/00-Overview 文件不单独显示(由父目录处理) + if (baseName === 'index' || baseName === 'README' || baseName === '00-Index' || baseName === '00-Overview') { return { order: -1, name: '', isDir: false } } @@ -87,12 +93,17 @@ function scanDirectory( if (entry.isDirectory()) { const subUrlBase = `${urlBase}${entry.name}/` const indexPath = path.join(entryPath, 'index.md') + const readmePath = path.join(entryPath, 'README.md') + const zeroIndexPath = path.join(entryPath, '00-Index.md') - // 检查是否有 index.md + // 检查是否有 index.md, README.md, 或 00-Index.md const hasIndex = fs.existsSync(indexPath) - if (!hasIndex) continue + const hasReadme = fs.existsSync(readmePath) + const hasZeroIndex = fs.existsSync(zeroIndexPath) + if (!hasIndex && !hasReadme && !hasZeroIndex) continue - const title = getTitle(indexPath, meta.name) + const entryFile = hasIndex ? indexPath : hasReadme ? readmePath : zeroIndexPath + const title = getTitle(entryFile, meta.name) const children = scanDirectory(entryPath, subUrlBase, depth + 1) const item: SidebarItem & { _order: number } = { diff --git a/docs/white-book/00-Manifesto/00-Index.md b/docs/white-book/00-Manifesto/00-Index.md new file mode 100644 index 000000000..8257cc2ad --- /dev/null +++ b/docs/white-book/00-Manifesto/00-Index.md @@ -0,0 +1,253 @@ +# KeyApp 技术文档索引 + +> 这是一份 AI-First 的技术文档,旨在作为代码库的 **Digital Twin**。 + +--- + +## 序言:纠正 AI 直觉 + +AI 模型在开发移动端 Web 应用时,往往会基于通用 Web 开发经验做出直觉性的选择。但本项目使用了特定的技术栈和架构模式,这些"直觉"可能导致严重的问题。 + +### 🚫 常见错误直觉 + +最佳实践已独立维护在: + +- `00-Manifesto/07-Best-Practices.md` +- `pnpm agent practice list` + +### 📚 为什么会出错? + +1. **Stackflow 是页面栈管理器**:它管理整个页面栈的动画和生命周期。使用 `position: fixed` 会绕过 Stackflow 的控制,导致动画冲突、页面"抖动"等问题。 + +2. **本项目是移动端优先**:需要原生 App 般的用户体验,包括滑动返回、栈式导航等。传统 Web 的弹窗模式不适用。 + +3. **组件已经封装好**:不要重新发明轮子,查看 `src/components/` 和 `src/stackflow/activities/sheets/` 下的现有实现。 + +--- + +## 设计哲学 + +本文档的第一读者是 **AI Agent**,目标是让 AI 能够: +1. 完整理解系统架构和设计意图 +2. 准确定位任何功能的实现位置 +3. 独立完成开发、调试和重构任务 +4. 在必要时从文档重建整个代码库 + +--- + +## 文档结构 + +### 📘 参考手册 (Reference) + +| 编号 | 书名 | 目录 | 内容 | +|------|------|------|------| +| 01 | [Kernel Reference](../01-Kernel-Ref/README.md) | `01-Kernel-Ref/` | 小程序运行时内核 | +| 02 | [Driver Reference](../02-Driver-Ref/README.md) | `02-Driver-Ref/` | 链适配器/Provider | +| 03 | [UI Reference](../03-UI-Ref/README.md) | `03-UI-Ref/` | 组件库 (114个组件) | +| 04 | [Platform Reference](../04-Platform-Ref/README.md) | `04-Platform-Ref/` | 平台服务 | +| 05 | [State Reference](../05-State-Ref/00-Index.md) | `05-State-Ref/` | 状态管理 | +| 06 | [Service Reference](../06-Service-Ref/00-Index.md) | `06-Service-Ref/` | 服务层 (35个服务) | + +### 📗 开发指南 (Guide) + +| 编号 | 书名 | 目录 | 内容 | +|------|------|------|------| +| 10 | [Wallet Guide](../10-Wallet-Guide/README.md) | `10-Wallet-Guide/` | 钱包功能开发 | +| 11 | [DApp Guide](../11-DApp-Guide/README.md) | `11-DApp-Guide/` | DApp 集成 | +| 12 | [Shell Guide](../12-Shell-Guide/00-Navigation-Map.md) | `12-Shell-Guide/` | 页面导航 (61个页面) | + +### 📕 运维手册 (Operations) + +| 编号 | 书名 | 目录 | 内容 | +|------|------|------|------| +| 90 | [DevOps](../90-DevOps/README.md) | `90-DevOps/` | 构建/测试/部署 | +| 99 | [Documentation Guide](../99-Documentation-Guide/README.md) | `99-Documentation-Guide/` | 文档规范 | + +--- + +## 核心章节速查 + +| 章节 | 路径 | 何时阅读 | +|------|------|---------| +| **导航系统** | `12-Shell-Guide/` | 实现页面跳转、Tab 切换时 | +| **Sheet 组件** | `03-UI-Ref/03-Composites/` | 实现底部弹出层时 | +| **Dialog 组件** | `03-UI-Ref/03-Composites/` | 实现居中对话框时 | +| **服务架构** | `06-Service-Ref/` | 调用后端 API 或链服务时 | +| **钱包存储** | `06-Service-Ref/02-Wallet/` | 操作钱包数据时 | +| **测试策略** | `90-DevOps/` | 编写测试用例时 | + +--- + +## 外部文档链接 + +以下是本项目依赖的核心库的 LLM 友好文档: + +| 库 | 文档链接 | 用途 | +|---|---------|------| +| **Stackflow** | https://stackflow.so/llms-full.txt | 页面栈导航、Activity、Sheet、Modal | +| **shadcn/ui** | https://ui.shadcn.com/docs | UI 组件库 | +| **TanStack Query** | https://tanstack.com/query/latest | 数据获取和缓存 | +| **TanStack Store** | https://tanstack.com/store/latest | 状态管理 | + +--- + +## 开发检查清单 + +在开始编码前,请确认: + +- [ ] 是否已阅读相关白皮书章节? +- [ ] 是否已查看 `src/` 下的类似实现? +- [ ] 弹出层是否使用了 Stackflow 的 `BottomSheet` 或 `Modal`? +- [ ] 是否遵循了现有的代码风格和模式? +- [ ] 是否添加了必要的国际化文案? +- [ ] 是否更新了相关测试? + +--- + +## 代码库统计 + +| 类别 | 数量 | 覆盖率 | +|------|------|--------| +| 组件 (TSX) | 114 | 100% | +| 服务 (TS) | 160 | 100% | +| 页面 (Activities) | 31 | 100% | +| 弹窗 (Sheets) | 27 | 100% | +| Stores | 10 | 100% | +| Queries | 10 | 100% | + +--- + +## 源码映射 + +``` +src/ +├── components/ → 03-UI-Ref/ +│ ├── ui/ → 03-UI-Ref/02-Primitives/ +│ ├── common/ → 03-UI-Ref/03-Composites/ +│ ├── layout/ → 03-UI-Ref/03-Composites/ +│ ├── wallet/ → 03-UI-Ref/04-Domain/01-Wallet-Asset.md +│ ├── asset/ → 03-UI-Ref/04-Domain/01-Wallet-Asset.md +│ ├── token/ → 03-UI-Ref/04-Domain/01-Wallet-Asset.md +│ ├── transaction/ → 03-UI-Ref/04-Domain/02-Transaction-Transfer.md +│ ├── transfer/ → 03-UI-Ref/04-Domain/02-Transaction-Transfer.md +│ ├── onboarding/ → 03-UI-Ref/04-Domain/03-Onboarding-Security.md +│ ├── security/ → 03-UI-Ref/04-Domain/03-Onboarding-Security.md +│ ├── authorize/ → 03-UI-Ref/04-Domain/03-Onboarding-Security.md +│ ├── migration/ → 03-UI-Ref/04-Domain/03-Onboarding-Security.md +│ ├── ecosystem/ → 03-UI-Ref/04-Domain/04-Ecosystem.md +│ ├── settings/ → 03-UI-Ref/04-Domain/05-Settings-Notification.md +│ ├── notification/ → 03-UI-Ref/04-Domain/05-Settings-Notification.md +│ └── contact/ → 03-UI-Ref/04-Domain/05-Settings-Notification.md +│ +├── services/ → 06-Service-Ref/ +│ ├── wallet-storage/ → 06-Service-Ref/02-Wallet/01-Storage.md +│ ├── chain-adapter/ → 06-Service-Ref/03-Chain/ +│ ├── miniapp-runtime/ → 06-Service-Ref/04-MiniApp/01-Runtime.md +│ ├── ecosystem/ → 06-Service-Ref/04-MiniApp/02-Ecosystem.md +│ ├── biometric/ → 06-Service-Ref/05-Platform/01-Biometric.md +│ └── ... → 06-Service-Ref/ +│ +├── stores/ → 05-State-Ref/02-Stores/ +├── queries/ → 05-State-Ref/03-Queries/ +│ +└── stackflow/ → 12-Shell-Guide/ + ├── activities/ → 12-Shell-Guide/01-Activities/ + ├── activities/sheets/ → 12-Shell-Guide/02-Sheets/ + └── activities/tabs/ → 12-Shell-Guide/03-Tabs/ +``` + +--- + +## 快速参考 + +### Stackflow Activity 类型 + +```tsx +// 普通全屏页面 +import { AppScreen } from "@stackflow/plugin-basic-ui"; + +// 底部弹出层(Sheet) +import { BottomSheet } from "@stackflow/plugin-basic-ui"; + +// 居中对话框(Modal) +import { Modal } from "@stackflow/plugin-basic-ui"; +``` + +### 导航操作 + +```tsx +import { useFlow } from "@/stackflow"; + +const { push, pop, replace } = useFlow(); + +// 打开新页面 +push("ActivityName", { param: "value" }); + +// 返回上一页 +pop(); + +// 替换当前页面 +replace("ActivityName", { param: "value" }); +``` + +### Sheet Activity 模式 + +当需要创建新的 Sheet 时,参考 `src/stackflow/activities/sheets/` 下的实现: + +1. 创建 Activity 组件,使用 `` 或 `` 包裹 +2. 在 `stackflow.ts` 中注册路由和组件 +3. 在 `sheets/index.ts` 中导出 + +--- + +## 常见问题 + +### Q: 为什么我的弹窗导致页面"抖动"或消失? + +A: 你可能使用了 Radix Dialog 或自定义 `position: fixed`。这会与 Stackflow 的动画系统冲突。请改用 Stackflow 的 `BottomSheet` 或 `Modal`。 + +### Q: 如何传递数据给 Sheet 并获取返回值? + +A: 使用全局回调模式。参考 `WalletLockConfirmJob` 的实现: + +```tsx +// 设置回调 +setWalletLockConfirmCallback((patternKey) => { + // 处理返回的图案密钥 +}); + +// 打开 Sheet +push("WalletLockConfirmJob", {}); +``` + +### Q: 什么时候用 BottomSheet,什么时候用 Modal? + +- **BottomSheet**:选择列表、表单输入、确认操作(从底部滑入) +- **Modal**:警告、确认对话框(居中显示) + +--- + +## 快速导航 + +### 按功能 + +- **钱包创建/导入**: [Onboarding Components](../03-UI-Ref/04-Domain/03-Onboarding-Security.md) → [Wallet Storage](../06-Service-Ref/02-Wallet/01-Storage.md) +- **转账**: [Transfer Components](../03-UI-Ref/04-Domain/02-Transaction-Transfer.md) → [Chain Adapter](../06-Service-Ref/03-Chain/01-Adapter.md) +- **余额查询**: [Balance Query](../05-State-Ref/03-Queries/01-Balance-Query.md) → [API Providers](../06-Service-Ref/03-Chain/06-Providers.md) +- **小程序**: [Ecosystem Components](../03-UI-Ref/04-Domain/04-Ecosystem.md) → [MiniApp Runtime](../06-Service-Ref/04-MiniApp/01-Runtime.md) + +### 按技术栈 + +- **React 组件**: [UI Reference](../03-UI-Ref/README.md) +- **状态管理**: [State Reference](../05-State-Ref/00-Index.md) +- **页面路由**: [Navigation Map](../12-Shell-Guide/00-Navigation-Map.md) +- **区块链接口**: [Chain Adapter](../06-Service-Ref/03-Chain/01-Adapter.md) + +--- + +## 相关文档 + +- [Architecture Overview](./03-Architecture.md) +- [Coding Guidelines](./06-Guidelines.md) +- [Best Practices](./07-Best-Practices.md) +- [Documentation Guide](../99-Documentation-Guide/README.md) diff --git a/docs/white-book/00-Manifesto/01-Vision.md b/docs/white-book/00-Manifesto/01-Vision.md new file mode 100644 index 000000000..f27ce7552 --- /dev/null +++ b/docs/white-book/00-Manifesto/01-Vision.md @@ -0,0 +1,25 @@ +# 01. 项目愿景 (Vision) + +## WebOS for Crypto + +KeyApp 不仅仅是一个多链钱包,它是一个 **去中心化 DApp 运行时 (Decentralized DApp Runtime)**,即 **WebOS**。 + +### 核心理念 + +1. **微内核 (Micro-Kernel)**: + * 通过 `miniapp-runtime` 实现应用进程隔离。 + * 每个 DApp 运行在独立的 iframe 沙箱中。 + * 通过 `BioBridge` 进行受控的跨进程通信。 + +2. **驱动分离 (Driver Abstraction)**: + * 底层链的差异被封装在 `ChainAdapter` 层。 + * 上层应用通过统一的 `ApiProvider` 接口与链交互。 + * 支持动态加载新的链驱动。 + +3. **沉浸式体验 (Immersive Shell)**: + * 提供类似原生 OS 的多任务管理 (Stack View)。 + * 支持手势导航、FLIP 动画和系统级通知。 + +### 为什么这样做? + +传统的 DApp 浏览器只是一个 WebView。KeyApp 试图在浏览器中重建操作系统的核心能力:**安全隔离**、**资源调度** 和 **统一交互**。这使得 KeyApp 能够成为连接 Web2 用户与 Web3 世界的终极网关。 diff --git a/docs/white-book/00-Manifesto/02-Tech-Stack.md b/docs/white-book/00-Manifesto/02-Tech-Stack.md new file mode 100644 index 000000000..a4b501f93 --- /dev/null +++ b/docs/white-book/00-Manifesto/02-Tech-Stack.md @@ -0,0 +1,30 @@ +# 02. 技术栈清单 (Tech Stack) + +KeyApp 选用了最现代化的前端技术栈,以支撑 WebOS 的复杂性。 + +## Core Framework +* **React 19**: 利用最新的 Hooks 和并发特性。 +* **Vite 6**: 极速构建工具,支持 ESM。 +* **TypeScript 5**: 严格类型安全。 + +## State Management +* **TanStack Store**: 轻量级、原子化的全局状态管理 (替代 Redux/Zustand)。 +* **TanStack Query (v5)**: 异步数据管理,用于链上数据缓存和同步。 + +## Navigation & Shell +* **Stackflow**: 仿原生 iOS/Android 的路由和页面栈管理。 + * *Why?* React Router 无法提供原生 App 的页面堆叠和手势体验。 + +## UI System +* **Tailwind CSS 4**: 原子化 CSS 引擎。 +* **shadcn/ui**: 基于 Radix UI 的可定制组件库。 +* **Framer Motion / Motion**: 负责复杂的 FLIP 动画和转场。 + +## Testing +* **Vitest**: 单元测试 (兼容 Jest API)。 +* **Playwright**: 端到端 (E2E) 测试。 + +## Architecture Patterns +* **Dependency Injection (DI)**: 通过 `context.tsx` 实现服务解耦。 +* **Adapter Pattern**: 用于多链适配 (`chain-adapter`)。 +* **Actor Model**: 用于 `miniapp-runtime` 的进程通信。 diff --git a/docs/white-book/00-Manifesto/03-Architecture.md b/docs/white-book/00-Manifesto/03-Architecture.md new file mode 100644 index 000000000..ca28117ec --- /dev/null +++ b/docs/white-book/00-Manifesto/03-Architecture.md @@ -0,0 +1,77 @@ +# Architecture Map + +KeyApp follows a **Layered Architecture** inspired by Operating System design. + +```mermaid +graph TD + subgraph "App Layer (DApps)" + DApp1[Uniswap] + Miniapp[System Miniapps] + end + + subgraph "Shell Layer (System UI)" + Router[Stackflow Router] + SystemApps[Wallet / Settings] + end + + subgraph "Kernel Layer (Runtime)" + Process[Process Manager] + Window[Window Manager] + Sandbox[Iframe Sandbox] + end + + subgraph "State Layer (Reactive)" + Stores[TanStack Store] + Queries[TanStack Query] + end + + subgraph "Service Layer (Logic)" + WalletCore[Wallet Core] + Identity[Biometric / Auth] + Platform[Platform Adapters] + end + + subgraph "Driver Layer (Chain)" + HAL[ApiProvider Interface] + EVM[EVM Driver] + UTXO[BTC Driver] + TVM[Tron Driver] + end + + DApp1 --> Sandbox + Sandbox --> ServiceLayer + SystemApps --> StateLayer + StateLayer --> ServiceLayer + ServiceLayer --> DriverLayer + ServiceLayer --> Platform +``` + +## Navigation Paths (Multi-Dimensional Access) + +### 1. By Code Structure (Physical View) +Mapping source directories to documentation books. + +| Architecture Layer | Code Path | Documentation Book | +| :--- | :--- | :--- | +| **Kernel** | `src/services/miniapp-runtime` | [`01-Kernel-Ref`](../01-Kernel-Ref) | +| **Drivers** | `src/services/chain-adapter` | [`02-Driver-Ref`](../02-Driver-Ref) | +| **UI System** | `src/components/ui`, `src/styles` | [`03-UI-Ref`](../03-UI-Ref) | +| **Platform** | `src/services/{biometric,camera,...}` | [`04-Platform-Ref`](../04-Platform-Ref) | +| **State** | `src/stores`, `src/queries` | [`05-State-Ref`](../05-State-Ref) | +| **Services** | `src/services/{chain-config,ecosystem,...}` | [`06-Service-Ref`](../06-Service-Ref) | +| **Wallet Logic** | `src/services/wallet`, `src/services/transaction` | [`10-Wallet-Guide`](../10-Wallet-Guide) | +| **DApps** | `src/components/ecosystem` | [`11-DApp-Guide`](../11-DApp-Guide) | +| **Shell** | `src/stackflow` | [`12-Shell-Guide`](../12-Shell-Guide) | +| **DevOps** | `vite.config.ts`, `.github` | [`90-DevOps`](../90-DevOps) | + +### 2. By User Flow (Logical View) +Tracing a feature across multiple layers. + +* **Transaction Flow**: + * Lifecycle: [`10-Wallet-Guide/03-Transaction-Flow`](../10-Wallet-Guide/03-Transaction-Flow) + * State: [`05-State-Ref/02-Stores/01-Wallet-Store`](../05-State-Ref/02-Stores/01-Wallet-Store.md) + * Driver: [`02-Driver-Ref`](../02-Driver-Ref) +* **Balance Refresh**: + * Query: [`05-State-Ref/03-Queries/01-Balance-Query`](../05-State-Ref/03-Queries/01-Balance-Query.md) + * Store: [`05-State-Ref/02-Stores/01-Wallet-Store`](../05-State-Ref/02-Stores/01-Wallet-Store.md) + * Platform: [`04-Platform-Ref/04-Haptics`](../04-Platform-Ref/04-Haptics.md) diff --git a/docs/white-book/00-Manifesto/04-Get-Started.md b/docs/white-book/00-Manifesto/04-Get-Started.md new file mode 100644 index 000000000..20b2636b9 --- /dev/null +++ b/docs/white-book/00-Manifesto/04-Get-Started.md @@ -0,0 +1,36 @@ +# 04. 快速开始 (Get Started) + +## 环境要求 +* **Node.js**: v20+ +* **pnpm**: v9+ (推荐 v10) +* **Git**: v2.40+ + +## 启动流程 + +1. **安装依赖** + ```bash + pnpm install + ``` + +2. **启动开发服务器** + ```bash + pnpm dev + ``` + 这将启动 Vite 服务,默认访问地址为 `http://localhost:5173`。 + +3. **运行测试** + * 单元测试: `pnpm test` + * 类型检查: `pnpm typecheck` + +4. **构建** + ```bash + pnpm build + ``` + +## 常用命令别名 (Agent) + +我们封装了一套 `pnpm agent` 工具链,辅助 AI 开发: + +* `pnpm agent readme`: 获取项目索引和上下文。 +* `pnpm agent worktree create `: 创建隔离开发环境。 +* `pnpm agent claim `: 领取任务。 diff --git "a/docs/white-book/01-\344\272\247\345\223\201\347\257\207/01-\344\272\247\345\223\201\346\204\277\346\231\257/index.md" b/docs/white-book/00-Manifesto/05-Product-Vision.md similarity index 63% rename from "docs/white-book/01-\344\272\247\345\223\201\347\257\207/01-\344\272\247\345\223\201\346\204\277\346\231\257/index.md" rename to docs/white-book/00-Manifesto/05-Product-Vision.md index d8a2b4beb..1990b3db1 100644 --- "a/docs/white-book/01-\344\272\247\345\223\201\347\257\207/01-\344\272\247\345\223\201\346\204\277\346\231\257/index.md" +++ b/docs/white-book/00-Manifesto/05-Product-Vision.md @@ -1,52 +1,50 @@ -# 第一章:产品愿景 +# 产品愿景 -> **让每个人都能安全、简单地管理自己的数字资产。** +> 让每个人都能安全、简单地管理自己的数字资产。 --- -## 1.1 产品定位 +## 产品定位 -BFM Pay 是一款**多链数字钱包移动应用**,目标是成为用户进入 Web3 世界的可信赖入口。 +BFM Pay 是一款 **多链数字钱包移动应用**,目标是成为用户进入 Web3 世界的可信赖入口。 ### 核心理念 -我们相信:**复杂的区块链技术不应成为普通用户的障碍。** +**复杂的区块链技术不应成为普通用户的障碍。** | 传统钱包的问题 | BFM Pay 的解决方案 | -|--------------|-------------------| -| 需要理解"助记词""Gas费"等概念 | 用通俗语言解释,引导式操作 | -| 多个钱包管理不同链的资产 | 一个钱包,多链支持 | +|----------------|-------------------| +| 需要理解助记词、Gas费 | 用通俗语言解释,引导式操作 | +| 多个钱包管理不同链 | 一个钱包,多链支持 | | 界面复杂,功能堆砌 | 渐进式复杂度,新手友好 | | 转错地址无法挽回 | 多重确认,地址簿管理 | -### 产品形态 +--- + +## 产品形态 ``` ┌─────────────────────────────────────────┐ │ BFM Pay │ ├─────────────────────────────────────────┤ -│ │ │ ┌─────────┐ ┌─────────┐ │ │ │ Web │ │ DWEB │ │ │ │ 版本 │ │ 版本 │ │ │ └────┬────┘ └────┬────┘ │ -│ │ │ │ │ └────────┬────────┘ │ -│ │ │ │ ┌───────▼───────┐ │ │ │ 统一核心 │ │ │ │ React + TS │ │ │ └───────────────┘ │ -│ │ └─────────────────────────────────────────┘ ``` -- **Web 版本**:浏览器访问,无需安装 -- **DWEB 版本**:Plaoc 原生应用,更深度的系统集成 +- **Web 版本**: 浏览器访问,无需安装 +- **DWEB 版本**: Plaoc 原生应用,更深度的系统集成 --- -## 1.2 目标市场 +## 目标市场 ### 主要市场 @@ -64,39 +62,32 @@ BFM Pay 是一款**多链数字钱包移动应用**,目标是成为用户进 --- -## 1.3 价值主张 - -### 对用户的价值 +## 价值主张 ``` ┌─────────────────────────────────────────────────┐ -│ │ │ 🔐 安全 → 私钥本地存储,永不上传 │ -│ │ │ 🌐 多链 → 一个钱包,管理所有链资产 │ -│ │ │ 📱 便捷 → 随时随地,轻松转账收款 │ -│ │ │ 🔗 生态 → 无缝连接 DWEB 应用 │ -│ │ └─────────────────────────────────────────────────┘ ``` ### 核心功能价值 | 功能 | 用户价值 | 技术实现 | -|-----|---------|---------| -| 创建钱包 | 30秒拥有自己的数字身份 | 助记词生成 + 多链派生 | +|------|----------|----------| +| 创建钱包 | 30秒拥有数字身份 | 助记词生成 + 多链派生 | | 资产查看 | 一目了然的资产状况 | 多链余额聚合 | | 转账收款 | 像发微信一样简单 | 统一的转账流程 | -| 跨链质押 | 参与生态建设,获取收益 | Mint/Burn 机制 | +| 跨链质押 | 参与生态,获取收益 | Mint/Burn 机制 | | DWEB 授权 | 安全地与应用交互 | Plaoc 协议 | --- -## 1.4 与 mpay 的关系 +## 与 mpay 的关系 -BFM Pay 是 mpay 的**技术重构版本**,而非简单的 UI 改版。 +BFM Pay 是 mpay 的 **技术重构版本**,而非简单的 UI 改版。 ### 保留 @@ -108,7 +99,7 @@ BFM Pay 是 mpay 的**技术重构版本**,而非简单的 UI 改版。 ### 提升 | 方面 | mpay (Angular) | BFM Pay (React) | -|-----|---------------|-----------------| +|------|----------------|-----------------| | 框架 | Angular 15 | React 19 | | 状态管理 | Service + RxJS | TanStack Store/Query | | 导航 | Angular Router | Stackflow | @@ -128,12 +119,12 @@ BFM Pay 是 mpay 的**技术重构版本**,而非简单的 UI 改版。 --- -## 1.5 成功指标 +## 成功指标 ### 用户体验指标 | 指标 | 目标 | -|-----|------| +|------|------| | 首次创建钱包时间 | < 60秒 | | 完成一笔转账时间 | < 30秒 | | 新用户次日留存率 | > 40% | @@ -142,7 +133,7 @@ BFM Pay 是 mpay 的**技术重构版本**,而非简单的 UI 改版。 ### 技术质量指标 | 指标 | 目标 | -|-----|------| +|------|------| | 单元测试覆盖率 | > 70% | | E2E 测试通过率 | 100% | | Lighthouse 性能分 | > 90 | @@ -150,15 +141,8 @@ BFM Pay 是 mpay 的**技术重构版本**,而非简单的 UI 改版。 --- -## 本章小结 - -- BFM Pay 的愿景是让数字资产管理变得安全、简单 -- 核心定位是多链钱包,服务 BioforestChain 生态和主流公链用户 -- 是 mpay 的技术重构,保留业务逻辑,提升技术栈和用户体验 -- 成功需要同时满足用户体验和技术质量指标 - ---- - -## 下一章 +## 相关文档 -继续阅读 [第二章:用户画像](../02-用户画像/),深入了解我们的目标用户。 +- [技术栈](./02-Tech-Stack.md) +- [开发工作流](./03-Workflow.md) +- [设计原则](../03-UI-Ref/01-Foundation/02-Design-Principles.md) diff --git a/docs/white-book/00-Manifesto/05-Workflows.md b/docs/white-book/00-Manifesto/05-Workflows.md new file mode 100644 index 000000000..fb3caf6e0 --- /dev/null +++ b/docs/white-book/00-Manifesto/05-Workflows.md @@ -0,0 +1,24 @@ +# 05. 开发工作流 (Workflows) + +为了保证代码质量和 AI 协作的高效性,我们强制执行以下工作流。 + +## 1. Git Worktree 模式 +永远不要在主目录直接开发。必须为每个任务创建一个独立的 worktree: + +```bash +pnpm agent worktree create fix-bug-123 --branch fix/issue-123 --base main +cd .git-worktree/fix-bug-123 +``` + +这保证了环境的隔离性,避免了 `node_modules` 污染和分支切换的开销。 + +## 2. Spec Mode (规划优先) +在开始编码之前,AI 必须进入 **Spec Mode**,撰写详细的实现计划。只有用户批准 Spec 后,才能退出 Spec Mode 开始写代码。 + +## 3. Pull Request 规范 +* **Title**: 遵循 Conventional Commits (e.g., `feat(wallet): add multi-chain support`). +* **Body**: 清晰描述 Changes, Reason, 和 Test Plan。 +* **Review**: 所有 PR 必须经过 CI 检查并通过 Review 才能合并。 + +## 4. CD 流程 +* **gh-pages**: 我们使用 `gh-pages` 分支托管预览版。CD 流程会自动 force-push 构建产物到该分支。 diff --git a/docs/white-book/00-Manifesto/06-Guidelines.md b/docs/white-book/00-Manifesto/06-Guidelines.md new file mode 100644 index 000000000..774e3acf2 --- /dev/null +++ b/docs/white-book/00-Manifesto/06-Guidelines.md @@ -0,0 +1,33 @@ +# Best Practices + +> **Note**: This file is automatically maintained by `pnpm agent practice`. + +## List + +- ❌ Radix Dialog / position:fixed → ✅ Stackflow BottomSheet/Modal +- ❌ React Router → ✅ Stackflow push/pop/replace +- ❌ 复制 mpay 代码 → ✅ 理解后用 React/TS 重写 +- ❌ 随意创建 store → ✅ 遵循 stores/ 现有模式 +- ❌ 明文选择器 → ✅ data-testid +- ❌ 安装新 UI 库 → ✅ shadcn/ui(已集成) +- ❌ 新建 CSS → ✅ Tailwind CSS +- ❌ text-secondary → ✅ text-muted-foreground 或 bg-secondary text-secondary-foreground(详见白皮书 02-设计篇/02-视觉设计/theme-colors) +- ❌ bg-primary text-white → ✅ bg-primary text-primary-foreground(暗色模式下 text-white 对比度不足) +- ❌ bg-muted 无文字色 → ✅ bg-muted text-muted-foreground(详见白皮书 02-设计篇/02-视觉设计/dark-mode) +- ❌ bg-gray-100 无 dark: 变体 → ✅ bg-gray-100 dark:bg-gray-800 或使用 bg-muted +- ❌ getByText('硬编码中文') → ✅ getByText(t('i18n.key')) 或 getByTestId +- ❌ password/Password(宽泛含义) → ✅ walletLock(钱包锁)/ twoStepSecret(安全密码)/ payPassword(支付密码)等具体命名 +- 圆形元素必须使用 aspect-square 标记,与 w-*/h-*/size-* 不冲突,是规范要求 +- 组件尺寸属性要考虑响应式布局,如 lg 尺寸应包含 @xs:w-12 等容器查询断点 +- ❌ JS scroll 事件监听 → ✅ CSS scroll-driven animations(animation-timeline: scroll()) +- 滚动驱动动画使用 `scroll-timeline: --name block` 定义 + `animation-timeline: --name` 绑定 +- 跨层级绑定使用 `timeline-scope: --name` 在公共祖先上声明 +- 紧凑头部效果使用 `animation-range: 0 80px` 限制动画范围 +- ⚠️ scroll-driven animations 是渐进增强:初始状态必须是可用的(如 opacity-0),不支持时保持初始状态 +- E2E 截图变更后运行 `pnpm e2e:audit` 检查残留截图,详见白皮书 08-测试篇/03-Playwright配置/e2e-best-practices +- 组件专属样式使用 CSS Modules:`component-name.module.css` + `import styles from './xxx.module.css'` +- CSS Modules 适用场景:@keyframes 动画、伪元素(::before/::after)、复杂选择器(:focus-within)、scroll-driven animations +- CSS Modules 与 Tailwind 混用:`className={cn(styles.header, 'sticky top-0 z-10 px-5')}` +- 优先级:CSS Modules > globals.css,组件样式应内聚到组件目录 +- ❌ as TypeAssertion → ✅ z.looseObject().safeParse() 验证外部 API 响应 +- ❌ z.record(z.record(...)) → ✅ z.record(z.string(), z.record(z.string(), schema))(Zod 4 嵌套 record 需显式 key 类型) diff --git "a/docs/white-book/00-\345\277\205\350\257\273/best-practices.md" b/docs/white-book/00-Manifesto/07-Best-Practices.md similarity index 100% rename from "docs/white-book/00-\345\277\205\350\257\273/best-practices.md" rename to docs/white-book/00-Manifesto/07-Best-Practices.md diff --git "a/docs/white-book/01-\344\272\247\345\223\201\347\257\207/03-\347\224\250\346\210\267\346\225\205\344\272\213/index.md" b/docs/white-book/00-Manifesto/08-User-Stories.md similarity index 98% rename from "docs/white-book/01-\344\272\247\345\223\201\347\257\207/03-\347\224\250\346\210\267\346\225\205\344\272\213/index.md" rename to docs/white-book/00-Manifesto/08-User-Stories.md index 7c546a4c3..40189269c 100644 --- "a/docs/white-book/01-\344\272\247\345\223\201\347\257\207/03-\347\224\250\346\210\267\346\225\205\344\272\213/index.md" +++ b/docs/white-book/00-Manifesto/08-User-Stories.md @@ -1,10 +1,10 @@ -# 第三章:用户故事 +# 用户故事 > 定义完整的功能需求和验收标准 --- -## 3.1 Epic 概览 +## Epic 概览 BFM Pay 的功能需求组织为 10 个 Epic: @@ -451,6 +451,8 @@ USD, CNY, EUR, JPY, KRW 等 --- -## 下一篇 +## 相关文档 -完成产品篇后,继续阅读 [第二篇:设计篇](../../02-设计篇/),了解产品的交互和视觉设计。 +- [产品愿景](./05-Product-Vision.md) +- [导航地图](../12-Shell-Guide/00-Navigation-Map.md) +- [Onboarding 组件](../03-UI-Ref/05-Components/08-Onboarding.md) diff --git a/docs/white-book/00-Manifesto/README.md b/docs/white-book/00-Manifesto/README.md new file mode 100644 index 000000000..71e7fcbda --- /dev/null +++ b/docs/white-book/00-Manifesto/README.md @@ -0,0 +1,19 @@ +# 🧭 Book E1: The Manifesto (开发者手册) + +> **KeyApp 开发者的第一站**。这里包含了项目的愿景、架构概览、技术栈清单以及核心的编码准则。 + +## 📖 目录 + +* [01-Vision.md](./01-Vision.md) - **WebOS for Crypto**:为什么 KeyApp 不仅仅是一个钱包? +* [02-Tech-Stack.md](./02-Tech-Stack.md) - 技术栈清单 (React 19, Vite, TanStack, Stackflow) +* [03-Architecture.md](./03-Architecture.md) - 宏观架构图 (Kernel - Shell - Driver - App) +* [04-Get-Started.md](./04-Get-Started.md) - 从零开始:环境搭建与启动 +* [05-Product-Vision.md](./05-Product-Vision.md) - **产品愿景**:让数字资产管理变得安全、简单 +* [05-Workflows.md](./05-Workflows.md) - AI 协作流 (Worktree, Spec Mode, PR) +* [06-Guidelines.md](./06-Guidelines.md) - 编码规范 (Hooks, i18n, Comments) + +## 🎯 核心原则 + +1. **AI-Native**: 所有代码和文档的首要读者是 AI Agent。保持上下文清晰、原子化。 +2. **WebOS 架构**: 我们在浏览器中构建操作系统。理解 Kernel (运行时)、Driver (链适配) 和 Shell (界面) 的分离。 +3. **Spec First**: 先思考 (Spec Mode),再行动。所有复杂变更必须先产出 Spec。 diff --git "a/docs/white-book/00-\345\277\205\350\257\273/index.md" "b/docs/white-book/00-\345\277\205\350\257\273/index.md" deleted file mode 100644 index 90c8021b2..000000000 --- "a/docs/white-book/00-\345\277\205\350\257\273/index.md" +++ /dev/null @@ -1,145 +0,0 @@ -# AI 开发指南 - 必读 - -> **重要**:本章节是 AI 模型开发本项目前的必读内容。 - ---- - -## 序言:纠正 AI 直觉 - -AI 模型在开发移动端 Web 应用时,往往会基于通用 Web 开发经验做出直觉性的选择。但本项目使用了特定的技术栈和架构模式,这些"直觉"可能导致严重的问题。 - -### 🚫 常见错误直觉 - -最佳实践已独立维护在: - -- `00-必读/best-practices.md` -- `pnpm agent practice list` - -### 📚 为什么会出错? - -1. **Stackflow 是页面栈管理器**:它管理整个页面栈的动画和生命周期。使用 `position: fixed` 会绕过 Stackflow 的控制,导致动画冲突、页面"抖动"等问题。 - -2. **本项目是移动端优先**:需要原生 App 般的用户体验,包括滑动返回、栈式导航等。传统 Web 的弹窗模式不适用。 - -3. **组件已经封装好**:不要重新发明轮子,查看 `src/components/` 和 `src/stackflow/activities/sheets/` 下的现有实现。 - ---- - -## 目录索引 - -使用以下命令获取白皮书完整目录: - -```bash -# 列出所有白皮书章节 -find docs/white-book -name "*.md" | sort -``` - -或者让 AI 执行 Grep 命令动态获取。 - -### 核心章节速查 - -| 章节 | 路径 | 何时阅读 | -|------|------|---------| -| **导航系统** | `03-架构篇/03-导航系统/` | 实现页面跳转、Tab 切换时 | -| **Sheet 组件** | `05-组件篇/01-基础组件/Sheet.md` | 实现底部弹出层时 | -| **Dialog 组件** | `05-组件篇/01-基础组件/Dialog.md` | 实现居中对话框时 | -| **服务架构** | `04-服务篇/01-服务架构/` | 调用后端 API 或链服务时 | -| **钱包存储** | `04-服务篇/08-钱包数据存储/` | 操作钱包数据时 | -| **国际化** | `07-国际化篇/` | 添加文案或多语言时 | -| **测试策略** | `08-测试篇/` | 编写测试用例时 | -| **E2E 最佳实践** | `08-测试篇/03-Playwright配置/e2e-best-practices.md` | **必读:禁止使用明文选择器** | - ---- - -## 外部文档链接 - -以下是本项目依赖的核心库的 LLM 友好文档: - -| 库 | 文档链接 | 用途 | -|---|---------|------| -| **Stackflow** | https://stackflow.so/llms-full.txt | 页面栈导航、Activity、Sheet、Modal | -| **shadcn/ui** | https://ui.shadcn.com/docs | UI 组件库 | -| **TanStack Query** | https://tanstack.com/query/latest | 数据获取和缓存 | -| **TanStack Store** | https://tanstack.com/store/latest | 状态管理 | - ---- - -## 开发检查清单 - -在开始编码前,请确认: - -- [ ] 是否已阅读相关白皮书章节? -- [ ] 是否已查看 `src/` 下的类似实现? -- [ ] 弹出层是否使用了 Stackflow 的 `BottomSheet` 或 `Modal`? -- [ ] 是否遵循了现有的代码风格和模式? -- [ ] 是否添加了必要的国际化文案? -- [ ] 是否更新了相关测试? - ---- - -## 快速参考 - -### Stackflow Activity 类型 - -```tsx -// 普通全屏页面 -import { AppScreen } from "@stackflow/plugin-basic-ui"; - -// 底部弹出层(Sheet) -import { BottomSheet } from "@stackflow/plugin-basic-ui"; - -// 居中对话框(Modal) -import { Modal } from "@stackflow/plugin-basic-ui"; -``` - -### 导航操作 - -```tsx -import { useFlow } from "@/stackflow"; - -const { push, pop, replace } = useFlow(); - -// 打开新页面 -push("ActivityName", { param: "value" }); - -// 返回上一页 -pop(); - -// 替换当前页面 -replace("ActivityName", { param: "value" }); -``` - -### Sheet Activity 模式 - -当需要创建新的 Sheet 时,参考 `src/stackflow/activities/sheets/` 下的实现: - -1. 创建 Activity 组件,使用 `` 或 `` 包裹 -2. 在 `stackflow.ts` 中注册路由和组件 -3. 在 `sheets/index.ts` 中导出 - ---- - -## 常见问题 - -### Q: 为什么我的弹窗导致页面"抖动"或消失? - -A: 你可能使用了 Radix Dialog 或自定义 `position: fixed`。这会与 Stackflow 的动画系统冲突。请改用 Stackflow 的 `BottomSheet` 或 `Modal`。 - -### Q: 如何传递数据给 Sheet 并获取返回值? - -A: 使用全局回调模式。参考 `WalletLockConfirmJob` 的实现: - -```tsx -// 设置回调 -setWalletLockConfirmCallback((patternKey) => { - // 处理返回的图案密钥 -}); - -// 打开 Sheet -push("WalletLockConfirmJob", {}); -``` - -### Q: 什么时候用 BottomSheet,什么时候用 Modal? - -- **BottomSheet**:选择列表、表单输入、确认操作(从底部滑入) -- **Modal**:警告、确认对话框(居中显示) diff --git a/docs/white-book/01-Kernel-Ref/00-Overview.md b/docs/white-book/01-Kernel-Ref/00-Overview.md new file mode 100644 index 000000000..271c5e0df --- /dev/null +++ b/docs/white-book/01-Kernel-Ref/00-Overview.md @@ -0,0 +1,38 @@ +# 00. 内核架构全景 (Kernel Overview) + +KeyApp 的内核 (`miniapp-runtime`) 是一个运行在浏览器主线程中的 **微内核 (Micro-Kernel)**。它的主要职责不是处理业务逻辑,而是管理 **进程 (Process)** 和 **资源 (Resource)**。 + +## 核心组件 + +1. **Process Manager**: 维护所有 DApp 的生命周期 (`MiniappInstance`)。 +2. **Window Manager**: 管理所有可见窗口 (`MiniappPresentation`) 及其 Z-Order 和动画。 +3. **Iframe Sandbox**: 为每个 DApp 创建隔离的执行环境。 +4. **BioBridge**: 提供宿主 (Host) 与微应用 (Miniapp) 之间的安全通信通道。 + +## 架构图 + +```mermaid +graph TD + subgraph "Host (KeyApp Main Thread)" + Kernel[Miniapp Kernel] + Store[Runtime Store] + BridgeHost[BioBridge Host] + + Kernel --> Store + Kernel --> BridgeHost + end + + subgraph "Sandbox (Iframe)" + BridgeGuest[BioBridge Guest] + DAppCode[DApp Code] + + DAppCode --> BridgeGuest + end + + BridgeHost <-->|postMessage| BridgeGuest +``` + +## 设计哲学 + +* **UI as a Function of State**: 内核本身是一个基于 TanStack Store 的状态机。所有的 UI 变化(如窗口打开、关闭)都是状态变更的副作用。 +* **Isolation by Default**: 默认情况下,DApp 无法访问任何系统资源,必须通过 Bridge 请求权限。 diff --git a/docs/white-book/01-Kernel-Ref/01-Process/01-State-Machine.md b/docs/white-book/01-Kernel-Ref/01-Process/01-State-Machine.md new file mode 100644 index 000000000..d798d4f09 --- /dev/null +++ b/docs/white-book/01-Kernel-Ref/01-Process/01-State-Machine.md @@ -0,0 +1,113 @@ + + +# 01. 进程状态机 (Process State Machine) + +KeyApp 的微应用运行时 (`miniapp-runtime`) 采用严格的**有限状态机 (FSM)** 来管理应用生命周期。这确保了应用在资源受限环境下的可预测行为。 + +## 核心状态 (`MiniappState`) + +状态机包含 6 个互斥状态。任何时刻,一个应用实例 (`MiniappInstance`) 只能处于其中一种状态。 + +| 状态 | 定义 | 资源占用 | 可交互性 | +| :--- | :--- | :--- | :--- | +| `preparing` | **准备中**。内核正在检查启动所需的资源(Icon Ref, Slot Ref, Iframe Ref)。如果资源未就绪,启动流程会被中止。 | 低 | 无 | +| `launching` | **启动中**。资源已就绪,iframe 正在加载 (`loading`),但尚未触发 `load` 事件。 | 高 (CPU/Net) | 无 | +| `splash` | **闪屏页**。iframe 可能已加载,但根据 Manifest 配置,展示系统级 Splash Screen 以掩盖初始化过程。 | 高 | 无 | +| `active` | **前台激活**。应用处于前台,iframe 可见且获得输入焦点。这是应用的正常运行状态。 | 高 | **有** | +| `background` | **后台运行**。应用被切换到后台。iframe 被移动到隐藏容器 (`visibility: hidden`),但在内存中保活。 | 中 (Memory) | 无 | +| `closing` | **关闭中**。用户请求关闭,系统正在播放退出动画。动画结束后,所有资源将被释放。 | 中 | 无 | + +## 状态流转图 (State Transitions) + +```mermaid +stateDiagram-v2 + [*] --> preparing: launchApp() + + state preparing { + [*] --> CheckResources + CheckResources --> ResourceReady + CheckResources --> ResourceMissing: Timeout + } + + preparing --> launching: ResourceReady + preparing --> [*]: ResourceMissing (Fail) + + state launching { + [*] --> CreateIframe + CreateIframe --> IframeLoading + } + + launching --> splash: Has Splash Config + launching --> active: No Splash & Loaded + + state splash { + [*] --> WaitSplashTimeout + WaitSplashTimeout --> DismissSplash + } + + splash --> active: DismissSplash + + active --> background: deactivateApp() + background --> active: activateApp() + + active --> closing: closeApp() + background --> closing: closeApp() + + state closing { + [*] --> PlayDismissAnimation + PlayDismissAnimation --> CleanupResources + } + + closing --> [*]: Finalized +``` + +## 动画流 (`MiniappFlow`) + +除了生命周期状态,内核还维护一个 `flow` 属性,专门用于描述**视觉过渡的方向性**。这对于实现流畅的 FLIP 动画至关重要。 + +### 状态 vs 流 + +* **State**: 描述应用的逻辑状态(存活/死亡/前台/后台)。 +* **Flow**: 描述应用在状态切换时的视觉表现。 + +### Flow 枚举 + +* `opening`: 图标 -> 窗口 (展开) +* `opened`: 窗口静止 (稳定态) +* `backgrounding`: 窗口 -> 图标 (收缩) +* `backgrounded`: 隐藏 (稳定态) +* `foregrounding`: 图标 -> 窗口 (再次展开) +* `closing`: 窗口 -> 消失 (销毁) + +> [!NOTE] +> `flow` 属性通常由 UI 层(如 `MiniappWindow.tsx`)监听,用于触发 CSS Transition 或 Framer Motion 动画。动画完成后,UI 层会回调内核的 `settleFlow()` 方法,将 `opening` 修正为 `opened`。 + +## 代码实现 + +状态转换逻辑集中在 `updateAppState` 函数中: + +```typescript +// src/services/miniapp-runtime/index.ts + +function updateAppState(appId: string, state: MiniappState): void { + miniappRuntimeStore.setState((s) => { + const app = s.apps.get(appId) + if (!app) return s + + // 根据前一个状态和新状态,推导 flow + const flow = deriveFlow(app.state, state) + + const newApps = new Map(s.apps) + newApps.set(appId, { ...app, state, flow }) + + return { ...s, apps: newApps } + }) + + // 广播事件 + emit({ type: 'app:state-change', appId, state }) +} +``` diff --git a/docs/white-book/01-Kernel-Ref/01-Process/02-Scheduling.md b/docs/white-book/01-Kernel-Ref/01-Process/02-Scheduling.md new file mode 100644 index 000000000..fa2baf7d9 --- /dev/null +++ b/docs/white-book/01-Kernel-Ref/01-Process/02-Scheduling.md @@ -0,0 +1,22 @@ +# 02. 调度与保活 (Scheduling) + +Code: `src/services/miniapp-runtime/iframe-manager.ts` + +为了防止浏览器内存溢出,KeyApp 实现了一套简单的调度策略来管理后台应用。 + +## 后台限制 (Background Limit) + +* **最大后台数**: 默认为 **4** 个 (`MAX_BACKGROUND_IFRAMES`)。 +* **淘汰策略**: **LRU (Least Recently Used)**。当后台应用数量超过限制时,最久未使用的应用会被强行销毁。 + +## Watchdog 机制 + +为了防止应用在关闭过程中卡死(例如动画回调未触发),内核启动了一个 **Watchdog Timer**。 +* **超时时间**: 30秒 (`DISMISS_WATCHDOG_DELAY`)。 +* **行为**: 如果在超时后应用仍未完成关闭流程,Watchdog 会强制执行 `finalizeCloseApp` 进行资源清理。 + +## 准备阶段超时 + +在 `preparing` 阶段,内核会等待 DOM 元素(图标、插槽)就绪。为了防止无限等待: +* **超时时间**: 2.5秒 (`PREPARING_TIMEOUT`)。 +* **行为**: 超时后自动取消启动,并提示用户错误信息。 diff --git a/docs/white-book/01-Kernel-Ref/02-Window/01-Presentation-Model.md b/docs/white-book/01-Kernel-Ref/02-Window/01-Presentation-Model.md new file mode 100644 index 000000000..23e6e41e5 --- /dev/null +++ b/docs/white-book/01-Kernel-Ref/02-Window/01-Presentation-Model.md @@ -0,0 +1,97 @@ + + +# 01. 窗口模型 (Presentation Model) + +KeyApp 的窗口管理器负责管理所有微应用在屏幕上的几何位置、层级 (Z-Order) 和动画上下文。它采用了 **Presentation-Desktop** 模型。 + +## 核心数据结构 + +### 1. Presentation (`MiniappPresentation`) + +`Presentation` 是应用在视觉层的投影。一个应用可能有实例 (`MiniappInstance`) 但没有呈现(例如纯后台服务,虽然目前 KeyApp 尚未支持无头应用)。 + +```typescript +export interface MiniappPresentation { + appId: string; + + /** 目标桌面 (stack | grid) */ + desktop: MiniappTargetDesktop; + + /** 视觉状态 (hidden | presenting | presented | dismissing) */ + state: MiniappPresentationState; + + /** Z 轴层级 */ + zOrder: number; + + /** 当前关联的过渡动画 ID */ + transitionId: string | null; + + /** 过渡类型 (present | dismiss) */ + transitionKind: MiniappTransitionKind | null; +} +``` + +### 2. Runtime Refs + +为了实现高性能的 **FLIP 动画**,内核必须直接持有 DOM 元素的引用。这是通过 `runtime-refs.ts` 中的注册表实现的。 + +| 引用类型 | 获取函数 | 描述 | +| :--- | :--- | :--- | +| **IconRef** | `getIconRef(appId)` | 桌面图标元素。动画的起点/终点。 | +| **SlotRef** | `getDesktopAppSlotRef(desktop, appId)` | 窗口在桌面布局中的占位容器。 | +| **IframeRef** | `app.iframeRef` | 实际的内容载体。 | + +## 窗口层级管理 (Z-Order Strategy) + +KeyApp 使用简单的 **自增种子 (Incremental Seed)** 策略来管理窗口层级,模仿原生 OS 的行为。 + +1. **全局种子**: Store 中维护一个 `zOrderSeed`,初始为 1。 +2. **聚焦 (Focus)**: 当应用被点击、激活或启动时,内核调用 `requestFocus(appId)`。 +3. **提升**: + * `zOrderSeed` 自增 1。 + * 目标应用的 `presentation.zOrder` 被更新为新的种子值。 + * 这保证了该应用永远处于所有其他窗口之上。 + +```typescript +// src/services/miniapp-runtime/index.ts + +export function requestFocus(appId: string): void { + miniappRuntimeStore.setState((s) => { + // ... + const nextZ = s.zOrderSeed + 1 + // ... + return { + ...s, + activeAppId: appId, + zOrderSeed: nextZ, // 全局种子递增 + } + }) +} +``` + +## 桌面模式 (Desktops) + +目前支持两种桌面模式: + +1. **Stack Desktop (默认)**: + * 类似 iOS 的多任务堆叠视图。 + * 窗口全屏显示,支持手势滑动切换。 + * 适用于大多数 DApp。 + +2. **Grid Desktop**: + * 传统桌面网格布局。 + * (预留) 支持小组件或悬浮窗模式。 + +## 视觉配置 (Visual Config) + +窗口的外观可以通过 `MiniappVisualConfig` 进行系统级配置: + +* **胶囊 (Capsule)**: 这里的"胶囊"是指右上角的控制按钮(关闭、更多)。应用可以请求 `dark` 或 `light` 主题的胶囊以适配自身背景。 +* **圆角 (Radius)**: 窗口圆角半径。 +* **遮罩 (Mask)**: 背景遮罩的透明度。 + +这些配置不仅影响静态布局,也会参与 FLIP 动画的补间计算。 diff --git a/docs/white-book/01-Kernel-Ref/02-Window/02-FLIP-Animation.md b/docs/white-book/01-Kernel-Ref/02-Window/02-FLIP-Animation.md new file mode 100644 index 000000000..b65ca1cca --- /dev/null +++ b/docs/white-book/01-Kernel-Ref/02-Window/02-FLIP-Animation.md @@ -0,0 +1,20 @@ +# 02. FLIP 动画引擎 (FLIP Animation) + +KeyApp 的标志性特征是其流畅的 **App 打开/关闭动画**,这完全基于 **FLIP (First, Last, Invert, Play)** 技术实现。 + +## 原理 + +1. **First (初始态)**: 获取图标 (`IconRef`) 在屏幕上的 `DOMRect`。 +2. **Last (最终态)**: 获取应用窗口 (`SlotRef`) 在屏幕上的 `DOMRect`。 +3. **Invert (反转)**: + * 计算两个 Rect 之间的位移 (`deltaX`, `deltaY`) 和缩放比例 (`scaleX`, `scaleY`)。 + * 将窗口元素通过 CSS `transform` 瞬间移动到图标的位置和大小,使其看起来像是在图标那里。 +4. **Play (播放)**: + * 移除 `transform`,并添加 `transition` 属性。 + * 浏览器会自动补间,使窗口从图标位置平滑放大到全屏位置。 + +## 性能优化 + +* **Will-Change**: 在动画开始前添加 `will-change: transform` 提示浏览器创建合成层。 +* **Layout ID**: 利用 Framer Motion 的 `layoutId` 自动处理复杂的共享元素过渡。 +* **遮罩同步**: 动画过程中,同步调整圆角 (`borderRadius`) 和遮罩,确保视觉连贯性。 diff --git a/docs/white-book/01-Kernel-Ref/03-Sandbox/01-Iframe-Manager.md b/docs/white-book/01-Kernel-Ref/03-Sandbox/01-Iframe-Manager.md new file mode 100644 index 000000000..68f2ab53b --- /dev/null +++ b/docs/white-book/01-Kernel-Ref/03-Sandbox/01-Iframe-Manager.md @@ -0,0 +1,25 @@ +# 01. Iframe 管理 (Iframe Manager) + +Code: `src/services/miniapp-runtime/iframe-manager.ts` + +Iframe 是 DApp 的容器。KeyApp 对 Iframe 进行了深度的定制管理。 + +## 创建策略 + +* **URL 构造**: 基础 URL + 上下文参数 (Context Params)。 +* **Sandbox**: 启用严格的沙箱模式: + ```typescript + iframe.sandbox.add('allow-scripts', 'allow-forms', 'allow-same-origin') + ``` + 注意:通常不开启 `allow-top-navigation`,防止 DApp 篡改主页面。 + +## 挂载策略 + +为了支持后台保活,KeyApp 使用了 **双容器策略**: + +1. **Visible Container**: 用于存放前台 Active 应用的 iframe。 +2. **Hidden Container**: 用于存放后台 Background 应用的 iframe。 + * 样式: `position: fixed; top: -9999px; visibility: hidden`。 + * 目的: 保持 DOM 节点存在,不触发 reload,但移出可视区域。 + +当应用在 前台/后台 切换时,我们只是简单地将 iframe 节点在两个容器之间 `appendChild` (移动节点),而不是销毁重建。这保证了 DApp 状态不丢失。 diff --git a/docs/white-book/01-Kernel-Ref/03-Sandbox/02-BioBridge-Protocol.md b/docs/white-book/01-Kernel-Ref/03-Sandbox/02-BioBridge-Protocol.md new file mode 100644 index 000000000..b9990a533 --- /dev/null +++ b/docs/white-book/01-Kernel-Ref/03-Sandbox/02-BioBridge-Protocol.md @@ -0,0 +1,40 @@ +# 02. BioBridge 协议 (BioBridge Protocol) + +**BioBridge** 是 Host 和 Guest (DApp) 之间的通信桥梁。 + +## 通信机制 + +基于 `window.postMessage` 实现双向 RPC 调用。 + +### 1. 请求 (Request) +DApp -> Host: +```json +{ + "id": 123, + "method": "bio.wallet.requestAccounts", + "params": [] +} +``` + +### 2. 响应 (Response) +Host -> DApp: +```json +{ + "id": 123, + "result": ["0x..."], + "error": null +} +``` + +## API 命名空间 + +* `bio.wallet.*`: 钱包相关 (连接、签名、转账) +* `bio.device.*`: 设备能力 (剪贴板、震动、生物识别) +* `bio.window.*`: 窗口控制 (关闭、全屏) + +## 安全检查 + +在处理任何请求之前,内核会检查: +1. **Origin**: 消息来源是否匹配 Manifest 中的定义。 +2. **Permission**: DApp 是否申请了对应的权限 (e.g., `wallet:write`). +3. **User Consent**: 敏感操作 (签名、授权) 必须弹出系统级对话框供用户确认。 diff --git a/docs/white-book/01-Kernel-Ref/README.md b/docs/white-book/01-Kernel-Ref/README.md new file mode 100644 index 000000000..0bf7bf339 --- /dev/null +++ b/docs/white-book/01-Kernel-Ref/README.md @@ -0,0 +1,18 @@ +# 📘 Book T1: The Kernel Reference (内核技术参考) + +> **Core of the WebOS** +> +> 本书深入解析 `miniapp-runtime` 的内部机制,解释 KeyApp 如何在浏览器中实现进程隔离、窗口管理和跨进程通信。 + +## 📖 目录 + +* [00-Overview.md](./00-Overview.md) - 内核架构全景 +* **01-Process (进程管理)** + * [01-State-Machine.md](./01-Process/01-State-Machine.md) - 进程状态机 + * [02-Scheduling.md](./01-Process/02-Scheduling.md) - 调度与保活 +* **02-Window (窗口管理)** + * [01-Presentation-Model.md](./02-Window/01-Presentation-Model.md) - 窗口模型 + * [02-FLIP-Animation.md](./02-Window/02-FLIP-Animation.md) - 动画引擎 +* **03-Sandbox (沙箱隔离)** + * [01-Iframe-Manager.md](./03-Sandbox/01-Iframe-Manager.md) - Iframe 管理 + * [02-BioBridge-Protocol.md](./03-Sandbox/02-BioBridge-Protocol.md) - BioBridge 协议 diff --git "a/docs/white-book/01-\344\272\247\345\223\201\347\257\207/02-\347\224\250\346\210\267\347\224\273\345\203\217/index.md" "b/docs/white-book/01-\344\272\247\345\223\201\347\257\207/02-\347\224\250\346\210\267\347\224\273\345\203\217/index.md" deleted file mode 100644 index 56bf4345c..000000000 --- "a/docs/white-book/01-\344\272\247\345\223\201\347\257\207/02-\347\224\250\346\210\267\347\224\273\345\203\217/index.md" +++ /dev/null @@ -1,260 +0,0 @@ -# 第二章:用户画像 - -> 深入理解我们的用户是谁,他们需要什么 - ---- - -## 2.1 主要用户群体 - -### 👤 新手小白 (Alice) - -**基本信息** -- 年龄:28岁 -- 职业:设计师 -- 技术水平:普通用户,熟悉手机 App - -**背景故事** -> Alice 听朋友说起加密货币,想尝试但觉得技术门槛高。她用过支付宝和微信支付,但从未接触过区块链。 - -**痛点** -- 😰 害怕操作失误丢失资产 -- 😕 不理解"助记词""Gas 费"等概念 -- 🤔 担心被骗或黑客攻击 - -**期望** -- ✅ 像支付宝一样简单 -- ✅ 有清晰的操作引导 -- ✅ 出问题能找到帮助 - -**心智模型** -``` -钱包 = 银行账户 -助记词 = 银行卡密码 -转账 = 微信转账 -``` - ---- - -### 👤 进阶用户 (Bob) - -**基本信息** -- 年龄:35岁 -- 职业:程序员 -- 技术水平:熟悉区块链,使用过多款钱包 - -**背景故事** -> Bob 已有多个链的资产,使用过 MetaMask、Trust Wallet、imToken 等钱包。他对技术有一定了解,但讨厌在多个钱包间切换。 - -**痛点** -- 😤 需要在多个钱包间切换 -- 😫 跨链操作繁琐 -- 🙄 重复的设置和备份流程 - -**期望** -- ✅ 一个钱包管理所有链 -- ✅ 快速完成日常操作 -- ✅ 高级功能不被隐藏 - -**心智模型** -``` -钱包 = 资产管理工具 -效率 = 最重要的事 -安全 = 基本要求 -``` - ---- - -### 👤 活跃交易者 (Carol) - -**基本信息** -- 年龄:30岁 -- 职业:交易员 -- 技术水平:精通区块链,高频交易 - -**背景故事** -> Carol 每天进行多笔转账和交易,需要快速确认交易状态。她最担心的是转错地址或被钓鱼攻击。 - -**痛点** -- 😱 担心转错地址 -- ⏱️ 需要快速确认交易状态 -- 🎣 警惕钓鱼和欺诈 - -**期望** -- ✅ 地址簿管理常用地址 -- ✅ 实时交易状态更新 -- ✅ 完整的历史记录 - -**心智模型** -``` -钱包 = 交易终端 -安全 = 生命线 -速度 = 金钱 -``` - ---- - -## 2.2 用户心智模型 - -### 关键认知映射 - -| 用户认知 | 技术概念 | 产品设计对应 | -|---------|---------|-------------| -| "钱包 = 存钱的地方" | 密钥管理 | 首页突出显示余额,像银行 App | -| "地址 = 账号" | 公钥哈希 | 简化地址展示,提供复制和二维码 | -| "助记词 = 最高密码" | BIP39 种子 | 强调备份重要性,通俗类比解释 | -| "转账要确认" | 签名广播 | 双重确认机制,显示手续费 | -| "不同链 = 不同银行" | 多链架构 | 清晰的链切换,统一的操作体验 | - -### 心智模型图 - -``` -用户视角 技术视角 -───────────── ───────────── - 钱包 ←────────→ 密钥对 - │ │ - ▼ ▼ - 账户/地址 ←────────→ 公钥地址 - │ │ - ▼ ▼ - 余额 ←────────→ 链上状态 - │ │ - ▼ ▼ - 转账 ←────────→ 签名交易 -``` - ---- - -## 2.3 用户旅程阶段 - -### 阶段一:认知 - -> "这是什么?对我有什么用?" - -**用户状态** -- 第一次听说或看到 BFM Pay -- 可能来自朋友推荐或应用商店 - -**设计重点** -- 清晰的价值主张 -- 简洁的首屏信息 -- 降低认知负担 - ---- - -### 阶段二:入门 - -> "我要怎么开始?" - -**用户状态** -- 决定尝试,开始创建或导入钱包 -- 最容易流失的阶段 - -**设计重点** -- 引导式流程 -- 即时反馈 -- 允许跳过非必要步骤 - ---- - -### 阶段三:日常使用 - -> "我需要完成一个任务" - -**用户状态** -- 已有钱包,进行日常操作 -- 转账、收款、查看余额 - -**设计重点** -- 高效的操作路径 -- 减少点击次数 -- 记住用户偏好 - ---- - -### 阶段四:进阶探索 - -> "还有什么高级功能?" - -**用户状态** -- 熟悉基础功能 -- 探索质押、DApp 连接等 - -**设计重点** -- 功能可发现性 -- 不干扰基础体验 -- 渐进式披露 - ---- - -### 阶段五:问题解决 - -> "出问题了,怎么办?" - -**用户状态** -- 遇到错误或困惑 -- 寻求帮助 - -**设计重点** -- 清晰的错误信息 -- 可访问的帮助入口 -- 自助解决方案 - ---- - -## 2.4 用户优先级 - -### 功能优先级矩阵 - -``` - 高频 - │ - ┌────────────┼────────────┐ - │ 转账 │ 查看余额 │ - │ 收款 │ 切换链 │ - 高 │────────────┼────────────│ 低 - 价值 │ 备份 │ 设置 │ 价值 - │ DApp授权 │ 历史记录 │ - │────────────┼────────────│ - │ 质押 │ 地址簿 │ - │ 导入钱包 │ 网络设置 │ - └────────────┼────────────┘ - │ - 低频 -``` - -### 开发优先级 - -| 优先级 | 功能 | 目标用户 | -|-------|------|---------| -| P0 | 创建/导入钱包、查看余额、转账、收款 | 所有用户 | -| P1 | 多链切换、交易历史、备份助记词 | 所有用户 | -| P2 | 地址簿、应用锁、指纹支付 | 进阶用户 | -| P3 | 质押、DApp 授权、自定义网络 | 活跃用户 | - ---- - -## 2.5 竞品对比中的用户需求 - -### 用户痛点对比 - -| 痛点 | MetaMask | Trust Wallet | BFM Pay 方案 | -|-----|----------|--------------|-------------| -| 助记词理解困难 | 无解释 | 简单提示 | 通俗类比 + 引导 | -| 多链管理混乱 | 手动添加网络 | 预置网络 | 统一的链切换面板 | -| 转账地址输入 | 纯手动 | 地址簿 | 扫码 + 地址簿 + 历史 | -| Gas 费理解 | 技术术语 | 简化显示 | "网络费用" + 预估法币 | - ---- - -## 本章小结 - -- 三类核心用户:新手小白、进阶用户、活跃交易者 -- 用户心智模型决定产品设计语言 -- 用户旅程分五个阶段,每阶段有不同设计重点 -- 功能开发按用户价值和使用频率确定优先级 - ---- - -## 下一章 - -继续阅读 [第三章:用户故事](../03-用户故事/),了解具体的功能需求和验收标准。 diff --git "a/docs/white-book/01-\344\272\247\345\223\201\347\257\207/index.md" "b/docs/white-book/01-\344\272\247\345\223\201\347\257\207/index.md" deleted file mode 100644 index cb87130d6..000000000 --- "a/docs/white-book/01-\344\272\247\345\223\201\347\257\207/index.md" +++ /dev/null @@ -1,56 +0,0 @@ -# 第一篇:产品篇 - -> 定义产品的「做什么」和「为什么」 - ---- - -## 概述 - -产品篇回答三个核心问题: - -1. **我们在做什么?** → [产品愿景](./01-产品愿景/) -2. **为谁而做?** → [用户画像](./02-用户画像/) -3. **具体做哪些功能?** → [用户故事](./03-用户故事/) - ---- - -## 章节导航 - -### [第一章:产品愿景](./01-产品愿景/) - -定义 BFM Pay 的核心定位和价值主张。 - -**要点**: -- 让每个人都能安全、简单地管理数字资产 -- 多链支持,一个钱包管理所有资产 -- 用户友好,复杂技术不成为障碍 - -### [第二章:用户画像](./02-用户画像/) - -深入分析目标用户群体及其需求。 - -**要点**: -- 三类核心用户:新手小白、进阶用户、活跃交易者 -- 用户心智模型:钱包 = 存钱的地方 -- 关键洞察:安全与便捷的平衡 - -### [第三章:用户故事](./03-用户故事/) - -定义完整的功能需求和验收标准。 - -**要点**: -- 10 个核心 Epic,覆盖完整用户旅程 -- 每个故事包含主线流程、支线流程、异常处理 -- 用户心智考量贯穿始终 - ---- - -## 本篇来源 - -本篇内容主要来源于 `PDR.md`(产品需求文档),并结合 mpay 原始代码的业务逻辑分析。 - ---- - -## 下一篇 - -完成产品篇的阅读后,建议继续阅读 [第二篇:设计篇](../02-设计篇/),了解产品的交互和视觉设计。 diff --git a/docs/white-book/02-Driver-Ref/00-Overview.md b/docs/white-book/02-Driver-Ref/00-Overview.md new file mode 100644 index 000000000..ef70e350a --- /dev/null +++ b/docs/white-book/02-Driver-Ref/00-Overview.md @@ -0,0 +1,49 @@ +# 00. 适配层架构 (Overview) + +Code: `src/services/chain-adapter/` + +为了支持多链 (EVM, UTXO, TVM),KeyApp 引入了一个抽象层,称为 **Driver Layer (或 HAL)**。 + +## 核心概念 + +### 1. ApiProvider (Driver) +每个 Provider 代表一个特定的数据源驱动。 +* 例如:`EtherscanProvider`, `EvmRpcProvider`, `MempoolProvider`。 +* 职责:负责与具体的后端 API 通信,并规范化数据格式。 + +### 2. ChainProvider (Manager) +每个链 (`chainId`) 拥有一个 `ChainProvider` 实例。 +* 职责:聚合该链配置下的所有 `ApiProvider`。 +* 策略:实现 **Fallback** 逻辑。如果 Etherscan 挂了,自动切换到 RPC。 + +### 3. Registry (Factory) +负责根据 `default-chains.json` 的配置,动态实例化对应的 Providers。 + +## 架构图 + +```mermaid +graph TD + User[UI / WalletStore] + + subgraph "ChainProvider (Manager)" + LB[Load Balancer / Fallback] + end + + subgraph "Drivers" + P1[Etherscan Provider] + P2[RPC Provider] + P3[WalletAPI Provider] + end + + subgraph "External World" + API1[api.etherscan.io] + API2[infura.io] + API3[walletapi.bfmeta.info] + end + + User --> LB + LB --> P1 & P2 & P3 + P1 --> API1 + P2 --> API2 + P3 --> API3 +``` diff --git a/docs/white-book/02-Driver-Ref/01-Protocol/01-Provider-Interface.md b/docs/white-book/02-Driver-Ref/01-Protocol/01-Provider-Interface.md new file mode 100644 index 000000000..f1408545a --- /dev/null +++ b/docs/white-book/02-Driver-Ref/01-Protocol/01-Provider-Interface.md @@ -0,0 +1,174 @@ + + +# 01. ApiProvider 接口规范 (HAL) + +`ApiProvider` 是 KeyApp 多链架构的核心抽象接口,相当于操作系统的 **硬件抽象层 (HAL)**。任何想要接入 KeyApp 的区块链网络,都必须实现此接口。 + +## 接口定义 + +```typescript +export interface ApiProvider { + /** + * 驱动类型标识 + * Format: `{protocol}-{variant}` + * Example: 'etherscan-v2', 'ethereum-rpc', 'mempool-v1' + */ + readonly type: string; + + /** + * 服务端点 URL + * Example: 'https://api.etherscan.io/v2/api' + */ + readonly endpoint: string; + + /** + * 配置参数 + * Example: { apiKeyEnv: 'ETHERSCAN_API_KEY' } + */ + readonly config?: Record; + + // ========== 能力声明 (Capabilities) ========== + // Provider 必须显式声明其支持的功能,以便 ChainProvider 进行路由和降级 + + /** 是否支持原生代币余额查询 (e.g. ETH, BTC) */ + readonly supportsNativeBalance?: boolean; + + /** 是否支持交易历史查询 */ + readonly supportsTransactionHistory?: boolean; + + /** 是否支持代币余额查询 (e.g. ERC20, TRC20) */ + readonly supportsTokenBalances?: boolean; + + /** 是否支持单笔交易查询 */ + readonly supportsTransaction?: boolean; + + /** 是否支持区块高度查询 */ + readonly supportsBlockHeight?: boolean; + + /** 是否支持交易广播 */ + readonly supportsBroadcast?: boolean; + + // ========== 核心方法 (Core Methods) ========== + + /** + * 查询原生代币余额 + * @param address 钱包地址 + * @returns 标准化的余额对象 + */ + getNativeBalance?(address: string): Promise; + + /** + * 查询代币余额列表 + * @param address 钱包地址 + */ + getTokenBalances?(address: string): Promise; + + /** + * 查询交易历史 + * @param address 钱包地址 + * @param limit 条数限制 (默认 20) + */ + getTransactionHistory?(address: string, limit?: number): Promise; + + /** + * 查询单笔交易详情 + * @param hash 交易哈希 + */ + getTransaction?(hash: string): Promise; + + /** + * 获取当前区块高度 + */ + getBlockHeight?(): Promise; + + // ========== 交易方法 (Transaction Methods) ========== + + /** + * 估算交易费用 + * @param params 转账参数 + */ + estimateFee?(params: TransferParams): Promise; + + /** + * 广播已签名的交易 + * @param signedTx 已签名的交易数据 (hex string) + * @returns 交易哈希 + */ + broadcastTransaction?(signedTx: SignedTransaction): Promise; +} +``` + +## 标准化数据类型 + +为了屏蔽底层链的差异,Driver 层必须将数据转换为统一的内部格式。 + +### 1. Balance +```typescript +interface Balance { + amount: Amount; // 封装了 BigInt, Decimals, Symbol 的值对象 + symbol: string; +} +``` + +### 2. Transaction +这是最复杂的数据结构,需要兼容 UTXO 和 Account 模型。 + +```typescript +interface Transaction { + hash: string; + + /** 发送方地址 (UTXO 模型中可能是输入地址之一) */ + from: string; + + /** 接收方地址 */ + to: string; + + /** 交易时间戳 (ms) */ + timestamp: number; + + /** 交易状态 */ + status: 'confirmed' | 'pending' | 'failed'; + + /** 所在区块号 */ + blockNumber?: bigint; + + /** + * 交易动作类型 + * - transfer: 普通转账 + * - contract: 合约调用 + * - swap: 代币兑换 + * - approve: 授权 + */ + action: Action; + + /** + * 相对于当前钱包的方向 + * - in: 收入 + * - out: 支出 + * - self: 自转 + */ + direction: Direction; + + /** + * 交易涉及的资产列表 + * 一笔交易可能包含多个资产变动 (e.g. Swap ETH -> USDT) + */ + assets: AssetTransfer[]; +} +``` + +## 错误处理 + +Driver 不应抛出原始的 HTTP 错误,而应抛出标准化的 `ChainServiceError`。 + +```typescript +throw new ChainServiceError( + ChainErrorCodes.NETWORK_ERROR, + 'Failed to reach endpoint', + { endpoint: this.endpoint } +); +``` diff --git a/docs/white-book/02-Driver-Ref/02-EVM/01-RPC-Provider.md b/docs/white-book/02-Driver-Ref/02-EVM/01-RPC-Provider.md new file mode 100644 index 000000000..b61c4d68c --- /dev/null +++ b/docs/white-book/02-Driver-Ref/02-EVM/01-RPC-Provider.md @@ -0,0 +1,21 @@ +# 01. EVM RPC Provider + +Code: `src/services/chain-adapter/providers/evm-rpc-provider.ts` + +基于标准 JSON-RPC 规范实现的通用驱动。 + +## 支持能力 +* ✅ `getNativeBalance`: 使用 `eth_getBalance` +* ✅ `getBlockHeight`: 使用 `eth_blockNumber` +* ❌ `getTransactionHistory`: 标准 RPC 不支持高效的历史查询 (需要 Indexer) + +## 典型配置 +```json +{ + "type": "ethereum-rpc", + "endpoint": "https://ethereum-rpc.publicnode.com" +} +``` + +## 实现细节 +该 Provider 主要作为 **Fallback** 使用。当 Etherscan 或 Indexer 不可用时,它能保证用户至少能看到余额,虽然看不到交易记录。 diff --git a/docs/white-book/02-Driver-Ref/02-EVM/02-Etherscan-Provider.md b/docs/white-book/02-Driver-Ref/02-EVM/02-Etherscan-Provider.md new file mode 100644 index 000000000..e738cda2d --- /dev/null +++ b/docs/white-book/02-Driver-Ref/02-EVM/02-Etherscan-Provider.md @@ -0,0 +1,20 @@ +# 02. Etherscan Provider + +Code: `src/services/chain-adapter/providers/etherscan-provider.ts` + +适配 Etherscan V2 API 及其兼容实现 (如 Blockscout)。 + +## 支持能力 +* ✅ `getNativeBalance` +* ✅ `getTransactionHistory`: 聚合 `txlist` (原生) 和 `tokentx` (ERC20) +* ✅ `getTokenBalances`: (部分支持) + +## 聚合逻辑 +Etherscan 将原生交易和代币交易分开返回。驱动层负责将它们聚合: +1. 并行请求 `txlist` 和 `tokentx`。 +2. 按 `hash` 进行分组。 +3. 如果一个 `hash` 同时存在于两者,合并为一个 `Transaction` 对象,并在 `assets` 数组中包含原生资产和代币资产。 +4. 按时间戳降序排列。 + +## API Key 管理 +支持轮询多个 API Key,并自动处理限流 (429) 错误。 diff --git a/docs/white-book/02-Driver-Ref/03-UTXO/01-BTC-Provider.md b/docs/white-book/02-Driver-Ref/03-UTXO/01-BTC-Provider.md new file mode 100644 index 000000000..b0a1c422d --- /dev/null +++ b/docs/white-book/02-Driver-Ref/03-UTXO/01-BTC-Provider.md @@ -0,0 +1,82 @@ +# Bitcoin Provider (UTXO) + +> **Code Source**: [`src/services/chain-adapter/providers/btcwallet-provider.ts`](https://github.com/BioforestChain/KeyApp/blob/main/src/services/chain-adapter/providers/btcwallet-provider.ts) + +## Overview + +The `BtcWalletProvider` implements the `ApiProvider` interface for Bitcoin-like UTXO chains. It relies on a Blockbook-compatible backend API (btcwallet) to fetch balances and transaction history. + +## Architecture + +```mermaid +graph TD + A[ChainProvider] --> B[BtcWalletProvider] + B --> C[Blockbook API] + C --> D[Bitcoin Node] +``` + +## Implementation Details + +### Class Structure + +- **Class**: `BtcWalletProvider` +- **Implements**: `ApiProvider` +- **Location**: [`src/services/chain-adapter/providers/btcwallet-provider.ts`](https://github.com/BioforestChain/KeyApp/blob/main/src/services/chain-adapter/providers/btcwallet-provider.ts) + +### Key Features + +1. **Native Balance**: + - Fetches balance via `/api/v2/address/{address}`. + - Combines `balance` (confirmed) and `unconfirmedBalance`. + - Caching: 60 seconds. + +2. **Transaction History**: + - Fetches history via `/api/v2/address/{address}?details=txs`. + - Parses inputs (`vin`) and outputs (`vout`) to determine direction and net value. + - Supports pagination (limit). + - Caching: 5 minutes. + +### Data Models + +#### Blockbook Response Schemas + +- `BlockbookAddressInfoSchema`: Contains balance and transaction list. +- `BlockbookTxSchema`: Detailed transaction info (inputs, outputs, block height). + +#### Logic: Direction & Value + +The provider calculates the net value change for the user's address to determine the transaction direction: + +- **Incoming (`in`)**: Net value > 0. +- **Outgoing (`out`)**: Net value < 0. +- **Self (`self`)**: Net value = 0 (e.g., consolidation). + +```typescript +const inSum = sumValues(tx.vin, address) +const outSum = sumValues(tx.vout, address) +const net = outSum - inSum +``` + +## Configuration + +- **Type**: `btcwallet-v1` +- **Endpoint**: URL of the Blockbook API (e.g., `https://btc.bioforest.io`). +- **Chain ID**: Passed during initialization to fetch symbol and decimals. + +## Caching Strategy + +| Data | TTL | Invalidation Tags | +|------|-----|-------------------| +| Balance | 60s | `balance:{chainId}:{address}` | +| History | 5m | `txhistory:{chainId}:{address}` | + +## Error Handling + +- Validates API responses using Zod schemas (`BlockbookErrorSchema`, `BlockbookAddressInfoSchema`). +- Throws specific errors for API failures or invalid data. + +## Future Improvements + +- [ ] Support for XPUB derived addresses. +- [ ] Fee estimation via Blockbook. +- [ ] Raw transaction broadcasting. diff --git a/docs/white-book/02-Driver-Ref/03-UTXO/README.md b/docs/white-book/02-Driver-Ref/03-UTXO/README.md new file mode 100644 index 000000000..c4f0c379e --- /dev/null +++ b/docs/white-book/02-Driver-Ref/03-UTXO/README.md @@ -0,0 +1,7 @@ +# UTXO Drivers + +Documentation for Unspent Transaction Output (UTXO) based chain drivers. + +## Providers + +- [Bitcoin (BTC)](./01-BTC-Provider.md) - Using `btcwallet` (Blockbook) backend. diff --git a/docs/white-book/02-Driver-Ref/04-TVM/01-Tron-Provider.md b/docs/white-book/02-Driver-Ref/04-TVM/01-Tron-Provider.md new file mode 100644 index 000000000..123aeef8a --- /dev/null +++ b/docs/white-book/02-Driver-Ref/04-TVM/01-Tron-Provider.md @@ -0,0 +1,93 @@ +# Tron Provider (TVM) + +> **Code Source**: [`src/services/chain-adapter/providers/tronwallet-provider.ts`](https://github.com/BioforestChain/KeyApp/blob/main/src/services/chain-adapter/providers/tronwallet-provider.ts) + +## Overview + +The `TronWalletProvider` implements the `ApiProvider` interface for the Tron blockchain. It interacts with a TronGrid-compatible API to handle native (TRX) and TRC20 token operations. + +## Architecture + +```mermaid +graph TD + A[ChainProvider] --> B[TronWalletProvider] + B --> C[TronGrid API] + C --> D[Tron Node] +``` + +## Implementation Details + +### Class Structure + +- **Class**: `TronWalletProvider` +- **Implements**: `ApiProvider` +- **Location**: [`src/services/chain-adapter/providers/tronwallet-provider.ts`](https://github.com/BioforestChain/KeyApp/blob/main/src/services/chain-adapter/providers/tronwallet-provider.ts) + +### Key Features + +1. **Native Balance**: + - Fetches TRX balance via `/balance`. + - Supports both Base58 and Hex address formats. + - Caching: 60 seconds. + +2. **Transaction History**: + - Aggregates data from two endpoints: + - Native: `/trans/common/history` + - TRC20: `/trans/trc20/history` + - Merges and sorts transactions by timestamp. + - Deduplicates native transactions triggered by TRC20 transfers. + - Caching: 5 minutes. + +### Address Handling + +Tron uses a dual-format address system. The provider includes utilities for conversion: + +- **Base58 (T-address)**: User-friendly format (e.g., `T9yD14Nj9j7...`). +- **Hex**: Internal format used by the API (starts with `41...`). + +Utilities: +- `tronBase58ToHex(address)`: Converts Base58 to Hex. +- `toTronBase58Address(address)`: Ensures Base58 format for UI display. + +### Data Models + +#### Response Schemas + +- `TronNativeTxSchema`: Standard TRX transfers. +- `TronTrc20TxSchema`: Token transfers (USDT, etc.). +- `TronHistorySchema`: Wrapper for API responses. + +#### Logic: TRC20 vs Native + +TRC20 transfers often generate a corresponding native transaction record. The provider intelligently merges them: + +1. Fetches both Native and TRC20 history. +2. Maps TRC20 transfers by Transaction ID (`txID`). +3. Iterates through Native transactions: + - If a matching TRC20 record exists, it takes precedence (richer data). + - If not, it's treated as a standard TRX transfer. +4. Appends any remaining orphan TRC20 transfers. + +## Configuration + +- **Type**: `tronwallet-v1` +- **Endpoint**: URL of the Tron API proxy. +- **Chain ID**: Passed during initialization. + +## Caching Strategy + +| Data | TTL | Invalidation Tags | +|------|-----|-------------------| +| Balance | 60s | `balance:{chainId}:{address}` | +| History | 5m | `txhistory:{chainId}:{address}` | + +## Error Handling + +- **Zod Validation**: Ensures API responses match expected schemas. +- **Upstream Errors**: Throws `Upstream API error` if the API reports failure. + +## Future Improvements + +- [ ] TRC10 token support. +- [ ] Energy/Bandwidth estimation. +- [ ] Smart contract interaction beyond TRC20. diff --git a/docs/white-book/02-Driver-Ref/04-TVM/README.md b/docs/white-book/02-Driver-Ref/04-TVM/README.md new file mode 100644 index 000000000..f13bb3b64 --- /dev/null +++ b/docs/white-book/02-Driver-Ref/04-TVM/README.md @@ -0,0 +1,7 @@ +# TVM Drivers + +Documentation for Tron Virtual Machine (TVM) based chain drivers. + +## Providers + +- [Tron (TRX)](./01-Tron-Provider.md) - Using TronGrid compatible backend. diff --git a/docs/white-book/02-Driver-Ref/README.md b/docs/white-book/02-Driver-Ref/README.md new file mode 100644 index 000000000..92007d6ca --- /dev/null +++ b/docs/white-book/02-Driver-Ref/README.md @@ -0,0 +1,18 @@ +# 📘 Book T2: The Driver Reference (驱动技术参考) + +> **The Hardware Abstraction Layer (HAL) for Blockchains** +> +> 本书定义了 KeyApp 的多链适配器架构,并详细记录了所有已支持链的驱动实现细节。 + +## 📖 目录 + +* [00-Overview.md](./00-Overview.md) - 适配层架构概览 +* **01-Protocol (核心协议)** + * [01-Provider-Interface.md](./01-Protocol/01-Provider-Interface.md) - ApiProvider 接口定义 +* **02-EVM (以太坊生态)** + * [01-RPC-Provider.md](./02-EVM/01-RPC-Provider.md) - JSON-RPC 实现 + * [02-Etherscan-Provider.md](./02-EVM/02-Etherscan-Provider.md) - Etherscan 实现 +* **03-UTXO (比特币生态)** + * [01-Mempool-Provider.md](./03-UTXO/01-Mempool-Provider.md) - Mempool.space 实现 +* **04-TVM (波场生态)** + * [01-Tron-Provider.md](./04-TVM/01-Tron-Provider.md) - TronGrid 实现 diff --git "a/docs/white-book/02-\350\256\276\350\256\241\347\257\207/01-\344\272\244\344\272\222\350\256\276\350\256\241/index.md" "b/docs/white-book/02-\350\256\276\350\256\241\347\257\207/01-\344\272\244\344\272\222\350\256\276\350\256\241/index.md" deleted file mode 100644 index fb1d37b56..000000000 --- "a/docs/white-book/02-\350\256\276\350\256\241\347\257\207/01-\344\272\244\344\272\222\350\256\276\350\256\241/index.md" +++ /dev/null @@ -1,359 +0,0 @@ -# 第四章:交互设计 - -> 定义信息架构、导航流程和页面结构 - ---- - -## 4.1 信息架构 - -### 一级架构 - -``` -BFM Pay -├── 首页 (Home) ← 默认落地页 -│ ├── 钱包卡片 -│ ├── 快捷操作 -│ └── 资产列表 -│ -├── 历史 (History) -│ └── 交易记录列表 -│ -└── 设置 (Settings) - ├── 钱包管理 - ├── 安全设置 - ├── 偏好设置 - └── 关于 -``` - -### 二级页面 - -``` -首页延伸 -├── 发送 (Send) -├── 收款 (Receive) -├── 铸造 (Mint) -├── 代币详情 (Token Detail) -└── 钱包详情 (Wallet Detail) - -设置延伸 -├── 钱包列表 (Wallet List) -├── 创建钱包 (Create Wallet) -├── 导入钱包 (Import Wallet) -├── 地址簿 (Address Book) -├── 语言设置 (Language) -├── 货币设置 (Currency) -├── 链配置 (Chain Config) -└── 应用锁 (App Lock) - -授权相关 -├── 地址授权 (Authorize Address) -└── 签名授权 (Authorize Signature) -``` - ---- - -## 4.2 导航模式 - -### 底部 Tab 导航 - -``` -┌─────────────────────────────────────┐ -│ │ -│ 页面内容区域 │ -│ │ -├─────────────────────────────────────┤ -│ 🏠 📜 ⚙️ │ -│ 首页 历史 设置 │ -└─────────────────────────────────────┘ -``` - -**设计决策**: -- 3 个 Tab,保持简洁 -- 首页为默认选中 -- Tab 图标 + 文字,便于识别 - -### 栈式导航 (Stackflow) - -``` - push -首页 ────────────────────► 发送页面 - pop -首页 ◄──────────────────── 发送页面 -``` - -**特点**: -- 原生 App 体验 -- 支持手势返回 -- 保留页面状态 - -### 底部弹窗 (Bottom Sheet) - -**使用场景**: -- 选择器(钱包、链、代币) -- 确认框(转账确认) -- 操作菜单 - -``` -┌─────────────────────────────────────┐ -│ │ -│ 页面内容 │ -│ │ -├─────────────────────────────────────┤ -│ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ │ ← 拖动条 -│ │ -│ 选择链 │ -│ │ -│ ┌───────────────────────────────┐ │ -│ │ ◉ Ethereum │ │ -│ │ ○ BSC │ │ -│ │ ○ Tron │ │ -│ │ ○ BFMeta │ │ -│ └───────────────────────────────┘ │ -│ │ -└─────────────────────────────────────┘ -``` - ---- - -## 4.3 页面结构模板 - -### 标准页面结构 - -``` -┌─────────────────────────────────────┐ -│ ← 返回 页面标题 [操作按钮] │ ← App Bar -├─────────────────────────────────────┤ -│ │ -│ │ -│ 主要内容区域 │ ← Content -│ │ -│ │ -├─────────────────────────────────────┤ -│ [主要操作按钮] │ ← Footer (可选) -└─────────────────────────────────────┘ -``` - -### 表单页面结构 - -``` -┌─────────────────────────────────────┐ -│ ← 返回 发送 │ -├─────────────────────────────────────┤ -│ │ -│ 标签 │ -│ ┌───────────────────────────────┐ │ -│ │ 输入框 │ │ -│ └───────────────────────────────┘ │ -│ 提示或错误信息 │ -│ │ -│ 标签 │ -│ ┌───────────────────────────────┐ │ -│ │ 输入框 │ │ -│ └───────────────────────────────┘ │ -│ │ -├─────────────────────────────────────┤ -│ ┌───────────────────────────────┐ │ -│ │ 确认发送 │ │ -│ └───────────────────────────────┘ │ -└─────────────────────────────────────┘ -``` - -### 列表页面结构 - -``` -┌─────────────────────────────────────┐ -│ ← 返回 交易历史 │ -├─────────────────────────────────────┤ -│ ┌───────────────────────────────┐ │ -│ │ 🔍 搜索 │ │ -│ └───────────────────────────────┘ │ -├─────────────────────────────────────┤ -│ 今天 │ -│ ├── 交易记录 1 │ -│ ├── 交易记录 2 │ -│ 昨天 │ -│ ├── 交易记录 3 │ -│ └── ... │ -└─────────────────────────────────────┘ -``` - ---- - -## 4.4 核心流程设计 - -### 创建钱包流程 - -``` -┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ -│ 设置钱包锁│───►│生成助记词│───►│验证助记词│───►│ 创建成功 │ -└─────────┘ └─────────┘ └─────────┘ └─────────┘ - │ │ │ - ▼ ▼ ▼ - 图案确认 显示/隐藏 3词验证 -``` - -**步骤指示器**: -``` - ●────────○────────○ - 图案 备份 验证 -``` - -### 转账流程 - -``` -┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ -│ 输入信息 │───►│ 确认详情 │───►│ 验证钱包锁│───►│ 发送成功 │ -└─────────┘ └─────────┘ └─────────┘ └─────────┘ - │ │ │ - ▼ ▼ ▼ - 地址+金额 显示手续费 图案/指纹 -``` - -### DWEB 授权流程 - -``` - DApp 请求 钱包响应 - │ │ - ▼ │ -┌───────────┐ │ -│ getAddress│──────────────┼──► 弹出授权页 -└───────────┘ │ │ - │ ▼ - │ 选择授权范围 - │ │ - │ ▼ - │ 验证钱包锁确认 - │ │ - ◄─────────┘ - 返回地址数据 -``` - ---- - -## 4.5 手势交互 - -### 支持的手势 - -| 手势 | 场景 | 行为 | -|-----|------|------| -| 左滑返回 | 所有次级页面 | 返回上一页 | -| 下拉刷新 | 首页、列表页 | 刷新数据 | -| 下滑关闭 | 底部弹窗 | 关闭弹窗 | -| 长按 | 地址文本 | 复制地址 | -| 双击 | 金额输入框 | 填入最大值 | - -### 手势反馈 - -- 滑动时有视觉位移 -- 刷新时显示加载指示器 -- 操作完成有触觉反馈(DWEB) - ---- - -## 4.6 加载状态设计 - -### 页面加载 - -``` -┌─────────────────────────────────────┐ -│ ← 返回 代币详情 │ -├─────────────────────────────────────┤ -│ │ -│ ┌─────────────┐ │ -│ │ ◠ ◡ ◠ │ │ -│ │ 加载中... │ │ -│ └─────────────┘ │ -│ │ -└─────────────────────────────────────┘ -``` - -### 骨架屏 - -``` -┌─────────────────────────────────────┐ -│ ████████ ████ │ -├─────────────────────────────────────┤ -│ ┌───────────────────────────────┐ │ -│ │ ████████████████████████████ │ │ -│ │ ████████ ░░░░░░░░░░░░░░░░░░ │ │ -│ └───────────────────────────────┘ │ -│ │ -│ ████ ░░░░░░░░░░ ████ ░░░░░░░░░ │ -│ ████ ░░░░░░░░░░ ████ ░░░░░░░░░ │ -└─────────────────────────────────────┘ -``` - -### 操作中状态 - -``` -┌───────────────────────────────────┐ -│ │ -│ ◠ ◡ ◠ │ -│ │ -│ 交易发送中... │ -│ │ -│ 请勿关闭页面 │ -│ │ -└───────────────────────────────────┘ -``` - ---- - -## 4.7 错误状态设计 - -### 空状态 - -``` -┌─────────────────────────────────────┐ -│ │ -│ 📭 │ -│ │ -│ 暂无交易记录 │ -│ │ -│ 完成您的第一笔转账后 │ -│ 交易记录将显示在这里 │ -│ │ -└─────────────────────────────────────┘ -``` - -### 网络错误 - -``` -┌─────────────────────────────────────┐ -│ │ -│ 📡 │ -│ │ -│ 网络连接失败 │ -│ │ -│ 请检查网络后重试 │ -│ │ -│ [重试] │ -│ │ -└─────────────────────────────────────┘ -``` - -### 表单错误 - -``` - 收款地址 - ┌───────────────────────────────┐ - │ 0x71C7656... │ - └───────────────────────────────┘ - ⚠️ 地址格式不正确 -``` - ---- - -## 本章小结 - -- 信息架构分 3 个一级入口,层级清晰 -- 导航采用底部 Tab + 栈式导航 + 底部弹窗 -- 页面结构有标准模板,保持一致性 -- 核心流程设计注重用户引导 -- 加载和错误状态设计完善 - ---- - -## 下一章 - -继续阅读 [第五章:视觉设计](../02-视觉设计/),了解视觉系统和品牌风格。 diff --git "a/docs/white-book/02-\350\256\276\350\256\241\347\257\207/02-\350\247\206\350\247\211\350\256\276\350\256\241/dark-mode.md" "b/docs/white-book/02-\350\256\276\350\256\241\347\257\207/02-\350\247\206\350\247\211\350\256\276\350\256\241/dark-mode.md" deleted file mode 100644 index f872505e7..000000000 --- "a/docs/white-book/02-\350\256\276\350\256\241\347\257\207/02-\350\247\206\350\247\211\350\256\276\350\256\241/dark-mode.md" +++ /dev/null @@ -1,162 +0,0 @@ -# 暗色模式最佳实践 - -> 确保应用在浅色和暗色主题下都有良好的可读性和视觉体验。 - ---- - -## 核心原则 - -### 1. 使用语义化颜色 Token - -**始终优先使用 shadcn/ui 的语义化颜色变量**,它们会自动适配主题: - -```tsx -// ✅ 正确 - 使用语义化颜色 -
-

辅助文字

- -
- -// ❌ 错误 - 硬编码颜色 -
-

辅助文字

-
-``` - -### 2. 配色对必须配套使用 - -每个 shadcn/ui 颜色变量都有对应的 `-foreground` 变体: - -| 背景色 | 前景色 | 使用场景 | -|--------|--------|----------| -| `bg-primary` | `text-primary-foreground` | 主要按钮 | -| `bg-secondary` | `text-secondary-foreground` | 次要按钮 | -| `bg-destructive` | `text-destructive-foreground` | 危险按钮 | -| `bg-muted` | `text-muted-foreground` | 低调区域 | -| `bg-accent` | `text-accent-foreground` | 强调区域 | -| `bg-card` | `text-card-foreground` | 卡片容器 | - -**例外**:`text-muted-foreground` 可以单独用于次要文字,不需要配套 `bg-muted`。 - -### 3. 禁止 `bg-primary text-white` - -```tsx -// ❌ 错误 - text-white 在暗色模式下不会变色 - - -// ✅ 正确 - text-primary-foreground 会自动适配主题 - -``` - -**原因**:在暗色模式下,`--primary` 变亮而 `--primary-foreground` 变暗,保持对比度。`text-white` 始终是白色,在亮色的 `bg-primary` 上可能对比度不足。 - -### 4. 不要将背景色用作文字色 - -```tsx -// ❌ 错误 - secondary 是背景色 -

看不见的文字

- -// ✅ 正确 -

次要文字

-// 或用于按钮 - -``` - -### 5. `bg-muted` 必须指定文字颜色 - -```tsx -// ❌ 错误 - 没有文字颜色,可能继承错误的颜色 -
- 这段文字可能不可见 -
- -// ✅ 正确 -
- 清晰可见 -
-``` - ---- - -## 硬编码颜色规则 - -### 需要 dark: 变体的情况 - -使用硬编码灰色时,**必须**添加暗色变体: - -```tsx -// ✅ 正确 - 有 dark: 变体 -
...
-

...

-
...
- -// ❌ 错误 - 缺少 dark: 变体 -
...
-``` - -### 灰度映射参考 - -| 浅色 | 暗色 | -|------|------| -| gray-50 | gray-900 | -| gray-100 | gray-800 | -| gray-200 | gray-700 | -| gray-300 | gray-600 | -| gray-400 | gray-500 | -| gray-500 | gray-400 | - -### 可接受的例外 - -以下情况**不需要** dark: 变体: - -1. **半透明颜色在渐变/彩色背景上**: - ```tsx - // ✅ OK - 在渐变背景上 -
- 半透明装饰 -

白色文字

-
- ``` - -2. **相机/扫描器界面**: - ```tsx - // ✅ OK - 相机背景 -
-
- ``` - -3. **固定颜色背景上的白字**(如 `bg-green-500`、`bg-red-500`): - ```tsx - // ✅ OK - 固定颜色背景 -
成功
- ``` - -4. **开发工具** (`mock-devtools/`):规则可以放宽 - ---- - -## 自动检查 - -运行主题检查: - -```bash -pnpm theme:check -``` - -检查规则: - -| 规则 | 严重性 | 说明 | -|------|--------|------| -| `no-bg-as-text` | Error | 禁止将背景色用作文字色 | -| `text-white-on-semantic-bg` | Error | 禁止在语义背景色上使用 text-white | -| `orphan-foreground` | Warning | foreground 颜色应有配套背景 | -| `bg-muted-no-text-color` | Warning | bg-muted 需要明确的文字颜色 | -| `missing-dark-variant` | Warning | 硬编码灰色应有 dark: 变体 | - ---- - -## 相关文档 - -- [主题配色系统](./theme-colors.md) - 配色对的详细说明 -- [shadcn/ui 主题文档](https://ui.shadcn.com/docs/theming) diff --git "a/docs/white-book/02-\350\256\276\350\256\241\347\257\207/02-\350\247\206\350\247\211\350\256\276\350\256\241/index.md" "b/docs/white-book/02-\350\256\276\350\256\241\347\257\207/02-\350\247\206\350\247\211\350\256\276\350\256\241/index.md" deleted file mode 100644 index d6e6a545e..000000000 --- "a/docs/white-book/02-\350\256\276\350\256\241\347\257\207/02-\350\247\206\350\247\211\350\256\276\350\256\241/index.md" +++ /dev/null @@ -1,374 +0,0 @@ -# 第五章:视觉设计 - -> 定义视觉系统和品牌风格 - ---- - -## 5.1 设计令牌 (Design Tokens) - -### 颜色系统 - -**品牌色** - -```css -/* 主色 - Bioforest Green */ ---primary: oklch(0.6 0.13 163); ---primary-foreground: oklch(0.98 0.02 166); - -/* 深色模式 */ -.dark { - --primary: oklch(0.7 0.15 162); - --primary-foreground: oklch(0.26 0.05 173); -} -``` - -**语义色** - -| 用途 | 浅色模式 | 深色模式 | 使用场景 | -|-----|---------|---------|---------| -| 成功 | `green-500` | `green-400` | 交易成功、验证通过 | -| 警告 | `yellow-500` | `yellow-400` | 提醒、注意事项 | -| 错误 | `red-500` | `red-400` | 错误提示、危险操作 | -| 信息 | `blue-500` | `blue-400` | 一般提示 | - -**中性色** - -```css ---background: oklch(1 0 0); /* 页面背景 */ ---foreground: oklch(0.145 0 0); /* 主要文字 */ ---muted: oklch(0.97 0 0); /* 次级背景 */ ---muted-foreground: oklch(0.556 0 0); /* 次级文字 */ ---border: oklch(0.922 0 0); /* 边框 */ -``` - -### 字体系统 - -**字体家族** - -| 字体 | CSS 类 | 用途 | -|-----|--------|------| -| DM Sans | `font-sans` | UI 文本、按钮、标签(默认) | -| DM Mono | `font-mono` | 地址、金额、代码 | -| DM Serif Display | `font-serif` | 协议、提示、正式内容 | - -**字体大小** - -| 级别 | 大小 | 行高 | 使用场景 | -|-----|------|------|---------| -| xs | 12px | 16px | 辅助信息、时间戳 | -| sm | 14px | 20px | 次要文字、标签 | -| base | 16px | 24px | 正文、按钮文字 | -| lg | 18px | 28px | 小标题 | -| xl | 20px | 28px | 页面标题 | -| 2xl | 24px | 32px | 金额显示 | -| 3xl | 30px | 36px | 大额数字 | - -### 间距系统 - -```css -/* 基于 4px 网格 */ ---spacing-1: 4px; ---spacing-2: 8px; ---spacing-3: 12px; ---spacing-4: 16px; ---spacing-5: 20px; ---spacing-6: 24px; ---spacing-8: 32px; ---spacing-10: 40px; ---spacing-12: 48px; -``` - -**使用规范**: -- 组件内部间距:4px, 8px -- 组件之间间距:16px, 24px -- 区块之间间距:32px, 48px - -### 圆角系统 - -| 用途 | 大小 | 使用场景 | -|-----|------|---------| -| sm | 4px | 小按钮、标签 | -| md | 8px | 输入框、卡片 | -| lg | 12px | 大卡片、弹窗 | -| xl | 16px | 底部弹窗 | -| full | 9999px | 圆形按钮、头像 | - ---- - -## 5.2 组件样式 - -### 按钮 - -**变体** - -``` -┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ -│ Primary │ │ Secondary │ │ Outline │ -│ 主要操作 │ │ 次要操作 │ │ 边框按钮 │ -└─────────────────┘ └─────────────────┘ └─────────────────┘ - -┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ -│ Ghost │ │ Destructive │ │ Link │ -│ 幽灵按钮 │ │ 危险操作 │ │ 链接按钮 │ -└─────────────────┘ └─────────────────┘ └─────────────────┘ -``` - -**尺寸** - -| 尺寸 | 高度 | 内边距 | 字体大小 | -|-----|------|-------|---------| -| sm | 32px | 12px | 14px | -| md | 40px | 16px | 14px | -| lg | 48px | 20px | 16px | - -**渐变按钮** - -```css -.gradient-blue { - background: linear-gradient(180deg, #6de7fe 0%, #44b5f7 100%); -} -.gradient-purple { - background: linear-gradient(180deg, #a694f8 0%, #8970ff 100%); -} -.gradient-red { - background: linear-gradient(180deg, #f77fa2 0%, #ea4879 100%); -} -``` - -### 卡片 - -**钱包卡片** - -``` -┌─────────────────────────────────────┐ -│ │ -│ ┌──┐ 钱包名称 │ -│ │🔷│ 0x71C7...976F [复制] │ -│ └──┘ │ -│ │ -│ ═══════════════════════════════ │ -│ │ -│ 转账 铸造 收款 │ -│ │ -└─────────────────────────────────────┘ -``` - -样式特点: -- 圆角 16px -- 阴影 `shadow-md` -- 背景渐变或纯色 - -**资产卡片** - -``` -┌─────────────────────────────────────┐ -│ ┌──┐ │ -│ │🔶│ ETH 10.5 │ -│ └──┘ Ethereum $2,100│ -└─────────────────────────────────────┘ -``` - -### 输入框 - -**默认状态** - -``` -┌───────────────────────────────────┐ -│ 请输入地址 │ -└───────────────────────────────────┘ -``` - -**聚焦状态** - -``` -┌───────────────────────────────────┐ -│ 0x71C7656EC7ab88b098defB751B... │ ← 边框高亮 -└───────────────────────────────────┘ -``` - -**错误状态** - -``` -┌───────────────────────────────────┐ -│ invalid_address │ ← 红色边框 -└───────────────────────────────────┘ - ⚠️ 地址格式不正确 ← 错误提示 -``` - -### 底部弹窗 - -``` -┌─────────────────────────────────────┐ -│ │ -│ (页面内容变暗) │ -│ │ -├─────────────────────────────────────┤ -│ ━━━━━━━━━━━ │ ← 拖动指示条 -│ │ -│ 选择链 │ ← 标题 -│ │ -│ ○ Ethereum │ -│ ● BSC │ ← 当前选中 -│ ○ Tron │ -│ ○ BFMeta │ -│ │ -│ ┌───────────────────────────────┐ │ -│ │ 确定 │ │ ← 操作按钮(可选) -│ └───────────────────────────────┘ │ -│ │ -└─────────────────────────────────────┘ -``` - ---- - -## 5.3 图标系统 - -### 图标来源 - -使用 [Tabler Icons](https://tabler.io/icons),React 组件:`@tabler/icons-react` - -### 常用图标 - -| 功能 | 图标 | 名称 | -|-----|------|------| -| 返回 | ← | `IconArrowLeft` | -| 复制 | 📋 | `IconCopy` | -| 扫码 | 📷 | `IconScan` | -| 设置 | ⚙️ | `IconSettings` | -| 钱包 | 💼 | `IconWallet` | -| 发送 | ↗️ | `IconSend` | -| 接收 | ↙️ | `IconDownload` | -| 锁定 | 🔒 | `IconLock` | -| 警告 | ⚠️ | `IconAlertTriangle` | -| 成功 | ✅ | `IconCheck` | - -### 图标尺寸 - -| 场景 | 尺寸 | 使用 | -|-----|------|------| -| 按钮内图标 | 16px | 小型按钮 | -| 列表项图标 | 20px | 列表左侧图标 | -| 导航图标 | 24px | Tab Bar | -| 状态图标 | 48px | 空状态、结果页 | - ---- - -## 5.4 深色模式 - -### 颜色映射 - -| 元素 | 浅色模式 | 深色模式 | -|-----|---------|---------| -| 背景 | `#ffffff` | `#0a0a0a` | -| 前景 | `#0a0a0a` | `#fafafa` | -| 卡片 | `#ffffff` | `#171717` | -| 边框 | `#e5e5e5` | `#262626` | -| 次级文字 | `#737373` | `#a3a3a3` | - -### 实现方式 - -```css -@custom-variant dark (&:is(.dark *)); - -:root { - --background: oklch(1 0 0); - --foreground: oklch(0.145 0 0); -} - -.dark { - --background: oklch(0.145 0 0); - --foreground: oklch(0.985 0 0); -} -``` - -### 切换逻辑 - -1. 默认跟随系统 -2. 用户可手动切换 -3. 存储用户偏好 - ---- - -## 5.5 响应式设计 - -### 断点定义 - -| 断点 | 宽度 | 设备 | -|-----|------|------| -| xs | < 360px | 小型手机 | -| sm | 360-414px | 标准手机 | -| md | 414-600px | 大屏手机 | -| lg | 600-840px | 折叠屏展开 | -| xl | > 840px | 平板 | - -### 容器查询 - -组件使用容器查询实现自适应: - -```tsx -
-
320px:水平布局 - "@md:p-6" // >448px:更大内边距 - )}> - {/* 内容 */} -
-
-``` - ---- - -## 5.6 动画规范 - -### 时长 - -| 类型 | 时长 | 使用场景 | -|-----|------|---------| -| 快速 | 150ms | hover、focus | -| 标准 | 200ms | 展开、收起 | -| 中等 | 300ms | 页面过渡 | -| 慢速 | 500ms | 复杂动画 | - -### 缓动函数 - -```css ---ease-out: cubic-bezier(0, 0, 0.2, 1); ---ease-in: cubic-bezier(0.4, 0, 1, 1); ---ease-in-out: cubic-bezier(0.4, 0, 0.2, 1); -``` - -### 常用动画 - -**淡入** -```css -@keyframes fade-in { - from { opacity: 0; } - to { opacity: 1; } -} -``` - -**滑入** -```css -@keyframes slide-in-from-bottom { - from { transform: translateY(100%); } - to { transform: translateY(0); } -} -``` - ---- - -## 本章小结 - -- 设计令牌定义了颜色、字体、间距、圆角 -- 组件样式包括按钮、卡片、输入框、弹窗 -- 图标使用 Tabler Icons -- 支持深色模式 -- 响应式设计使用容器查询 -- 动画规范保证一致的交互体验 - ---- - -## 下一章 - -继续阅读 [第六章:设计原则](../03-设计原则/),了解设计决策的指导原则。 diff --git "a/docs/white-book/02-\350\256\276\350\256\241\347\257\207/03-\350\256\276\350\256\241\345\216\237\345\210\231/index.md" "b/docs/white-book/02-\350\256\276\350\256\241\347\257\207/03-\350\256\276\350\256\241\345\216\237\345\210\231/index.md" deleted file mode 100644 index 259092b32..000000000 --- "a/docs/white-book/02-\350\256\276\350\256\241\347\257\207/03-\350\256\276\350\256\241\345\216\237\345\210\231/index.md" +++ /dev/null @@ -1,302 +0,0 @@ -# 第六章:设计原则 - -> 定义设计决策的指导原则 - ---- - -## 6.1 信任优先 - -钱包是用户管理资产的工具,信任是最重要的基础。 - -### 透明 - -**原则**:所有操作都清晰展示细节 - -| 场景 | 透明设计 | -|-----|---------| -| 转账 | 显示完整地址、金额、手续费 | -| 授权 | 显示 DApp 来源、请求权限 | -| 签名 | 显示签名内容(消息/交易) | - -**示例**: - -``` -转账确认 - -发送 0x71C7656EC7ab88b098defB751B7401B5f6d8976F -接收 0xabcd...1234 - -金额 1.5 ETH -手续费 0.002 ETH (~$4.50) -───────────────────────────── -总计 1.502 ETH - -[取消] [确认发送] -``` - -### 可控 - -**原则**:用户始终可以取消、返回、重试 - -| 场景 | 可控设计 | -|-----|---------| -| 多步骤流程 | 每步都可返回上一步 | -| 弹窗操作 | 可点击外部或关闭按钮关闭 | -| 长时操作 | 显示进度,可取消 | - -### 安全提示 - -**原则**:在敏感操作前给予警告 - -**警告级别**: - -| 级别 | 样式 | 场景 | -|-----|------|------| -| 提示 | 蓝色 | 一般信息 | -| 警告 | 黄色 | 需要注意 | -| 危险 | 红色 | 高风险操作 | - -**示例**: - -``` -⚠️ 警告 - -助记词是恢复钱包的唯一方式。 -一旦丢失,资产将无法找回。 - -请确保: -• 周围没有其他人 -• 不要截图保存 -• 用纸笔抄写备份 - -[取消] [我已了解,继续] -``` - ---- - -## 6.2 渐进式复杂度 - -### 新手友好 - -**原则**:核心功能零学习成本 - -**实现方式**: -- 首页直接展示余额和快捷操作 -- 转账流程最少只需 2 步 -- 收款一键展示二维码 - -### 进阶可选 - -**原则**:高级功能不干扰基础体验 - -**实现方式**: -- 质押、DApp 在首页不强调 -- 高级设置放在二级菜单 -- 功能按需加载 - -### 专家高效 - -**原则**:提供快捷操作给熟练用户 - -**实现方式**: -- 地址簿快速选择 -- 最近转账记录 -- 手势操作支持 - ---- - -## 6.3 错误预防 - -### 格式验证 - -**原则**:实时校验输入格式 - -``` -收款地址 -┌───────────────────────────────┐ -│ 0x71C7656EC7ab88b098defB751B │ ✓ 格式正确 -└───────────────────────────────┘ - -收款地址 -┌───────────────────────────────┐ -│ invalid_address │ ✗ -└───────────────────────────────┘ - ⚠️ 地址格式不正确 -``` - -### 二次确认 - -**原则**:大额/异常操作需确认 - -**需要二次确认的场景**: -- 转账金额超过阈值 -- 删除钱包 -- 导出私钥 -- 首次向新地址转账 - -### 可恢复 - -**原则**:提供明确的补救路径 - -| 问题 | 补救路径 | -|-----|---------| -| 忘记图案 | 通过助记词重置 | -| 交易失败 | 显示原因,提供重试 | -| 操作中断 | 保存草稿,下次继续 | - ---- - -## 6.4 一致性体验 - -### 跨链统一 - -**原则**:不同链的操作流程保持一致 - -| 操作 | ETH | TRX | BFMeta | -|-----|-----|-----|--------| -| 转账 | 相同流程 | 相同流程 | 相同流程 | -| 手续费 | "网络费用" | "网络费用" | "网络费用" | -| 地址格式 | 自动识别 | 自动识别 | 自动识别 | - -### 视觉统一 - -**原则**:相同功能使用相同的图标和位置 - -| 功能 | 图标 | 位置 | -|-----|------|------| -| 返回 | ← | 左上角 | -| 更多 | ⋯ | 右上角 | -| 复制 | 📋 | 地址后方 | -| 扫码 | 📷 | 输入框内右侧 | - -### 语言统一 - -**原则**:用通俗语言解释技术概念 - -| 技术术语 | 用户友好表述 | -|---------|-------------| -| Gas Fee | 网络费用 | -| Nonce | (隐藏,不展示) | -| Block Confirmation | 交易确认中 | -| Private Key | 私钥 | -| Mnemonic | 助记词 | - ---- - -## 6.5 自适应布局 - -### 设计目标 - -- **一份代码**:无需为不同设备开发独立版本 -- **内容优先**:根据可用空间展示合适的信息量 -- **交互一致**:核心操作在各设备上保持相同 - -### 布局策略 - -| 设备 | 宽度 | 布局特点 | -|-----|------|---------| -| 小型手机 | < 360px | 紧凑单列,核心信息优先 | -| 标准手机 | 360-414px | 标准单列,完整功能 | -| 大屏手机 | 414-600px | 宽松单列,显示更多细节 | -| 折叠屏 | 600-840px | 卡片并排 | -| 平板 | > 840px | 分栏布局 | - -### 典型场景 - -**钱包卡片** -- 窄屏:垂直排列信息 -- 宽屏:水平展开,显示更多 - -**转账确认** -- 窄屏:全屏弹窗 -- 宽屏:居中卡片式弹窗 - -**设置页面** -- 窄屏:单列列表 -- 宽屏:分组卡片布局 - ---- - -## 6.6 无障碍设计 - -### 色彩对比度 - -- 正文与背景对比度 ≥ 4.5:1 -- 大文字与背景对比度 ≥ 3:1 -- 不仅依赖颜色传达信息 - -### 触控目标 - -- 最小触控区域 44x44px -- 相邻可点击元素间距 ≥ 8px - -### 屏幕阅读器 - -- 所有交互元素有 `aria-label` -- 图标按钮有文字说明 -- 表单字段关联 label - -### 键盘导航 - -- Tab 顺序合理 -- 焦点状态可见 -- 支持 Enter/Space 激活 - ---- - -## 6.7 设计检查清单 - -开发新功能时,检查以下项目: - -### 信任 - -- [ ] 是否清晰展示了所有关键信息? -- [ ] 用户是否可以随时取消/返回? -- [ ] 敏感操作是否有适当警告? - -### 复杂度 - -- [ ] 新手用户能否轻松完成? -- [ ] 高级功能是否不干扰基础体验? -- [ ] 是否提供了快捷操作? - -### 错误预防 - -- [ ] 是否有实时输入验证? -- [ ] 是否有必要的二次确认? -- [ ] 出错后是否有补救路径? - -### 一致性 - -- [ ] 是否与其他类似功能保持一致? -- [ ] 是否使用了正确的图标和位置? -- [ ] 是否使用了用户友好的语言? - -### 响应式 - -- [ ] 是否在不同屏幕尺寸下正常显示? -- [ ] 是否使用了容器查询? -- [ ] 核心功能是否始终可用? - -### 无障碍 - -- [ ] 色彩对比度是否足够? -- [ ] 触控目标是否足够大? -- [ ] 是否支持屏幕阅读器? - ---- - -## 本章小结 - -- 信任优先:透明、可控、安全提示 -- 渐进复杂度:新手友好、进阶可选、专家高效 -- 错误预防:格式验证、二次确认、可恢复 -- 一致性:跨链统一、视觉统一、语言统一 -- 自适应:一份代码适配多种设备 -- 无障碍:色彩、触控、阅读器、键盘 - ---- - -## 下一篇 - -完成设计篇后,继续阅读 [第三篇:架构篇](../../03-架构篇/),了解技术实现方案。 diff --git "a/docs/white-book/02-\350\256\276\350\256\241\347\257\207/index.md" "b/docs/white-book/02-\350\256\276\350\256\241\347\257\207/index.md" deleted file mode 100644 index b35dc98e5..000000000 --- "a/docs/white-book/02-\350\256\276\350\256\241\347\257\207/index.md" +++ /dev/null @@ -1,56 +0,0 @@ -# 第二篇:设计篇 - -> 定义产品的「长什么样」 - ---- - -## 概述 - -设计篇回答三个核心问题: - -1. **用户如何操作?** → [交互设计](./01-交互设计/) -2. **界面什么风格?** → [视觉设计](./02-视觉设计/) -3. **设计遵循什么原则?** → [设计原则](./03-设计原则/) - ---- - -## 章节导航 - -### [第四章:交互设计](./01-交互设计/) - -定义信息架构、导航流程和页面结构。 - -**要点**: -- 底部 Tab 导航:首页、历史、设置 -- 栈式导航:原生 App 体验 -- 底部弹窗:选择器、确认框 - -### [第五章:视觉设计](./02-视觉设计/) - -定义视觉系统和品牌风格。 - -**要点**: -- 设计令牌:颜色、字体、间距 -- 组件样式:按钮、卡片、表单 -- 深色模式支持 - -### [第六章:设计原则](./03-设计原则/) - -定义设计决策的指导原则。 - -**要点**: -- 信任优先:透明、可控、安全提示 -- 渐进复杂度:新手友好、进阶可选 -- 响应式设计:适配多种屏幕 - ---- - -## 本篇来源 - -本篇内容来源于 `PDR.md` 的设计原则章节和 `TDD.md` 的 UI 组件规范。 - ---- - -## 下一篇 - -完成设计篇后,继续阅读 [第三篇:架构篇](../03-架构篇/),了解技术实现方案。 diff --git a/docs/white-book/03-UI-Ref/00-Overview.md b/docs/white-book/03-UI-Ref/00-Overview.md new file mode 100644 index 000000000..908a7a324 --- /dev/null +++ b/docs/white-book/03-UI-Ref/00-Overview.md @@ -0,0 +1,18 @@ +# 00. 设计系统概览 (Overview) + +Code: `src/styles/globals.css`, `tailwind.config.js` + +KeyApp 使用了一套基于 **Tailwind CSS 4** 和 **CSS Variables** 的动态主题系统。 + +## 核心原则 + +1. **Semantic Naming**: 不使用具体的颜色名 (e.g., `blue-500`),而是使用语义名 (e.g., `primary`, `destructive`)。 +2. **Dark Mode First**: 设计系统原生支持深色模式。所有颜色 Token 都有对应的 `dark:` 变体(通过 CSS 变量自动处理)。 +3. **Mobile First**: 默认样式针对移动端,使用 `@md:` 等前缀适配桌面端。 + +## 技术栈 + +* **Styling**: Tailwind CSS +* **Component Base**: Radix UI (Headless) +* **Component Lib**: shadcn/ui (Customized) +* **Icons**: Tabler Icons diff --git a/docs/white-book/03-UI-Ref/01-Foundation/00-Index.md b/docs/white-book/03-UI-Ref/01-Foundation/00-Index.md new file mode 100644 index 000000000..91e633db9 --- /dev/null +++ b/docs/white-book/03-UI-Ref/01-Foundation/00-Index.md @@ -0,0 +1,55 @@ +# 设计基础 (Foundation) + +> 设计系统的基础层:原则、颜色、交互规范 + +--- + +## 文档列表 + +| 文档 | 说明 | +|------|------| +| [01-Colors](./01-Colors.md) | 基础颜色定义 | +| [02-Design-Principles](./02-Design-Principles.md) | 设计原则(信任优先、渐进复杂度) | +| [03-Theme-Colors](./03-Theme-Colors.md) | 主题配色系统(配色对、钱包主题色) | +| [04-Interaction-Specs](./04-Interaction-Specs.md) | 交互规范(触摸、手势、动效、可访问性) | + +--- + +## 快速参考 + +### 行为约束级别 + +| 级别 | 含义 | 后果 | +|------|------|------| +| **MUST** | 必须遵守 | 违反导致功能缺陷或安全问题 | +| **SHOULD** | 建议遵守 | 不遵守会降低用户体验 | +| **MAY** | 可选实现 | 增强体验但非必需 | +| **MUST NOT** | 禁止行为 | 违反导致严重问题 | + +### 设计核心原则 + +1. **信任优先** - 透明、可控、安全提示 +2. **渐进复杂度** - 新手友好,进阶可选 +3. **响应式设计** - 移动优先,360px 为设计基准 + +### 配色对规则 + +```tsx +// ✅ 配套使用 + + Subtitle + + +// ❌ 错误:硬编码 +
+ +
+``` diff --git a/docs/white-book/03-UI-Ref/01-Foundation/02-Design-Principles.md b/docs/white-book/03-UI-Ref/01-Foundation/02-Design-Principles.md new file mode 100644 index 000000000..314eea993 --- /dev/null +++ b/docs/white-book/03-UI-Ref/01-Foundation/02-Design-Principles.md @@ -0,0 +1,176 @@ +# 设计原则 + +> 源码: 全局设计决策指导原则 + +--- + +## 核心原则 + +### 1. 信任优先 (Trust First) + +钱包是用户管理资产的工具,**信任是最重要的基础**。 + +#### 透明 (Transparency) + +**原则**: 所有操作都清晰展示细节 + +| 场景 | 透明设计 | MUST/SHOULD | +|------|----------|-------------| +| 转账 | 显示完整地址、金额、手续费 | MUST | +| 授权 | 显示 DApp 来源、请求权限 | MUST | +| 签名 | 显示签名内容(消息/交易) | MUST | +| 错误 | 显示具体原因,不用模糊措辞 | SHOULD | + +#### 可控 (Control) + +**原则**: 用户始终掌握主动权 + +| 场景 | 可控设计 | MUST/SHOULD | +|------|----------|-------------| +| 私钥 | 永不上传服务器 | MUST | +| 授权 | 可随时撤销 | MUST | +| 操作 | 明确的取消路径 | MUST | +| 设置 | 可调整所有偏好 | SHOULD | + +#### 安全提示 (Security Awareness) + +**原则**: 主动提醒潜在风险 + +| 场景 | 安全提示 | MUST/SHOULD | +|------|----------|-------------| +| 陌生地址 | 首次转账警告 | SHOULD | +| 大额交易 | 二次确认 | MUST | +| 敏感操作 | 生物识别/密码确认 | MUST | +| 异常行为 | 主动告警 | SHOULD | + +--- + +### 2. 渐进复杂度 (Progressive Complexity) + +**原则**: 新手友好,进阶可选 + +``` +入门路径 进阶路径 +──────── ──────── +创建钱包 (30秒) 导入钱包 (助记词/私钥) + │ │ + ▼ ▼ +查看余额 (一键) 高级设置 (Gas/Nonce) + │ │ + ▼ ▼ +简单转账 (扫码/地址簿) 批量操作 (多签/合约) +``` + +#### 默认值策略 + +| 设置项 | 默认值 | 理由 | +|--------|--------|------| +| Gas 费 | 系统推荐 | 新手无需理解 | +| 地址格式 | 自动检测 | 减少选择负担 | +| 网络 | 主网 | 安全优先 | +| 语言 | 系统语言 | 符合预期 | + +#### 进阶入口 + +- **MUST** 进阶功能隐藏在二级菜单 +- **MUST** 进阶设置有默认值 +- **SHOULD** 提供进阶功能的简要说明 +- **MAY** 提供进阶教程链接 + +--- + +### 3. 响应式设计 (Responsive Design) + +**原则**: 适配多种屏幕,优先移动端 + +#### 断点定义 + +| 断点 | 宽度范围 | 典型设备 | 优先级 | +|------|----------|----------|--------| +| xs | < 360px | 小屏手机 | 兼容 | +| sm | 360-428px | 普通手机 | **设计基准** | +| md | 428-768px | 大屏手机/小平板 | 适配 | +| lg | ≥ 768px | 平板 | 可选 | + +#### 适配策略 + +```typescript +// 布局适配 +const layoutStrategy = { + xs: { columns: 1, padding: 12 }, + sm: { columns: 1, padding: 16 }, // 设计基准 + md: { columns: 2, padding: 20 }, + lg: { columns: 3, padding: 24 }, +} + +// 字体适配 +const fontStrategy = { + title: 'clamp(1.25rem, 4vw, 1.5rem)', + body: '1rem', + caption: '0.875rem', +} +``` + +--- + +## 行为约束规范 + +### MUST (必须) + +违反将导致功能缺陷或安全问题: + +- 显示完整交易信息(地址、金额、费用) +- 敏感操作需要认证确认 +- 私钥永不离开设备 +- 提供明确的取消路径 +- 错误状态有恢复指引 + +### SHOULD (建议) + +不遵守会降低用户体验: + +- 提供操作反馈(视觉/触觉) +- 支持减少动效模式 +- 显示操作进度 +- 提供撤销机会(在安全范围内) +- 记住用户偏好 + +### MAY (可选) + +增强体验但非必需: + +- 高级自定义选项 +- 快捷操作手势 +- 数据导出功能 +- 主题个性化 + +--- + +## 设计决策清单 + +在设计新功能时,检查以下问题: + +```markdown +## 信任检查 +- [ ] 操作是否透明?用户能否理解发生了什么? +- [ ] 用户是否可以取消或撤销? +- [ ] 是否有必要的安全提示? + +## 复杂度检查 +- [ ] 新手能否在 30 秒内完成核心路径? +- [ ] 进阶选项是否隐藏在二级入口? +- [ ] 默认值是否合理? + +## 响应式检查 +- [ ] 在 360px 宽度下是否正常显示? +- [ ] 触摸目标是否足够大(44×44px)? +- [ ] 是否支持系统减少动效设置? +``` + +--- + +## 相关文档 + +- [主题配色系统](./03-Theme-Colors.md) +- [交互规范](./04-Interaction-Specs.md) +- [组件库](../05-Components/00-Index.md) diff --git "a/docs/white-book/02-\350\256\276\350\256\241\347\257\207/02-\350\247\206\350\247\211\350\256\276\350\256\241/theme-colors.md" b/docs/white-book/03-UI-Ref/01-Foundation/03-Theme-Colors.md similarity index 50% rename from "docs/white-book/02-\350\256\276\350\256\241\347\257\207/02-\350\247\206\350\247\211\350\256\276\350\256\241/theme-colors.md" rename to docs/white-book/03-UI-Ref/01-Foundation/03-Theme-Colors.md index f9239d3ae..8520d9f9e 100644 --- "a/docs/white-book/02-\350\256\276\350\256\241\347\257\207/02-\350\247\206\350\247\211\350\256\276\350\256\241/theme-colors.md" +++ b/docs/white-book/03-UI-Ref/01-Foundation/03-Theme-Colors.md @@ -1,6 +1,6 @@ # 主题配色系统 -> shadcn/ui 配色对的正确使用方式 +> 源码: [`src/styles/`](https://github.com/BioforestChain/KeyApp/blob/main/src/styles/), [`tailwind.config.ts`](https://github.com/BioforestChain/KeyApp/blob/main/tailwind.config.ts) --- @@ -13,17 +13,14 @@ shadcn/ui 使用**配色对**设计,每个颜色变量都有对应的 `xxx-for | `--xxx` | **背景色** | | `--xxx-foreground` | **在该背景上的前景色/文字色** | -**关键规则**:它们必须**配套使用**。 +**关键规则**: 它们 **MUST** 配套使用。 --- -## 配色对一览 +## 配色对使用指南 ``` ┌─────────────────────────────────────────────────────────────┐ -│ 配色对使用指南 │ -├─────────────────────────────────────────────────────────────┤ -│ │ │ primary ──────────────────────► 主要操作 │ │ ┌─────────────────────────────────────┐ │ │ │ bg-primary text-primary-foreground │ 主要按钮 │ @@ -52,104 +49,43 @@ shadcn/ui 使用**配色对**设计,每个颜色变量都有对应的 `xxx-for │ ┌─────────────────────────────────────┐ │ │ │ text-destructive │ 错误文字 │ │ └─────────────────────────────────────┘ │ -│ │ -│ accent ──────────────────────► 强调/高亮 │ -│ ┌─────────────────────────────────────┐ │ -│ │ bg-accent text-accent-foreground │ 悬停/选中状态 │ -│ └─────────────────────────────────────┘ │ -│ │ └─────────────────────────────────────────────────────────────┘ ``` --- -## 正确用法示例 - -### ✅ 主要按钮 - -```tsx - -``` - -### ✅ 次要按钮 - -```tsx - -``` - -### ✅ 次要/辅助文字 - -```tsx -

- 这是辅助说明文字 -

-``` - -### ✅ 强调文字/链接 +## 行为约束 -```tsx - - 查看详情 - -``` - -### ✅ 错误提示 +### MUST (必须) ```tsx -

- 图案不正确 -

-``` - -### ✅ 成功/确认状态 +// ✅ 配套使用 + -```tsx - -交易成功 +// ❌ 禁止单独使用 foreground +
看不清
``` ---- - -## 常见错误 - -### ❌ 错误:text-secondary 当文字用 +### MUST NOT (禁止) ```tsx -// ❌ 错误!secondary 是背景色,在亮色主题下几乎不可见 -

这段文字看不见

+// ❌ 禁止:text-secondary 当文字色(它是背景色!) +

看不见

-// ✅ 正确 -

次要文字

+// ❌ 禁止:secondary 表示成功状态 + ``` -### ❌ 错误:用 secondary 表示成功状态 +### SHOULD (建议) ```tsx -// ❌ 错误!secondary 是中性灰色,不代表成功 - +// ✅ 次要文字用 muted-foreground +

辅助说明文字

-// ✅ 正确 +// ✅ 成功状态用 green ``` -### ❌ 错误:单独使用 foreground 类 - -```tsx -// ❌ 错误!foreground 颜色是为特定背景设计的 -
- 这个白色文字在默认背景上看不清 -
- -// ✅ 正确:配套使用 -
- 这样才对 -
-``` - --- ## 语义色对照表 @@ -168,7 +104,7 @@ shadcn/ui 使用**配色对**设计,每个颜色变量都有对应的 `xxx-for --- -## 当前主题变量值 +## 主题变量值 ### 亮色主题 @@ -177,14 +113,14 @@ shadcn/ui 使用**配色对**设计,每个颜色变量都有对应的 `xxx-for --primary: oklch(0.59 0.26 323); /* 品牌紫色 */ --primary-foreground: oklch(1 0 0); /* 白色 */ - --secondary: oklch(0.967 0.001 286.375); /* 极浅灰(背景) */ - --secondary-foreground: oklch(0.21 0.006 285.885); /* 深色文字 */ + --secondary: oklch(0.967 0.001 286.375); /* 极浅灰 */ + --secondary-foreground: oklch(0.21 0.006 285.885); - --muted: oklch(0.967 0.001 286.375); /* 极浅灰(同 secondary) */ - --muted-foreground: oklch(0.552 0.016 285.938); /* 中灰文字 */ + --muted: oklch(0.967 0.001 286.375); /* 极浅灰 */ + --muted-foreground: oklch(0.552 0.016 285.938); --destructive: oklch(0.577 0.245 27.325); /* 红色 */ - --destructive-foreground: oklch(1 0 0); /* 白色 */ + --destructive-foreground: oklch(1 0 0); } ``` @@ -192,56 +128,30 @@ shadcn/ui 使用**配色对**设计,每个颜色变量都有对应的 `xxx-for ```css .dark { - --primary: oklch(0.67 0.26 322); /* 亮一点的品牌紫色 */ - --primary-foreground: oklch(0.141 0.005 285.823); /* 深色 */ + --primary: oklch(0.67 0.26 322); /* 亮品牌紫 */ + --primary-foreground: oklch(0.141 0.005 285.823); - --secondary: oklch(0.274 0.006 286.033); /* 深灰(背景) */ - --secondary-foreground: oklch(0.985 0 0); /* 白色文字 */ + --secondary: oklch(0.274 0.006 286.033); /* 深灰 */ + --secondary-foreground: oklch(0.985 0 0); - --muted: oklch(0.274 0.006 286.033); /* 深灰(同 secondary) */ - --muted-foreground: oklch(0.705 0.015 286.067); /* 浅灰文字 */ + --muted: oklch(0.274 0.006 286.033); + --muted-foreground: oklch(0.705 0.015 286.067); - --destructive: oklch(0.704 0.191 22.216); /* 亮红色 */ - --destructive-foreground: oklch(1 0 0); /* 白色 */ + --destructive: oklch(0.704 0.191 22.216); /* 亮红 */ + --destructive-foreground: oklch(1 0 0); } ``` --- -## 快速参考 - -| 我想要... | 使用 | -|-----------|------| -| 主要按钮 | `bg-primary text-primary-foreground` | -| 次要按钮 | `bg-secondary text-secondary-foreground` | -| 危险按钮 | `bg-destructive text-destructive-foreground` | -| 强调链接 | `text-primary` | -| 辅助文字 | `text-muted-foreground` | -| 错误文字 | `text-destructive` | -| 成功图标 | `text-green-500` | -| 低调背景 | `bg-muted` | -| 卡片背景 | `bg-card text-card-foreground` | - ---- - -## 本节小结 - -1. **配色对必须配套使用**:`bg-xxx` 搭配 `text-xxx-foreground` -2. **不要单独使用 `text-secondary`**:它是背景色,不是文字色 -3. **次要文字用 `text-muted-foreground`**:这才是设计给辅助文字的颜色 -4. **成功/确认状态用 `text-green-500`**:不要用 secondary -5. **理解亮/暗模式差异**:颜色值会自动切换,保持对比度 - ---- - ## 钱包个性化主题色 ### 概述 每个钱包拥有独立的主题色(色相值 0-360),用于: - 钱包卡片渐变背景 -- 确认/保存按钮动态颜色 -- 视觉区分多个钱包 +- 确认按钮动态颜色 +- 视觉区分多钱包 ### CSS 自定义属性 @@ -251,37 +161,11 @@ shadcn/ui 使用**配色对**设计,每个颜色变量都有对应的 `xxx-for inherits: true; initial-value: 323; } - -@property --primary-lightness { - syntax: ""; - inherits: true; - initial-value: 0.59; -} - -@property --primary-saturation { - syntax: ""; - inherits: true; - initial-value: 0.26; -} -``` - -### 动态主题色应用 - -```tsx -// 按钮跟随钱包主题色 - ``` ### 色相派生算法 -从钱包地址稳定派生初始色相,确保跨设备一致: +从钱包地址稳定派生初始色相: ```typescript function deriveThemeHue(address: string): number { @@ -294,20 +178,28 @@ function deriveThemeHue(address: string): number { } ``` -### 预设颜色 +### 渐变背景 -提供 12 个预设色相,覆盖色轮主要区域: +使用 OKLCH 色彩空间生成和谐渐变: + +```typescript +const gradient = `linear-gradient( + 135deg, + oklch(0.5 0.2 ${themeHue}) 0%, + oklch(0.4 0.22 ${themeHue + 20}) 50%, + oklch(0.3 0.18 ${themeHue + 40}) 100% +)`; +``` + +### 预设色相 ```typescript const WALLET_THEME_COLORS = [ { hue: 0, name: '红色' }, { hue: 30, name: '橙色' }, { hue: 60, name: '黄色' }, - { hue: 90, name: '黄绿' }, { hue: 120, name: '绿色' }, - { hue: 150, name: '青绿' }, { hue: 180, name: '青色' }, - { hue: 210, name: '天蓝' }, { hue: 240, name: '蓝色' }, { hue: 270, name: '紫色' }, { hue: 300, name: '品红' }, @@ -315,31 +207,46 @@ const WALLET_THEME_COLORS = [ ]; ``` -### 趋避算法 +--- + +## 深色模式 + +### 行为约束 + +| 约束 | 说明 | +|------|------| +| MUST | 跟随系统设置 | +| MUST | 颜色自动切换 | +| SHOULD | 提供手动切换入口 | +| MUST NOT | 使用硬编码颜色 | -为避免多钱包颜色相近,选择器会: -1. 显示已用色相标记 -2. 降低相近颜色(距离 < 30°)的视觉权重 +### 检测方式 ```typescript -function calculateAvoidanceWeight(hue: number, existingHues: number[]): number { - const minDistance = 30; - let minDist = 180; - - for (const existing of existingHues) { - const dist = Math.min(Math.abs(hue - existing), 360 - Math.abs(hue - existing)); - if (dist < minDist) minDist = dist; - } - - return minDist < minDistance ? minDist / minDistance : 1; +// CSS 媒体查询 +@media (prefers-color-scheme: dark) { + :root { /* dark values */ } } + +// JavaScript 检测 +const isDark = window.matchMedia('(prefers-color-scheme: dark)').matches; ``` --- -## 相关链接 +## 对比度要求 + +| 元素 | 最小对比度 | WCAG 级别 | +|------|-----------|-----------| +| 正文文本 | 4.5:1 | AA | +| 大文本(≥18px) | 3:1 | AA | +| 图标 | 3:1 | AA | +| 禁用状态 | 无要求 | - | + +--- + +## 相关文档 -- [shadcn/ui 主题文档](https://ui.shadcn.com/docs/theming) -- [Tailwind CSS 颜色](https://tailwindcss.com/docs/customizing-colors) -- [WalletCard 组件](../../05-组件篇/03-钱包组件/WalletCard.md) -- [WalletConfig 组件](../../05-组件篇/03-钱包组件/WalletConfig.md) +- [设计原则](./02-Design-Principles.md) +- [交互规范](./04-Interaction-Specs.md) +- [WalletCard 组件](../05-Components/04-Wallet.md) diff --git a/docs/white-book/03-UI-Ref/01-Foundation/04-Interaction-Specs.md b/docs/white-book/03-UI-Ref/01-Foundation/04-Interaction-Specs.md new file mode 100644 index 000000000..4697ede8c --- /dev/null +++ b/docs/white-book/03-UI-Ref/01-Foundation/04-Interaction-Specs.md @@ -0,0 +1,310 @@ +# 交互规范 + +> 源码: 全局交互行为、动效和可访问性规范 + +--- + +## 触摸交互规范 + +### 触摸目标 + +| 规范 | 要求 | 约束级别 | +|------|------|----------| +| 最小尺寸 | 44 × 44 px (iOS) / 48 × 48 dp (Android) | MUST | +| 间距 | 相邻可触摸元素间距 ≥ 8 px | MUST | +| 热区扩展 | 视觉元素 < 最小尺寸时扩展触摸热区 | SHOULD | + +### 触摸反馈 + +| 事件 | 反馈 | 时机 | 约束级别 | +|------|------|------|----------| +| touch start | 视觉变化 | 立即 | MUST | +| touch end | 恢复原状 | 立即 | MUST | +| long press | 振动 + 上下文菜单 | 500ms | SHOULD | + +### 按压态规范 + +```css +/* Button 按压态 */ +.button:active { + opacity: 0.7; /* 或 */ + transform: scale(0.98); /* 或 */ + filter: brightness(0.9); +} + +/* Card 按压态 */ +.card:active { + transform: scale(0.98); + box-shadow: /* 增强阴影 */; +} +``` + +--- + +## 手势规范 + +### 滑动手势 + +| 手势 | 方向 | 应用场景 | 约束级别 | +|------|------|----------|----------| +| 滑动 | 水平 | 列表项操作 | MAY | +| 滑动 | 垂直 | Sheet 关闭 | MUST | +| 下拉 | 垂直向下 | 刷新内容 | SHOULD | + +### Sheet 关闭手势 + +```typescript +const sheetGesture = { + // 关闭阈值 + closeThreshold: 0.3, // 30% 高度 + + // 速度检测 + velocityThreshold: 500, // px/s + + // 决策逻辑 + shouldClose: (distance: number, velocity: number, height: number) => { + if (velocity > velocityThreshold) return true; + return distance / height >= closeThreshold; + } +}; +``` + +### 禁止行为 + +| 行为 | 约束级别 | +|------|----------| +| 拦截系统缩放手势 | MUST NOT | +| 拦截系统返回手势 | MUST NOT | +| 自定义不可预期的手势 | SHOULD NOT | + +--- + +## 动效规范 + +### 时间曲线 + +| 动效类型 | 持续时间 | 缓动函数 | 约束级别 | +|----------|----------|----------|----------| +| 微交互 | 100-150ms | ease-out | MUST | +| 页面切换 | 250-350ms | ease-in-out | MUST | +| Sheet 展开 | 300-400ms | spring(0.8) | SHOULD | +| 骨架闪烁 | 1500ms | linear | SHOULD | + +### 页面转场 + +```typescript +// Push 进入 +const pushAnimation = { + entering: { + transform: 'translateX(0)', + opacity: 1, + from: { transform: 'translateX(100%)', opacity: 1 } + }, + exiting: { + transform: 'translateX(-30%)', + opacity: 0.3, + from: { transform: 'translateX(0)', opacity: 1 } + } +}; + +// Pop 返回 +const popAnimation = { + entering: { + transform: 'translateX(0)', + opacity: 1, + from: { transform: 'translateX(-30%)', opacity: 0.3 } + }, + exiting: { + transform: 'translateX(100%)', + opacity: 1, + from: { transform: 'translateX(0)', opacity: 1 } + } +}; +``` + +### 3D 卡片效果 + +```css +/* 透视容器 */ +.perspective-container { + perspective: 1000px; +} + +/* 3D 卡片 */ +.card-3d { + --tilt-x: 0; + --tilt-y: 0; + --tilt-intensity: 0; + + transform: rotateX(calc(var(--tilt-x) * 1deg)) + rotateY(calc(var(--tilt-y) * 1deg)); + transform-style: preserve-3d; + transition: all 0.4s cubic-bezier(0.34, 1.56, 0.64, 1); +} + +/* 参数限制 */ +.card-3d { + --max-tilt: 15; /* 最大倾斜角度 ±15° */ + --perspective: 1000px; /* 透视距离 */ + --transition: 400ms; /* 过渡时长 */ +} +``` + +### 减少动效模式 + +| 约束 | 说明 | +|------|------| +| MUST | 检测系统 "减少动效" 设置 | +| MUST | 禁用弹簧动画 | +| MUST | 使用淡入淡出替代滑动 | +| MUST | 缩短动画时间至最小 | + +```typescript +const prefersReducedMotion = + window.matchMedia('(prefers-reduced-motion: reduce)').matches; + +const duration = prefersReducedMotion ? 0 : 300; +``` + +--- + +## 加载状态规范 + +### 骨架屏 + +| 适用场景 | 形态 | 约束级别 | +|----------|------|----------| +| 文本 | 圆角矩形,高度=行高 | SHOULD | +| 头像 | 圆形 | SHOULD | +| 卡片 | 与实际尺寸一致 | SHOULD | +| 列表 | 重复 3-5 个骨架项 | SHOULD | + +```css +/* 骨架动画 */ +@keyframes skeleton-shimmer { + 0% { background-position: -200% 0; } + 100% { background-position: 200% 0; } +} + +.skeleton { + background: linear-gradient( + 90deg, + hsl(var(--muted)) 25%, + hsl(var(--muted) / 0.5) 50%, + hsl(var(--muted)) 75% + ); + background-size: 200% 100%; + animation: skeleton-shimmer 1.5s infinite; +} +``` + +### 加载指示器类型 + +| 类型 | 适用场景 | 约束级别 | +|------|----------|----------| +| Spinner | 按钮内、小区域 | SHOULD | +| Skeleton | 页面首次加载 | SHOULD | +| Progress | 已知进度操作 | MAY | + +--- + +## 空状态规范 + +### 结构 + +``` +┌─────────────────────────────────┐ +│ [插图/图标] │ +│ │ +│ 主标题 │ +│ 副标题(可选) │ +│ │ +│ [操作按钮] │ +└─────────────────────────────────┘ +``` + +### 文案规范 + +| 元素 | 内容 | 约束级别 | +|------|------|----------| +| 主标题 | 描述当前状态 | MUST | +| 副标题 | 说明原因或引导 | SHOULD | +| 按钮 | 提供恢复路径 | SHOULD | + +--- + +## 反馈规范 + +### Toast 消息 + +| 类型 | 图标 | 持续时间 | 约束级别 | +|------|------|----------|----------| +| success | ✓ | 2s | MUST | +| error | ✗ | 3s | MUST | +| warning | ⚠ | 3s | SHOULD | +| info | ℹ | 2s | SHOULD | + +### 振动反馈 + +| 场景 | 振动类型 | 约束级别 | +|------|----------|----------| +| 按钮点击 | light | MAY | +| 操作成功 | success | SHOULD | +| 操作失败 | error | SHOULD | +| 危险确认 | warning | MUST | + +### 振动约束 + +| 约束 | 说明 | +|------|------| +| MUST | 检测系统振动设置 | +| MUST NOT | 静音模式下振动(除非用户明确开启) | + +--- + +## 可访问性规范 + +### 语义结构 + +| 元素 | 语义角色 | 约束级别 | +|------|----------|----------| +| 导航栏 | role="navigation" | MUST | +| 主内容 | role="main" | MUST | +| 对话框 | role="dialog" | MUST | +| 列表 | role="list" | SHOULD | +| 按钮 | role="button" | MUST | + +### 焦点管理 + +| 约束 | 说明 | +|------|------| +| MUST | 遵循视觉阅读顺序 | +| MUST | 可通过键盘 Tab 遍历 | +| MUST | 模态对话框内焦点循环 | +| MUST | 关闭对话框时焦点返回触发元素 | + +### 屏幕阅读器 + +| 约束 | 说明 | +|------|------| +| MUST | 所有按钮有 accessible name | +| MUST | 所有输入框有 label | +| MUST | 图标按钮使用 aria-label | +| SHOULD | 动态内容使用 aria-live | + +### 对比度 + +| 元素 | 最小对比度 | WCAG 级别 | +|------|-----------|-----------| +| 正文文本 | 4.5:1 | AA | +| 大文本 (≥18px) | 3:1 | AA | +| 图标 | 3:1 | AA | +| 禁用状态 | 无要求 | - | + +--- + +## 相关文档 + +- [设计原则](./02-Design-Principles.md) +- [主题配色](./03-Theme-Colors.md) +- [组件库](../05-Components/00-Index.md) diff --git a/docs/white-book/03-UI-Ref/02-Primitives/00-Index.md b/docs/white-book/03-UI-Ref/02-Primitives/00-Index.md new file mode 100644 index 000000000..182be7268 --- /dev/null +++ b/docs/white-book/03-UI-Ref/02-Primitives/00-Index.md @@ -0,0 +1,263 @@ +# Primitives 完整索引 + +> Source: [src/components/ui/](https://github.com/BioforestChain/KeyApp/tree/main/src/components/ui) + +## 概览 + +基于 shadcn/ui 构建的基础组件库,共 **18 个** 组件。 + +--- + +## 组件列表 + +### 按钮与交互 + +| 组件 | 文件 | 描述 | +|------|------|------| +| Button | `button.tsx` | 基础按钮 | +| Checkbox | `checkbox.tsx` | 复选框 | +| DropdownMenu | `dropdown-menu.tsx` | 下拉菜单 | + +### 表单输入 + +| 组件 | 文件 | 描述 | +|------|------|------| +| Input | `input.tsx` | 文本输入 | +| InputGroup | `input-group.tsx` | 输入组 | +| Textarea | `textarea.tsx` | 多行文本 | +| Select | `select.tsx` | 选择器 | +| Combobox | `combobox.tsx` | 组合框 (搜索+选择) | +| Label | `label.tsx` | 标签 | +| Field | `field.tsx` | 表单字段容器 | + +### 展示 + +| 组件 | 文件 | 描述 | +|------|------|------| +| Card | `card.tsx` | 卡片 | +| Badge | `badge.tsx` | 徽章 | +| Avatar | `avatar.tsx` | 头像 | +| Separator | `separator.tsx` | 分隔线 | +| Progress | `progress.tsx` | 进度条 | +| MarqueeText | `marquee-text.tsx` | 跑马灯文本 | + +### 弹窗与反馈 + +| 组件 | 文件 | 描述 | +|------|------|------| +| Sheet | `sheet.tsx` | 底部弹窗 | +| AlertDialog | `alert-dialog.tsx` | 警告对话框 | + +--- + +## Button + +```typescript +interface ButtonProps extends React.ButtonHTMLAttributes { + variant?: 'default' | 'destructive' | 'outline' | 'secondary' | 'ghost' | 'link'; + size?: 'default' | 'sm' | 'lg' | 'icon'; + asChild?: boolean; +} +``` + +**变体**: +- `default`: 主按钮 (填充) +- `destructive`: 危险操作 (红色) +- `outline`: 轮廓 +- `secondary`: 次要 +- `ghost`: 幽灵 (透明背景) +- `link`: 链接样式 + +--- + +## Input + +```typescript +interface InputProps extends React.InputHTMLAttributes { + // 继承原生 input 属性 +} +``` + +**特性**: +- 支持所有原生 input 类型 +- 自动 focus 样式 +- 错误状态通过 `aria-invalid` 控制 + +--- + +## Card + +```typescript +// 组合使用 + + + 标题 + 描述 + + 内容 + 底部 + +``` + +--- + +## Sheet (底部弹窗) + +```typescript +interface SheetProps { + open?: boolean; + onOpenChange?: (open: boolean) => void; + children: React.ReactNode; +} + +// 使用 + + + + + + + 标题 + + {/* 内容 */} + + +``` + +**Side 选项**: `top` | `bottom` | `left` | `right` + +--- + +## AlertDialog + +```typescript + + + + + + + 确认删除? + + 此操作无法撤销。 + + + + 取消 + 确认 + + + +``` + +--- + +## Badge + +```typescript +interface BadgeProps extends React.HTMLAttributes { + variant?: 'default' | 'secondary' | 'destructive' | 'outline'; +} + +// 使用 +待处理 +失败 +``` + +--- + +## Avatar + +```typescript + + + JD + +``` + +--- + +## Progress + +```typescript +interface ProgressProps { + value?: number; // 0-100 + max?: number; + className?: string; +} + + +``` + +--- + +## Select + +```typescript + +``` + +--- + +## Combobox + +```typescript + +``` + +--- + +## MarqueeText + +超长文本自动滚动。 + +```typescript + + 0x1234567890abcdef1234567890abcdef12345678 + +``` + +--- + +## 样式定制 + +所有组件支持通过 `className` 和 CSS 变量定制: + +```tsx +// 使用 cn() 合并样式 +import { cn } from '@/lib/utils'; + + +``` + +--- + +## 相关文档 + +- [Button](./Button.md) - 按钮组件 +- [Card](./Card.md) - 卡片组件 +- [Input](./Input.md) - 输入组件 +- [Dialog](./Dialog.md) - 对话框组件 +- [Design System](../01-Foundation/01-Colors.md) diff --git a/docs/white-book/03-UI-Ref/02-Primitives/Button.md b/docs/white-book/03-UI-Ref/02-Primitives/Button.md new file mode 100644 index 000000000..1a566d20a --- /dev/null +++ b/docs/white-book/03-UI-Ref/02-Primitives/Button.md @@ -0,0 +1,52 @@ +# Button Primitive + +## Overview + +The `Button` component is the primary interactive element, built on top of `@base-ui/react/button`. It supports multiple variants, sizes, and icon integrations. + +## Usage + +```tsx +import { Button } from '@/components/ui/button'; +import { IconPlus } from '@tabler/icons-react'; + +export function Example() { + return ( +
+ + + +
+ ); +} +``` + +## Props + +| Prop | Type | Default | Description | +|------|------|---------|-------------| +| `variant` | `string` | `default` | Visual style (`default`, `outline`, `ghost`, `secondary`, `destructive`, `link`). | +| `size` | `string` | `default` | Size preset (`default`, `xs`, `sm`, `lg`, `icon`, `icon-xs`, `icon-sm`, `icon-lg`). | +| `asChild` | `boolean` | `false` | Merges props into the child element (Slot pattern). | + +## Styling + +- **Base**: `rounded-lg border font-medium transition-all` +- **Focus**: `focus-visible:ring-ring/50 focus-visible:ring-[3px]` +- **Icons**: Automatically sizes SVGs based on button size (e.g., `size-4` for default). + +## Variants + +- **Default**: `bg-primary text-primary-foreground` +- **Secondary**: `bg-secondary text-secondary-foreground` +- **Outline**: `border-border bg-background hover:bg-muted` +- **Ghost**: `hover:bg-muted` +- **Destructive**: `bg-destructive/10 text-destructive` + +## Accessibility + +- Fully accessible via keyboard. +- Supports `aria-invalid` states. +- `disabled` state handles pointer events and opacity. diff --git a/docs/white-book/03-UI-Ref/02-Primitives/Card.md b/docs/white-book/03-UI-Ref/02-Primitives/Card.md new file mode 100644 index 000000000..420e0676b --- /dev/null +++ b/docs/white-book/03-UI-Ref/02-Primitives/Card.md @@ -0,0 +1,60 @@ +# Card Primitive + +## Overview + +The `Card` component is a flexible container for grouping related content. It provides a consistent background, border, and spacing structure. + +## Usage + +```tsx +import { + Card, + CardHeader, + CardTitle, + CardDescription, + CardContent, + CardFooter, + CardAction +} from '@/components/ui/card'; + +export function Example() { + return ( + + + Card Title + Optional description + + + + + +

Main content area.

+
+ + + +
+ ); +} +``` + +## Components + +- **Card**: Main container. Supports `size="sm"` for tighter padding. +- **CardHeader**: Top section, supports grid layout for title/description/action. +- **CardTitle**: Bold heading text (`text-base font-medium`). +- **CardDescription**: Muted secondary text. +- **CardAction**: Positioned in the top-right of the header. +- **CardContent**: Main body area. +- **CardFooter**: Bottom section, often with a different background or border. + +## Styling + +- **Base**: `bg-card text-card-foreground rounded-xl ring-1 ring-foreground/10` +- **Footer**: `bg-muted/50 border-t` (visual separation). +- **Responsive**: `size="sm"` reduces padding and font sizes for dense layouts. + +## Behavior + +- **Image Integration**: First/last child images automatically get rounded corners to match the card. +- **Grid Layout**: Header uses CSS Grid to align title, description, and action button. diff --git a/docs/white-book/03-UI-Ref/02-Primitives/Dialog.md b/docs/white-book/03-UI-Ref/02-Primitives/Dialog.md new file mode 100644 index 000000000..a2ef4fedd --- /dev/null +++ b/docs/white-book/03-UI-Ref/02-Primitives/Dialog.md @@ -0,0 +1,64 @@ +# Dialog Primitive + +## Overview + +The `Dialog` (and `AlertDialog`) components provide modal overlays for critical interactions or information. Built on `@base-ui/react/alert-dialog`. + +## Usage + +```tsx +import { + AlertDialog, + AlertDialogContent, + AlertDialogHeader, + AlertDialogTitle, + AlertDialogDescription, + AlertDialogFooter, + AlertDialogAction, + AlertDialogCancel, + AlertDialogTrigger +} from '@/components/ui/alert-dialog'; + +export function Example() { + return ( + + + + + + + Are you sure? + This action cannot be undone. + + + Cancel + Confirm + + + + ); +} +``` + +## Components + +- **AlertDialog**: Root container, manages open state. +- **AlertDialogContent**: The modal popup itself. +- **AlertDialogOverlay**: Backdrop (dimmed background). +- **AlertDialogHeader**: Container for title/description/media. +- **AlertDialogMedia**: Slot for an icon or illustration at the top. +- **AlertDialogFooter**: Container for actions (buttons). + +## Styling + +- **Overlay**: `bg-black/10 backdrop-blur-xs` +- **Content**: `bg-background rounded-xl ring-1 ring-foreground/10 shadow-lg` +- **Animations**: + - `zoom-in-95` / `zoom-out-95` scale effect. + - `fade-in` / `fade-out` opacity effect. + +## Accessibility + +- Focus trapped inside the dialog when open. +- Clicking overlay or pressing ESC closes the dialog (unless configured otherwise). +- Appropriate ARIA roles (`alertdialog`) applied automatically. diff --git a/docs/white-book/03-UI-Ref/02-Primitives/Input.md b/docs/white-book/03-UI-Ref/02-Primitives/Input.md new file mode 100644 index 000000000..f941567c5 --- /dev/null +++ b/docs/white-book/03-UI-Ref/02-Primitives/Input.md @@ -0,0 +1,40 @@ +# Input Primitive + +## Overview + +The `Input` component is a wrapper around the HTML `input` element, styled with Tailwind CSS to match the KeyApp design system. It is built on top of `@base-ui/react/input` primitive. + +## Usage + +```tsx +import { Input } from '@/components/ui/input'; + +export function Example() { + return ; +} +``` + +## Props + +Inherits all standard HTML input attributes via `React.ComponentProps`. + +| Prop | Type | Default | Description | +|------|------|---------|-------------| +| `className` | `string` | - | Additional CSS classes. | +| `type` | `string` | `text` | Input type (text, password, email, etc.). | +| `placeholder` | `string` | - | Placeholder text. | +| `disabled` | `boolean` | `false` | Whether the input is disabled. | + +## Styling + +- **Base**: `h-8 rounded-lg border bg-transparent px-2.5 py-1 text-base` +- **Dark Mode**: `dark:bg-input/30` +- **Focus**: `focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]` +- **Invalid**: `aria-invalid:border-destructive aria-invalid:ring-destructive/20` +- **Disabled**: `disabled:opacity-50 disabled:cursor-not-allowed` + +## Accessibility + +- Automatically handles `aria-invalid` styling. +- Supports standard keyboard navigation and focus states. +- Uses `data-slot="input"` for internal targeting. diff --git a/docs/white-book/03-UI-Ref/03-Composites/00-Index.md b/docs/white-book/03-UI-Ref/03-Composites/00-Index.md new file mode 100644 index 000000000..9800d7a18 --- /dev/null +++ b/docs/white-book/03-UI-Ref/03-Composites/00-Index.md @@ -0,0 +1,288 @@ +# Composites 完整索引 + +> Source: [src/components/common/](https://github.com/BioforestChain/KeyApp/tree/main/src/components/common) | [src/components/layout/](https://github.com/BioforestChain/KeyApp/tree/main/src/components/layout) + +## 概览 + +复合组件是由基础组件组合而成的业务通用组件,分为 **Common** 和 **Layout** 两类。 + +--- + +## Common 组件 (20个) + +| 组件 | 文件 | 描述 | +|------|------|------| +| StepIndicator | `step-indicator.tsx` | 步骤指示器 | +| AnimatedNumber | `animated-number.tsx` | 数字动画 | +| QRCode | `qr-code.tsx` | 二维码生成 | +| ErrorBoundary | `error-boundary.tsx` | 错误边界 | +| FormField | `form-field.tsx` | 表单字段 | +| IconCircle | `icon-circle.tsx` | 圆形图标容器 | +| ContactAvatar | `contact-avatar.tsx` | 联系人头像 | +| DevWatermark | `DevWatermark.tsx` | 开发水印 | +| EmptyState | `empty-state.tsx` | 空状态 | +| ProviderFallbackWarning | `provider-fallback-warning.tsx` | Provider 降级警告 | +| TimeDisplay | `time-display.tsx` | 时间显示 | +| GradientButton | `gradient-button.tsx` | 渐变按钮 | +| SwiperSyncContext | `swiper-sync-context.tsx` | Swiper 同步上下文 | +| Alert | `alert.tsx` | 警告提示 | +| LoadingSpinner | `loading-spinner.tsx` | 加载动画 | +| MigrationRequiredView | `migration-required-view.tsx` | 迁移提示视图 | +| SafeMarkdown | `safe-markdown.tsx` | 安全 Markdown | +| AmountDisplay | `amount-display.tsx` | 金额显示 | +| Skeleton | `skeleton.tsx` | 骨架屏 | + +--- + +## Layout 组件 (5个) + +| 组件 | 文件 | 描述 | +|------|------|------| +| SwipeableTabs | `swipeable-tabs.tsx` | 可滑动标签页 | +| BottomSheet | `bottom-sheet.tsx` | 底部弹窗 | +| TabBar | `tab-bar.tsx` | 底部导航栏 | +| PageHeader | `page-header.tsx` | 页面头部 | +| Modal | `modal.tsx` | 模态框 | + +--- + +## 详细文档 + +### StepIndicator + +步骤进度指示器。 + +```typescript +interface StepIndicatorProps { + currentStep: number; + totalSteps: number; + labels?: string[]; +} + + +``` + +### AnimatedNumber + +数字变化动画。 + +```typescript +interface AnimatedNumberProps { + value: number; + duration?: number; + decimals?: number; + prefix?: string; + suffix?: string; +} + + +``` + +### QRCode + +二维码生成。 + +```typescript +interface QRCodeProps { + value: string; + size?: number; + logo?: string; + className?: string; +} + + +``` + +### AmountDisplay + +格式化金额显示。 + +```typescript +interface AmountDisplayProps { + amount: Amount | string; + symbol?: string; + showSign?: boolean; + showFiat?: boolean; + fiatValue?: number; +} + + +// 显示: 1.5 ETH ($3,000.00) +``` + +### TimeDisplay + +相对/绝对时间显示。 + +```typescript +interface TimeDisplayProps { + timestamp: number; + format?: 'relative' | 'absolute' | 'auto'; +} + + +// 显示: 1 分钟前 +``` + +### EmptyState + +空状态占位。 + +```typescript +interface EmptyStateProps { + icon?: React.ReactNode; + title: string; + description?: string; + action?: React.ReactNode; +} + +} + title="暂无钱包" + description="创建或导入钱包开始使用" + action={} +/> +``` + +### LoadingSpinner + +加载动画。 + +```typescript +interface LoadingSpinnerProps { + size?: 'sm' | 'md' | 'lg'; + className?: string; +} + + +``` + +### Skeleton + +骨架屏加载占位。 + +```typescript + + +``` + +### PageHeader + +页面头部导航。 + +```typescript +interface PageHeaderProps { + title: string; + onBack?: () => void; + rightAction?: React.ReactNode; +} + + pop()} + rightAction={} +/> +``` + +### TabBar + +底部导航栏。 + +```typescript +interface TabBarProps { + items: TabBarItem[]; + activeIndex: number; + onChange: (index: number) => void; +} + +interface TabBarItem { + icon: React.ReactNode; + label: string; + badge?: number; +} +``` + +### SwipeableTabs + +可滑动切换的标签页。 + +```typescript +interface SwipeableTabsProps { + tabs: Tab[]; + activeIndex: number; + onChange: (index: number) => void; + children: React.ReactNode[]; +} + + + + + +``` + +### Alert + +警告/提示条。 + +```typescript +interface AlertProps { + variant?: 'default' | 'destructive' | 'warning'; + children: React.ReactNode; +} + + + + 注意 + 请确保您已备份助记词 + +``` + +### GradientButton + +渐变背景按钮。 + +```typescript +interface GradientButtonProps { + children: React.ReactNode; + onClick?: () => void; + disabled?: boolean; + gradient?: string; +} + + + 立即购买 + +``` + +### ErrorBoundary + +错误边界组件。 + +```typescript +}> + + +``` + +### SafeMarkdown + +安全渲染 Markdown (XSS 防护)。 + +```typescript + +``` + +--- + +## 相关文档 + +- [Primitives](../02-Primitives/00-Index.md) +- [Domain Components](../04-Domain/01-Wallet-Asset.md) +- [Layout](./Layout.md) - 布局组件 diff --git a/docs/white-book/03-UI-Ref/03-Composites/Common.md b/docs/white-book/03-UI-Ref/03-Composites/Common.md new file mode 100644 index 000000000..33a0d9231 --- /dev/null +++ b/docs/white-book/03-UI-Ref/03-Composites/Common.md @@ -0,0 +1,40 @@ +# Common Components + +> **Code Source**: [`src/components/common`](https://github.com/BioforestChain/KeyApp/tree/main/src/components/common) + +## Overview + +High-level reusable components that don't fit into a specific business domain. + +## Components + +### AmountDisplay + +A powerful component for formatting crypto and fiat amounts. + +- **Features**: + - **Auto-Formatting**: Handles decimals, grouping, and scientific notation fallback. + - **Animation**: Uses `NumberFlow` for smooth value transitions. + - **Privacy**: Supports `hidden` prop to mask values (e.g. `••••••`). + - **Coloring**: Auto-colors positive/negative values if `color="auto"`. + +```tsx + +``` + +### EmptyState + +Standardized placeholder for lists with no data. +- **Props**: `title`, `description`, `icon`, `action` (button). + +### QRCode + +Wrapper around `qrcode.react` with styling and logo support. + +### SafeMarkdown + +Renders Markdown content with strict sanitization (no HTML, no scripts). Used for DApp descriptions and release notes. diff --git a/docs/white-book/03-UI-Ref/03-Composites/Layout.md b/docs/white-book/03-UI-Ref/03-Composites/Layout.md new file mode 100644 index 000000000..1e6f53ad0 --- /dev/null +++ b/docs/white-book/03-UI-Ref/03-Composites/Layout.md @@ -0,0 +1,39 @@ +# Layout Components + +> **Code Source**: [`src/components/layout`](https://github.com/BioforestChain/KeyApp/tree/main/src/components/layout) + +## Overview + +Layout components provide the structural scaffolding for pages (Activities) and modal overlays. + +## Components + +### PageHeader + +The standard navigation bar. + +- **Props**: + - `title`: Center title string. + - `onBack`: Callback for the back button (renders button if present). + - `rightAction`: Node to render on the right side (e.g., Settings icon). + - `transparent`: Visual style toggle. + +```tsx + pop()} + rightAction={} +/> +``` + +--- + +## TransactionItem + +单条交易显示组件。 + +### Props + +```typescript +interface TransactionInfo { + id: string; + type: 'send' | 'receive' | 'contract' | 'swap'; + status: 'pending' | 'confirming' | 'confirmed' | 'failed'; + amount: string; + symbol: string; + address: string; // 对方地址 + timestamp: Date | string; + hash: string; +} + +interface TransactionItemProps { + transaction: TransactionInfo; + onClick?: () => void; + showChainIcon?: boolean; + chainId?: string; +} +``` + +### 视觉布局 + +``` +┌────────────────────────────────────────────────────────────┐ +│ ┌────┐ │ +│ │ ↑ │ 发送到 0x1234...5678 -0.5 ETH │ +│ │ 🔴 │ 14:32 · 确认中 ≈ $1,500 │ +│ └────┘ [🔗] │ +└────────────────────────────────────────────────────────────┘ + +图标: + ↑ 红色 = 发送 + ↓ 绿色 = 接收 + ⟳ 蓝色 = 合约 + ⇄ 紫色 = 兑换 +``` + +--- + +## TransactionStatus + +交易状态指示器。 + +### Props + +```typescript +interface TransactionStatusProps { + status: 'pending' | 'confirming' | 'confirmed' | 'failed'; + confirmations?: number; + requiredConfirmations?: number; +} +``` + +### 状态映射 + +| Status | 图标 | 颜色 | 描述 | +|--------|------|------|------| +| pending | ⏳ | 黄色 | 等待确认 | +| confirming | ⟳ | 蓝色 | 确认中 (X/Y) | +| confirmed | ✓ | 绿色 | 已确认 | +| failed | ✗ | 红色 | 失败 | + +### 进度显示 + +```tsx +// 确认中显示进度 + +// 显示: ⟳ 确认中 (3/12) +``` + +--- + +## FeeDisplay + +手续费显示组件。 + +### Props + +```typescript +interface FeeDisplayProps { + fee: Amount; + symbol: string; + fiatValue?: number; + speed?: 'slow' | 'normal' | 'fast'; + estimatedTime?: number; // 秒 +} +``` + +### 显示格式 + +``` +┌────────────────────────────────────────┐ +│ 手续费 │ +│ 0.002 ETH ≈ $4.00 │ +│ 预计 30 秒确认 │ +└────────────────────────────────────────┘ +``` + +--- + +## 使用示例 + +### 完整交易历史页 + +```tsx +function HistoryPage() { + const { walletId, selectedChain } = useCurrentWallet(); + const { transactions, isLoading, filter, setFilter, refresh } = + useTransactionHistoryQuery(walletId); + const { push } = useFlow(); + + return ( +
+ + + {/* 筛选器 */} +
+ + + +
+ + {/* 交易列表 */} + { + push('TransactionDetailActivity', { txId: tx.id }); + }} + /> +
+ ); +} +``` + +--- + +## 相关文档 + +- [Transaction History Query](../../05-State-Ref/03-Queries/02-TransactionHistory-Query.md) +- [Transfer Components](./02-Transaction-Transfer.md) +- [Chain Adapter](../../06-Service-Ref/03-Chain/01-Adapter.md) diff --git a/docs/white-book/03-UI-Ref/04-Domain/02-Transaction-Transfer.md b/docs/white-book/03-UI-Ref/04-Domain/02-Transaction-Transfer.md new file mode 100644 index 000000000..3ad278b20 --- /dev/null +++ b/docs/white-book/03-UI-Ref/04-Domain/02-Transaction-Transfer.md @@ -0,0 +1,216 @@ +# Transaction & Transfer Components + +> Source: [src/components/transaction/](https://github.com/aspect-build/aspect-workflows/tree/main/src/components/transaction) | [src/components/transfer/](https://github.com/aspect-build/aspect-workflows/tree/main/src/components/transfer) + +## Overview + +Domain components for transaction history display and transfer operations. + +--- + +## Transaction Components + +### TransactionList +**Source**: `src/components/transaction/transaction-list.tsx` + +Paginated transaction history with infinite scroll. + +```tsx +interface TransactionListProps { + walletId: string; + chainId?: string; + filter?: TransactionFilter; + onSelect?: (tx: Transaction) => void; +} +``` + +### TransactionCard +**Source**: `src/components/transaction/transaction-card.tsx` + +Single transaction row with status and amount. + +```tsx +interface TransactionCardProps { + transaction: Transaction; + onClick?: () => void; + showChain?: boolean; +} +``` + +### TransactionDetail +**Source**: `src/components/transaction/transaction-detail.tsx` + +Full transaction details page content. + +### TransactionStatus +**Source**: `src/components/transaction/transaction-status.tsx` + +Visual status indicator (pending, confirmed, failed). + +```tsx +type TransactionStatusType = 'pending' | 'confirming' | 'confirmed' | 'failed'; + +interface TransactionStatusProps { + status: TransactionStatusType; + confirmations?: number; + requiredConfirmations?: number; +} +``` + +### TransactionIcon +**Source**: `src/components/transaction/transaction-icon.tsx` + +Transaction type icon (send, receive, swap, contract). + +### TransactionAmount +**Source**: `src/components/transaction/transaction-amount.tsx` + +Formatted amount with direction indicator (+/-). + +### TransactionTimestamp +**Source**: `src/components/transaction/transaction-timestamp.tsx` + +Relative or absolute time display. + +### TransactionHash +**Source**: `src/components/transaction/transaction-hash.tsx` + +Truncated hash with copy and explorer link. + +### TransactionFilter +**Source**: `src/components/transaction/transaction-filter.tsx` + +Filter controls for transaction list. + +--- + +## Transfer Components + +### TransferForm +**Source**: `src/components/transfer/transfer-form.tsx` + +Complete send transaction form. + +```tsx +interface TransferFormProps { + chainId: string; + tokenAddress?: string; + initialRecipient?: string; + initialAmount?: string; + onSubmit: (params: TransferParams) => void; +} +``` + +### RecipientInput +**Source**: `src/components/transfer/recipient-input.tsx` + +Address input with validation and QR scan. + +### AmountInput +**Source**: `src/components/transfer/amount-input.tsx` + +Token amount input with max button and fiat conversion. + +### GasFeeSelector +**Source**: `src/components/transfer/gas-fee-selector.tsx` + +Gas price/limit selection (slow/normal/fast). + +```tsx +interface GasFeeSelectorProps { + chainId: string; + gasEstimate: GasEstimate; + selectedSpeed: 'slow' | 'normal' | 'fast'; + onSpeedChange: (speed: 'slow' | 'normal' | 'fast') => void; + customGas?: CustomGasParams; + onCustomGasChange?: (params: CustomGasParams) => void; +} +``` + +### TransferPreview +**Source**: `src/components/transfer/transfer-preview.tsx` + +Transaction preview before signing. + +### TransferConfirm +**Source**: `src/components/transfer/transfer-confirm.tsx` + +Final confirmation with biometric/password. + +### TransferSuccess +**Source**: `src/components/transfer/transfer-success.tsx` + +Success state with transaction hash. + +### TransferError +**Source**: `src/components/transfer/transfer-error.tsx` + +Error state with retry option. + +--- + +## Transaction Flow + +``` +┌────────────────────────────────────────────────────────────┐ +│ TransferForm │ +│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐│ +│ │RecipientInput│ │ AmountInput │ │ TokenSelector ││ +│ └─────────────┘ └─────────────┘ └─────────────────────┘│ +│ ┌────────────────────────────────────────────────────────┐│ +│ │ GasFeeSelector ││ +│ └────────────────────────────────────────────────────────┘│ +└────────────────────────────────────────────────────────────┘ + │ + ▼ +┌────────────────────────────────────────────────────────────┐ +│ TransferPreview │ +│ From: 0x1234...5678 │ +│ To: 0xabcd...efgh │ +│ Amount: 1.5 ETH ($3,000) │ +│ Gas: 0.002 ETH ($4) │ +│ Total: 1.502 ETH ($3,004) │ +└────────────────────────────────────────────────────────────┘ + │ + ▼ +┌────────────────────────────────────────────────────────────┐ +│ TransferConfirm │ +│ [Biometric/Password Verification] │ +└────────────────────────────────────────────────────────────┘ + │ + ┌───────────┴───────────┐ + ▼ ▼ +┌─────────────────────┐ ┌─────────────────────┐ +│ TransferSuccess │ │ TransferError │ +│ TX: 0x789... │ │ [Retry Button] │ +└─────────────────────┘ └─────────────────────┘ +``` + +--- + +## State Machine + +``` +idle → validating → previewing → confirming → broadcasting → success + │ │ + └──────── failed ──────────┘ +``` + +--- + +## Integration Points + +| Component | Service | Store | +|-----------|---------|-------| +| TransferForm | `chain-adapter` | `walletStore` | +| GasFeeSelector | `gas-estimator` | - | +| TransactionList | `transaction-history` | `transactionStore` | +| TransferConfirm | `biometric` | - | + +--- + +## Related Documentation + +- [Transaction Lifecycle](../../10-Wallet-Guide/03-Transaction-Flow/01-Lifecycle.md) +- [Chain Adapter](../../02-Driver-Ref/01-Overview.md) +- [Biometric Service](../../04-Platform-Ref/02-Biometric.md) diff --git a/docs/white-book/03-UI-Ref/04-Domain/03-Onboarding-Security.md b/docs/white-book/03-UI-Ref/04-Domain/03-Onboarding-Security.md new file mode 100644 index 000000000..2abd12fc8 --- /dev/null +++ b/docs/white-book/03-UI-Ref/04-Domain/03-Onboarding-Security.md @@ -0,0 +1,298 @@ +# Onboarding & Security Components + +> Source: [src/components/onboarding/](https://github.com/aspect-build/aspect-workflows/tree/main/src/components/onboarding) | [src/components/security/](https://github.com/aspect-build/aspect-workflows/tree/main/src/components/security) | [src/components/authorize/](https://github.com/aspect-build/aspect-workflows/tree/main/src/components/authorize) | [src/components/migration/](https://github.com/aspect-build/aspect-workflows/tree/main/src/components/migration) + +## Overview + +Domain components for wallet creation/import, security setup, DApp authorization, and migration flows. + +--- + +## Onboarding Components + +### ChainSelector +**Source**: `src/components/onboarding/chain-selector.tsx` + +Multi-chain network selection with grouping by chain type. + +```tsx +interface ChainSelectorProps { + chains: ChainConfig[]; + selectedChains: string[]; + onSelectionChange: (chainIds: string[]) => void; + favoriteChains?: string[]; + onFavoriteChange?: (chainIds: string[]) => void; + showSearch?: boolean; +} +``` + +**Features**: +- Groups chains by `chainKind` (bioforest, evm, bitcoin, tron, custom) +- Search/filter functionality +- Favorite chains support +- Batch selection per group + +### ChainAddressPreview +**Source**: `src/components/onboarding/chain-address-preview.tsx` + +Preview of derived addresses for selected chains. + +### KeyTypeSelector +**Source**: `src/components/onboarding/key-type-selector.tsx` + +Selection between mnemonic and arbitrary key import. + +### ArbitraryKeyInput +**Source**: `src/components/onboarding/arbitrary-key-input.tsx` + +Private key/WIF input with validation. + +### RecoverWalletForm +**Source**: `src/components/onboarding/recover-wallet-form.tsx` + +Complete wallet recovery form with mnemonic input. + +### MnemonicConfirmBackup +**Source**: `src/components/onboarding/mnemonic-confirm-backup.tsx` + +Interactive mnemonic backup verification. + +```tsx +interface MnemonicConfirmBackupProps { + mnemonic: string[]; + onConfirm: () => void; + onCancel: () => void; +} +``` + +### BackupTipsSheet +**Source**: `src/components/onboarding/backup-tips-sheet.tsx` + +Security tips bottom sheet before backup. + +### CollisionConfirmDialog +**Source**: `src/components/onboarding/collision-confirm-dialog.tsx` + +Warning dialog when wallet already exists. + +### CreateWalletSuccess +**Source**: `src/components/onboarding/create-wallet-success.tsx` + +Success screen after wallet creation. + +### ImportWalletSuccess +**Source**: `src/components/onboarding/import-wallet-success.tsx` + +Success screen after wallet import. + +### SecurityWarningDialog +**Source**: `src/components/onboarding/security-warning-dialog.tsx` + +Generic security warning dialog. + +--- + +## Security Components + +### PatternLock +**Source**: `src/components/security/pattern-lock.tsx` + +9-dot pattern lock with touch/mouse gesture support. + +```tsx +interface PatternLockProps { + value?: number[]; + onChange?: (pattern: number[]) => void; + onComplete?: (pattern: number[]) => void; + minPoints?: number; + disabled?: boolean; + error?: boolean; + success?: boolean; + size?: number; +} +``` + +**Features**: +- Touch and mouse gesture drawing +- Keyboard accessibility (Tab + Space/Enter) +- Error shake animation with fade-out +- Visual feedback for selection state + +### PatternLockSetup +**Source**: `src/components/security/pattern-lock-setup.tsx` + +Two-phase pattern creation (create + confirm). + +### PasswordInput +**Source**: `src/components/security/password-input.tsx` + +Password input with strength indicator. + +```tsx +interface PasswordInputProps { + value: string; + onChange: (value: string) => void; + showStrength?: boolean; + minLength?: number; + requireUppercase?: boolean; + requireNumber?: boolean; + requireSpecial?: boolean; +} +``` + +### MnemonicDisplay +**Source**: `src/components/security/mnemonic-display.tsx` + +Read-only mnemonic word grid display. + +### MnemonicInput +**Source**: `src/components/security/mnemonic-input.tsx` + +Editable mnemonic input with word suggestions. + +### MnemonicConfirm +**Source**: `src/components/security/mnemonic-confirm.tsx` + +Shuffled word selection for backup verification. + +--- + +## Authorize Components + +### AppInfoCard +**Source**: `src/components/authorize/AppInfoCard.tsx` + +DApp information display for authorization. + +```tsx +interface AppInfoCardProps { + appInfo: { + name: string; + icon?: string; + url: string; + description?: string; + }; +} +``` + +### PermissionList +**Source**: `src/components/authorize/PermissionList.tsx` + +Requested permissions checklist. + +### BalanceWarning +**Source**: `src/components/authorize/BalanceWarning.tsx` + +Warning when transaction exceeds balance. + +### TransactionDetails +**Source**: `src/components/authorize/TransactionDetails.tsx` + +Transaction parameters for approval. + +--- + +## Migration Components + +### WhatsNewSheet +**Source**: `src/components/migration/WhatsNewSheet.tsx` + +New version features announcement. + +### MigrationProgressStep +**Source**: `src/components/migration/MigrationProgressStep.tsx` + +Migration progress indicator. + +### MigrationCompleteStep +**Source**: `src/components/migration/MigrationCompleteStep.tsx` + +Migration success with summary. + +--- + +## Onboarding Flow + +``` +┌──────────────────────────────────────────────────────────────┐ +│ Welcome Screen │ +│ [Create Wallet] [Import Wallet] │ +└──────────────────────────────────────────────────────────────┘ + │ │ + ▼ ▼ +┌─────────────────────┐ ┌─────────────────────────────────┐ +│ ChainSelector │ │ KeyTypeSelector │ +│ (Select Networks) │ │ [Mnemonic] [Private Key] │ +└─────────────────────┘ └─────────────────────────────────┘ + │ │ │ + ▼ ▼ ▼ +┌─────────────────────┐ ┌────────────┐ ┌────────────────────┐ +│ MnemonicConfirmBackup│ │MnemonicInput│ │ArbitraryKeyInput │ +│ (Verify Backup) │ │(12/24 words)│ │(Private Key/WIF) │ +└─────────────────────┘ └────────────┘ └────────────────────┘ + │ │ │ + └───────────────────┴──────────────┘ + │ + ▼ +┌──────────────────────────────────────────────────────────────┐ +│ Security Setup │ +│ [PatternLockSetup] or [PasswordInput] │ +└──────────────────────────────────────────────────────────────┘ + │ + ▼ +┌──────────────────────────────────────────────────────────────┐ +│ CreateWalletSuccess │ +│ ImportWalletSuccess │ +└──────────────────────────────────────────────────────────────┘ +``` + +--- + +## DApp Authorization Flow + +``` +┌────────────────────────────────────────────────────┐ +│ Authorization Request │ +│ ┌──────────────────────────────────────────────┐ │ +│ │ AppInfoCard │ │ +│ │ [App Icon] App Name │ │ +│ │ https://dapp.example.com │ │ +│ └──────────────────────────────────────────────┘ │ +│ ┌──────────────────────────────────────────────┐ │ +│ │ PermissionList │ │ +│ │ ☑ View wallet addresses │ │ +│ │ ☑ Request transaction signing │ │ +│ │ ☐ Auto-approve small transactions │ │ +│ └──────────────────────────────────────────────┘ │ +│ ┌──────────────────────────────────────────────┐ │ +│ │ TransactionDetails (if tx) │ │ +│ │ To: 0x1234... │ │ +│ │ Value: 0.1 ETH │ │ +│ └──────────────────────────────────────────────┘ │ +│ ┌──────────────────────────────────────────────┐ │ +│ │ BalanceWarning (if needed) │ │ +│ └──────────────────────────────────────────────┘ │ +│ [Reject] [Approve] │ +└────────────────────────────────────────────────────┘ +``` + +--- + +## Integration Points + +| Component | Service | Store | +|-----------|---------|-------| +| ChainSelector | `chain-config` | `chainConfigStore` | +| PatternLock | `biometric` | - | +| MnemonicInput | `wallet-service` | - | +| AppInfoCard | `miniapp-runtime` | - | +| MigrationProgressStep | `migration-service` | - | + +--- + +## Related Documentation + +- [Key Derivation](../../10-Wallet-Guide/01-Account-System/01-Key-Derivation.md) +- [Biometric Service](../../04-Platform-Ref/02-Biometric.md) +- [Migration Service](../../06-Service-Ref/03-Migration/01-Mpay-Migration.md) +- [MiniApp Runtime](../../01-Kernel-Ref/01-Overview.md) diff --git a/docs/white-book/03-UI-Ref/04-Domain/04-Ecosystem.md b/docs/white-book/03-UI-Ref/04-Domain/04-Ecosystem.md new file mode 100644 index 000000000..0cb7e8694 --- /dev/null +++ b/docs/white-book/03-UI-Ref/04-Domain/04-Ecosystem.md @@ -0,0 +1,278 @@ +# Ecosystem Components + +> Source: [src/components/ecosystem/](https://github.com/aspect-build/aspect-workflows/tree/main/src/components/ecosystem) + +## Overview + +Domain components for the miniapp ecosystem — app discovery, windowing, and iOS-style desktop experience. + +--- + +## Discovery Components + +### DiscoverPage +**Source**: `src/components/ecosystem/discover-page.tsx` + +App store discovery interface with categories and search. + +```tsx +interface DiscoverPageProps { + className?: string; +} +``` + +**Features**: +- Category browsing +- Search functionality +- Featured apps carousel +- App recommendations + +### MyAppsPage +**Source**: `src/components/ecosystem/my-apps-page.tsx` + +Installed apps grid with management options. + +**Features**: +- iOS-style app grid layout +- Drag-to-rearrange (planned) +- Long-press context menu +- App folders (planned) + +### EcosystemDesktop +**Source**: `src/components/ecosystem/ecosystem-desktop.tsx` + +iOS Springboard-style desktop shell. + +```tsx +interface EcosystemDesktopProps { + className?: string; +} +``` + +**Storybook**: `ecosystem-desktop.stories.tsx` demonstrates all visual states. + +--- + +## MiniApp Visual Components + +### MiniappIcon +**Source**: `src/components/ecosystem/miniapp-icon.tsx` + +App icon with iOS-style rendering (rounded corners, shadows). + +```tsx +interface MiniappIconProps { + appId: string; + iconUrl?: string; + name: string; + size?: 'sm' | 'md' | 'lg' | 'xl'; + showLabel?: boolean; + className?: string; +} +``` + +### MiniappCapsule +**Source**: `src/components/ecosystem/miniapp-capsule.tsx` + +iOS-style status bar capsule (minimize/close controls). + +### SourceIcon +**Source**: `src/components/ecosystem/source-icon.tsx` + +App source indicator (official, third-party, developer). + +### IosSearchCapsule +**Source**: `src/components/ecosystem/ios-search-capsule.tsx` + +iOS-style search input capsule. + +### IosWallpaper +**Source**: `src/components/ecosystem/ios-wallpaper.tsx` + +Dynamic wallpaper background component. + +--- + +## MiniApp Window System + +### MiniappWindow +**Source**: `src/components/ecosystem/miniapp-window.tsx` + +Main miniapp container with portal rendering. + +```tsx +interface MiniappWindowProps { + className?: string; +} +``` + +**Architecture**: +- Uses React Portal for rendering into desktop slots +- Manages splash screen → iframe transitions +- Handles window focus and z-index stacking +- Integrates with `miniapp-runtime` store + +### MiniappSplashScreen +**Source**: `src/components/ecosystem/miniapp-splash-screen.tsx` + +App launch splash with icon animation. + +```tsx +interface MiniappSplashScreenProps { + app: MiniappManifest; + onDismiss?: () => void; +} +``` + +**Storybook**: `miniapp-splash-screen.stories.tsx` shows launch animations. + +### MiniappStackView +**Source**: `src/components/ecosystem/miniapp-stack-view.tsx` + +Multi-window stack management (app switcher). + +### MiniappStackCard +**Source**: `src/components/ecosystem/miniapp-stack-card.tsx` + +Individual app card in stack view. + +### MiniappWindowStack +**Source**: `src/components/ecosystem/miniapp-window-stack.tsx` + +Window stacking order manager. + +### AppStackPage +**Source**: `src/components/ecosystem/app-stack-page.tsx` + +Full-screen app switcher view. + +--- + +## Animation & Motion + +### MiniappMotionFlow +**Source**: `src/components/ecosystem/miniapp-motion-flow.ts` + +Motion preset generators for miniapp transitions. + +```tsx +// Flow functions for coordinated animations +flowToCapsule(flowId: string): MotionProps +flowToSplashBgLayer(flowId: string): MotionProps +flowToSplashIconLayer(flowId: string): MotionProps +flowToIframeLayer(flowId: string): MotionProps +flowToWindowContainer(flowId: string): MotionProps +``` + +### EcosystemTabIndicator +**Source**: `src/components/ecosystem/ecosystem-tab-indicator.tsx` + +Animated tab indicator for navigation. + +### SwiperSyncDemo +**Source**: `src/components/ecosystem/swiper-sync-demo.tsx` + +Demo component for synced swiper animations. + +--- + +## MiniApp Sheet + +### MiniappSheetHeader +**Source**: `src/components/ecosystem/miniapp-sheet-header.tsx` + +Bottom sheet header for miniapp modals. + +--- + +## Component Hierarchy + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ EcosystemDesktop │ +│ ┌────────────────────────────────────────────────────────────┐│ +│ │ IosWallpaper ││ +│ └────────────────────────────────────────────────────────────┘│ +│ ┌────────────────────────────────────────────────────────────┐│ +│ │ IosSearchCapsule ││ +│ └────────────────────────────────────────────────────────────┘│ +│ ┌────────────────────────────────────────────────────────────┐│ +│ │ MyAppsPage ││ +│ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ ││ +│ │ │MiniappIcon│MiniappIcon│MiniappIcon│MiniappIcon│ ││ +│ │ └─────────┘ └─────────┘ └─────────┘ └─────────┘ ││ +│ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ ││ +│ │ │MiniappIcon│MiniappIcon│MiniappIcon│MiniappIcon│ ││ +│ │ └─────────┘ └─────────┘ └─────────┘ └─────────┘ ││ +│ └────────────────────────────────────────────────────────────┘│ +│ ┌────────────────────────────────────────────────────────────┐│ +│ │ EcosystemTabIndicator ││ +│ └────────────────────────────────────────────────────────────┘│ +└─────────────────────────────────────────────────────────────────┘ + │ + │ (tap icon) + ▼ +┌─────────────────────────────────────────────────────────────────┐ +│ MiniappWindow │ +│ ┌────────────────────────────────────────────────────────────┐│ +│ │ MiniappSplashScreen ││ +│ │ (animate icon → fullscreen) ││ +│ └────────────────────────────────────────────────────────────┘│ +│ ┌────────────────────────────────────────────────────────────┐│ +│ │ MiniappCapsule ││ +│ │ [○ ○ ○] status [−] [×] ││ +│ └────────────────────────────────────────────────────────────┘│ +│ ┌────────────────────────────────────────────────────────────┐│ +│ │