Files
pangolin/design/CONTRACT.md
T
wangjia 277d1c6e97 feat(client): toast 限定主显示区/自适应宽/上限80%/超长多行居中(1.0.26)
按真相源新规:toast 改为自定义 Overlay 实现(widgets/pangolin_toast.dart),完全控制布局——
不覆盖左侧栏(left=侧栏宽 desktop204/tablet232/mobile0)、宽度自适应内容上限主区80%、超长文本
多行、主区内水平居中贴底、淡入轻起;仍走语义 token 明暗适配。自动连接改用 showPangolinToast。
同步 design/CONTRACT.md §2 toast 规格(canonical=showPangolinToast)。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-29 19:50:33 +08:00

93 lines
7.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 设计契约 · iPad / Tabletdesign-distill
> 像素基准:`design/ui_kits/tablet/tabapp.jsx`1180×820 横屏侧栏布局)+ `index.html`。
> 数值取自原型源码,非目测。token 单源:`design/colors_and_type.css` → `client/lib/pangolin_tokens.gen.dart`(勿手改)。
> 目标实现:`client/lib/shell/tablet_shell.dart` + 四页 `isWide` 分支 + `client/lib/widgets/`。
> 验收闸:`client/test/golden/tablet_pages_golden_test.dart`1180×820 / iOS 平台 → formFactor=tablet)。
## 0. 归一化产物
- 类型 A(结构化包):token 单源已存在、codegen 已接(`design/codegen/gen_flutter_tokens.mjs`)。本契约只补 **tablet 页面像素规格 + 验收清单**
- 断点:触屏宽 **≥900 → tablet 侧栏**,否则 mobile 底 Tab`client/lib/core/responsive/form_factor.dart`,对齐 README「≥900 切侧栏」)。
## 1. token 映射(复用既有语义层)
| 原型 CSS var | Flutter 语义层 |
|---|---|
| `--bg` / `--bg-subtle` | `c.bg` / `c.bgSubtle` |
| `--surface` | `c.surface` |
| `--fg1/2/3` | `c.fg1/fg2/fg3` |
| `--accent` / `--accent-subtle` / `--accent-border` | `c.accent` / `c.accentSubtle` / `c.accentBorder` |
| `--success` `--warning` | `c.success` `c.warning` |
| `--border` / `--border-strong` | `c.border` / `c.borderStrong` |
| `--radius-{sm,md,lg,xl,full}` | `PangolinRadius.{sm,md,lg,xl,full}` |
| `--shadow-{sm,md,lg}` | `PangolinShadow.{sm,md,lg}` |
| `--font-{display,sans,mono}` | `PangolinText.{h*/body...}` / `PangolinText.mono` |
## 2. 组件映射
| 原型 | Flutter | 状态 |
|---|---|---|
| `TabRail` 侧栏 | `TabletShell` + `widgets/nav_sidebar.dart` | 已接,宽 232、行高≥48 |
| 连接键三态 | `widgets/connect_button.dart` | 复用(off 态 canonical 走「虚线轨道环」,见 design/CLAUDE.md §5,优先于原型实心环简化) |
| 免费额度卡 | `widgets/quota_card.dart` | 复用 |
| 智能选择卡 | `widgets/smart_select_card.dart` | 复用 |
| 节点行 | `widgets/server_tile.dart` / `nodes_page` `_NodeGridTile` | 双列网格 |
| 指标卡 | `stats_page` `_MetricCard` | 复用 |
| 段控/开关/行 | `account_page` 内组件 | 复用 |
| Toast / 通知条 | `widgets/pangolin_toast.dart` `showPangolinToast` | 新增组件(无原型) |
### Toast / 通知条规格
跨平台轻提示(如自动连接「正在自动连接到 X」)。**无 React 原型 → 此处即真相源**;全部走语义 token,明暗自动适配。
**外观**:底 `--surface`(浅=白 / 深=`#221E19`)+ 文字 `--fg1`(Manrope 14/600,居中)+ 描边 `--border` 1px + 圆角 `md`(10)+ 柔和暖阴影(`shadow-sm`);淡入并轻微上移(240ms ease-out)。绝不用 Material 默认黑底。
**布局**(铁律):
- **只在主显示区内**,不覆盖左侧栏(left = 侧栏宽:desktop 204 / tablet 232 / mobile 0)。
- **宽度自适应内容**,上限 = 主显示区宽度的 **80%**;超过则**文本多行**。
- 在主显示区内**水平居中**,贴底(bottom 28)。
- Canonical 实现:`widgets/pangolin_toast.dart` `showPangolinToast(context, msg)`(Overlay 实现,非 SnackBar,以完全控制上述布局)。`pangolin_theme``snackBarTheme` 只作普通 SnackBar 的兜底底色样式。
## 3. 页面像素规格(取自 tabapp.jsx
### 外壳 TabletApp
- 内屏 1180×820`data-theme` 切明暗。侧栏 + 内容列(顶栏 56 + 主体)。
- 内容顶栏:高 56padding `0 28`,标题 `font-display 700 / 19 / fg1`,右侧连接状态(mono 12.5on=success「● {code}」/ off=fg3「○」)。
### TabRail 侧栏
- 宽 232`bg-subtle`,右 1px `border`padding `18 14 16`
- 品牌头:Mark 30 + 「穿山甲」(display 700/17) + 「PANGOLIN」(9/600/字距0.2em/accent)gap 10padding `0 8 20`
- 导航项:gap 4;每项 padding `13 14`、radius md、字号 15、active 700+accent+accent-subtle 底 / inactive 500+fg2、**minHeight 48**、图标 20active stroke 2.4)、gap 12。
- 底部套餐徽章:free=surface+border / pro=`linear-gradient(150deg,clay-600,clay-800)`+白字;radius lgpadding `12 13`;头像圈 32 + 名(12.5/700) + 邮箱(10.5/opacity.65)。
### 连接视图 TabConnect(双栏)
- 左列 flex **1.25**,居中,gap 26:按钮 216×216 圆、`box-shadow 0 0 0 11px {ring}, shadow-lg`、图标 60、label mono 700/14/字距0.08em;下方 caption(16/600/fg2)on 态计时 mono 28/fg1。
- 右列宽 **332**gap 14,垂直居中,paddingRight 28
- 免费额度卡(card padding `14 16`)clock + 「今日剩余 {n} 分钟」+ 「免费版」pill + 进度条(高6,≤3 变 warning) + 看广告按钮(accent-subtle/accent-border/full/minHeight44)。
- 当前节点卡(padding `13 15`, minHeight 48)CC 码块 + 「当前节点」(11/600/fg3) + 名(15/600) + 副(12/fg3) + chevron。
- on 态速率行:3 卡(下载/上传/延迟),各 padding `11 13`、值 mono 16。
### 节点视图 TabNodes
- padding `6 28 24`overflow auto。
- 智能卡:accent-subtle 底、border(active=accent)、radius xl、padding `15 16`、minHeight 56、marginBottom 14zap 在 clay 渐变盒 42×42 + 「智能选择」(15.5/700) + 「推荐」pill + 副(12/fg2) + active check。
- 搜索框:bg-subtle、radius md、padding `11 14`、maxWidth 380、marginBottom 14。
- 网格:**2 列 `1fr 1fr`gap 11**;每格 padding `13 15`、minHeight 56、active=accent-subtle+accent-borderCC + 名(14.5/600) + 副 + ping(mono 12) + Signal + active check。
### 统计视图 TabStats(上聚合 · 下分设备)
- padding `6 28 24`
- **上聚合**3 指标卡一行,gap 14marginBottom 20;各 padding `18 20`label(12.5/fg3/600) + 值(mono 26/fg1)。周柱卡 padding `20 22`:标题(13.5/600) + 7 柱(gap 22, 容器高150, 柱 maxWidth 40, accent opacity .85, radius `6 6 0 0`) + 值(mono 10.5) + 星期(11.5)。
- **下分设备**「设备明细 / By device」(统一组件 `DeviceStatRow`,四端复用):周柱卡下 marginTop 20,标题(13/600/fg1);设备卡 surface+border+radius-lg+shadow-sm,行内分隔线 border。每行 padding `14 16/15 18`:左平台图标盒 38×38(accent-subtle, radius md, Lucide smartphone/laptop/monitor-smartphone, clay 2.2px) + 中(名 14.515/600 省略号 + 占比迷你条 height 4 radius 999, track=border, fill=accent .85, 宽=本设备流量/最忙设备) + 右(流量 mono 14.515 + " GB" caption;时长 caption "X h")。流量降序;空数据显示占位「暂无设备用量 / No device usage yet」。
- 数据源:`GET /v1/usage/devices?days=N`(账户内每设备窗口聚合,busiest-first)→ `deviceUsageProvider`
### 账户视图 TabAccount
- padding `6 28 24`maxWidth 640(生产页功能更丰富,沿用同设计语言:套餐横幅 + 分区卡 + 行 + 段控/开关)。
- 套餐横幅 radius xl padding 20;行 minHeight 48,图标盒 34 radius sm accent-subtleTabToggle 48×29(on=accent)。
## 4. 逐屏验收清单(每屏 × 明/暗 × 中/英)
- [ ] 连接 / 节点 / 统计 / 账户 四视图 × light/dark × zh/en:无溢出、侧栏 232 比例正确、触控目标 ≥48。
- [ ] 连接页双栏左右比例 ≈ 1.25 : 332;on 态速率行 3 卡出现。
- [ ] 节点页 2 列网格 + 置顶智能卡;搜索框 maxWidth 380。
- [ ] 颜色全部语义 token、无硬编码 hexdesign/CLAUDE.md §1)。
- [ ] 文案无红线词(§13)、双语单显不并排。
- [ ] golden 回归闸 `tablet_pages_golden_test.dart` 通过;真机/模拟器 mini/11″/12.9″ 横竖屏目测过。
## 5. 已知差异(记录,非缺陷)
- 连接键 off 态:原型用实心 11px 环,Flutter 用「虚线轨道环」(design/CLAUDE.md §5 canonical 连接键),以 §5 为准。
- 账户页:生产实现比原型多设备管理/兑换/联系/协议行,属真实功能扩展,沿用同设计语言。
- golden 测试环境未打包 Noto Sans SC → CJK 显示为方块,仅影响 golden 文字、不影响真机;布局可判。节点网格/周柱在未登录测试态无数据(需注入演示数据方显内容)。