a642bf16a2
design/ 同步自最新设计导出,新增 ui_kits/tablet/ 平板分栏布局;todo/ 录入 18 个并行实施任务。 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
136 lines
7.7 KiB
Markdown
136 lines
7.7 KiB
Markdown
# 穿山甲 VPN — Flutter 设计令牌
|
||
|
||
生产前端使用 **Flutter**。本目录提供与 `../colors_and_type.css` **一一对应**的 Dart 令牌,Flutter 可直接消费。`ui_kits/` 下的 React/HTML 是**视觉规范参考**(像素级还原 + 交互),Flutter 实现以它们为蓝本、以本文件为令牌来源。
|
||
|
||
## 快速开始
|
||
1. 新建 Flutter 工程,把本目录的 `pubspec.yaml` 覆盖到根目录(按需改 `name`)。
|
||
2. 拷贝:`pangolin_theme.dart` → `lib/`;`widgets/` 整个目录 → `lib/widgets/`;`main.dart` → `lib/`;`assets/*.svg` → 工程 `assets/`。
|
||
3. 自备 4 款字体的 ttf 放 `fonts/`(或改用 `google_fonts` 包),族名须与 `pubspec.yaml` 一致。
|
||
4. `flutter pub get` → `flutter run`。`main.dart` 已串好「登录 → 引导 → 主框架」可直接跑。
|
||
|
||
## 文件
|
||
- `pubspec.yaml` — **工程清单模板**:已配好 `flutter_svg` / `lucide_icons` 依赖、4 个 SVG 资产、4 款字体声明(族名对齐 `PangolinFonts`)。拷到工程根目录,补字体 ttf,`flutter pub get` 即可。
|
||
- `main.dart` — **入口示例**:`runApp` + 明/暗主题 + 「登录 → 引导 → 主框架」`RootFlow` 串接,可直接跑通。
|
||
- `pangolin_theme.dart` — 全部令牌 + 明/暗 `ThemeData`:
|
||
- `PangolinColors` — clay / sand / 语义色阶(const `Color`)
|
||
- `PangolinScheme`(`ThemeExtension`)— 语义令牌(bg/surface/fg/accent/border/success…),含 `.light` / `.dark`
|
||
- `PangolinSpacing`(4px 基准)、`PangolinRadius`、`PangolinMotion`(时长 + 缓动曲线)
|
||
- `PangolinFonts`、`PangolinText`(字号阶)、`PangolinShadow`(暖色软阴影)
|
||
- `PangolinTheme.light` / `PangolinTheme.dark` — 开箱即用
|
||
- `widgets/` — **核心组件 Dart 雏形**(纯样式,业务逻辑自接),全部读 `context.pangolin` 令牌:
|
||
- `pangolin_icons.dart` — **Lucide 图标映射表**:`PangolinIcons.power` 等直用常量 + `PangolinIcons.byName('shield-check')` 查表(从 React `data-lucide` 名移植)。需 `lucide_icons` 包。
|
||
- `pangolin_button.dart` — `PangolinButton`(primary / secondary / ghost / danger,胶囊形)
|
||
- `country_code.dart` — `CountryCode`(2 字母国家码块)、`SignalBars`(延迟信号条)
|
||
- `status_pill.dart` — `StatusPill`(连接态 / PRO 等色点胶囊)
|
||
- `connect_button.dart` — `ConnectButton`(核心连接键三态:off 轨道环 / connecting 旋转弧 / on 满环 + 计时)
|
||
- `server_tile.dart` — `ServerTile` + `ServerInfo`(服务器列表行)
|
||
- `plan_card.dart` — `PlanCard`(套餐卡,专业版渐变高亮 + 「最受欢迎」浮标)
|
||
- `auth_screen.dart` — `AuthScreen`(登录 / 邮箱验证码注册,分屏式,带 `zh` 简单 i18n)
|
||
- `onboarding_screen.dart` — `OnboardingScreen`(首次引导 `PageView`,3 屏可滑动 + 进度点 + 跳过)
|
||
- `home_shell.dart` — `HomeShell`(主框架:底部 4 Tab 连接/节点/统计/账户 + 连接状态机 + 计时;各页骨架)
|
||
- `account_screens.dart` — 账户子页:`PlansScreen`(套餐选择)、`DevicesScreen`(设备管理 + 移除)、`RedeemScreen`(兑换码 + 购买渠道)、`ContactScreen`(联系渠道 + 服务时间);均为带返回栏的独立页,`HomeShell` 账户页已 `push` 接入
|
||
- `pangolin_logo.dart` — `PangolinMark` / `PangolinBrandLockup` / `PangolinWordmark` / `PangolinAppIcon`(`flutter_svg` 加载 `assets/` 矢量 logo,深色自动反白)
|
||
- `pangolin_widgets.dart` — 统一 `export`
|
||
> 这些是**视觉雏形**:对应 React UI Kit 的同名组件,Flutter 工程师可直接拷贝/微调,接上真实状态与导航。图标已走 `PangolinIcons`(Lucide),与设计一致。
|
||
|
||
## 接入
|
||
```dart
|
||
MaterialApp(
|
||
theme: PangolinTheme.light,
|
||
darkTheme: PangolinTheme.dark,
|
||
themeMode: ThemeMode.system, // 跟随系统;也可由设置里的开关控制
|
||
);
|
||
```
|
||
|
||
读语义色(随明暗自动切换):
|
||
```dart
|
||
final c = context.pangolin; // PangolinScheme
|
||
Container(color: c.surface);
|
||
Text('已连接', style: PangolinText.h3.copyWith(color: c.success));
|
||
```
|
||
|
||
令牌直取:
|
||
```dart
|
||
PangolinColors.clay500 // 品牌主色
|
||
PangolinSpacing.x4 // 16
|
||
BorderRadius.circular(PangolinRadius.lg)
|
||
AnimatedContainer(duration: PangolinMotion.base, curve: PangolinMotion.easeOut, ...)
|
||
```
|
||
|
||
组件雏形(组合示例):
|
||
```dart
|
||
import 'widgets/pangolin_widgets.dart';
|
||
|
||
// 连接键
|
||
ConnectButton(status: VpnStatus.on, elapsed: const Duration(seconds: 8048), onTap: toggle);
|
||
|
||
// 服务器行
|
||
ServerTile(
|
||
server: const ServerInfo(code: 'HK', name: '香港 · 流媒体', sub: 'Hong Kong', ping: 18),
|
||
active: true, onTap: () {},
|
||
);
|
||
|
||
// 套餐卡(专业版高亮)
|
||
PlanCard(
|
||
name: '专业版', price: '¥25', period: '/月', popularLabel: '最受欢迎', featured: true,
|
||
features: const ['80+ 全球节点', '无限流量 · 极速', '5 台设备同时在线'],
|
||
ctaLabel: '立即升级', onPressed: () {},
|
||
);
|
||
|
||
PangolinButton(label: '连接', icon: PangolinIcons.power, onPressed: () {});
|
||
StatusPill(label: '已连接', status: PangolinStatus.connected);
|
||
```
|
||
|
||
页面串接(登录 → 引导 → 主应用):
|
||
```dart
|
||
enum AppStage { auth, onboarding, app }
|
||
|
||
class _RootState extends State<Root> {
|
||
AppStage stage = AppStage.auth;
|
||
@override
|
||
Widget build(BuildContext context) => switch (stage) {
|
||
AppStage.auth => AuthScreen(onDone: () => setState(() => stage = AppStage.onboarding)),
|
||
AppStage.onboarding => OnboardingScreen(onDone: () => setState(() => stage = AppStage.app)),
|
||
AppStage.app => const HomeShell(), // 主框架:底部 4 Tab(连接/节点/统计/账户)
|
||
};
|
||
}
|
||
```
|
||
|
||
## 字体
|
||
在 `pubspec.yaml` 注册 **Sora**(display)、**Manrope**(正文/UI)、**Noto Sans SC**(中文)、**JetBrains Mono**(数据)。可用 `google_fonts` 包或打包本地字体;族名见 `PangolinFonts`。
|
||
|
||
## 图标
|
||
UI Kit 用 Lucide(细线条)。Flutter 侧用 [`lucide_icons`](https://pub.dev/packages/lucide_icons) 包,经 `widgets/pangolin_icons.dart` 的映射表引用:`Icon(PangolinIcons.power)`。`pubspec.yaml` 加 `lucide_icons: ^0.x`。某常量名若在你的包版本缺失,按 IDE 提示替换为最接近名即可(文件内已注明 Lucide 原名)。
|
||
|
||
## Logo / 品牌标(SVG)
|
||
矢量 logo 在 `assets/`(`logo-mark.svg` clay 标、`logo-mark-white.svg` 反白标、`logo-wordmark.svg` 字标、`app-icon.svg` App 图标)。用 [`flutter_svg`](https://pub.dev/packages/flutter_svg) 加载,封装在 `widgets/pangolin_logo.dart`:
|
||
- `PangolinMark(size: 28)` — 仅标记,**深色主题自动用反白版**(可 `forceLight`/`forceDark`)
|
||
- `PangolinBrandLockup(zh: true)` — 标记 + 「穿山甲 / Pangolin」(随主题变色 + 双语,顶栏用)
|
||
- `PangolinWordmark(height: 28)` — 横版字标锁版(浅背景)
|
||
- `PangolinAppIcon(size: 64)` — App 图标(自动圆角)
|
||
|
||
接入步骤:
|
||
1. `pubspec.yaml` 加依赖与资产:
|
||
```yaml
|
||
dependencies:
|
||
flutter_svg: ^2.0.0
|
||
flutter:
|
||
assets:
|
||
- assets/logo-mark.svg
|
||
- assets/logo-mark-white.svg
|
||
- assets/logo-wordmark.svg
|
||
- assets/app-icon.svg
|
||
```
|
||
2. 把本目录的 `assets/*.svg` 拷进你工程的 `assets/`(若用别的前缀,改 `pangolin_logo.dart` 顶部的 `_base`)。
|
||
3. `AuthScreen` / `HomeShell` 顶栏已用 `PangolinMark` / `PangolinBrandLockup`,无需再改。
|
||
4. App 启动图标 / 桌面图标用 `app-icon.svg` 导出 PNG(`flutter_launcher_icons` 包)。
|
||
|
||
## 规则(务必遵守)
|
||
- 颜色只用语义令牌,组件天然适配明/暗,不要硬编码十六进制。
|
||
- 暖色基调:表面是暖白/暖 espresso,**不要纯白纯黑**大面积填充。
|
||
- 圆角偏大、阴影柔和暖调;状态用「色点 + 文字」,不用 emoji;国家用 2 字母码块,不用 emoji 国旗。
|
||
- 界面单语言显示(中文**或** EN),由设置切换;不要中英并排。
|
||
- App 内不放支付表单;走兑换码 + 外部渠道。
|
||
|
||
> ⚠️ 字体均为开源字体(Google Fonts),作为本品牌正式选定字体。若你已有授权品牌字体,替换族名与文件即可。
|