Files
pangolin/client/lib/widgets/content_top_bar.dart
wangjia 281a6261fb feat(client): tablet 外壳 + 视觉 diff 工作流文档
- tablet_shell: 侧栏 232·4 项触控(minHeight 48, 字号 15) + 顶栏无主题切换 + 连接页双栏
  对照 ui_kits/tablet/tabapp.jsx;home_shell 分发 tablet→TabletShell
- nav_sidebar 加 dense 参数(desktop 紧凑 / tablet 触控)
- content_top_bar 加 showThemeToggle + titleSize 参数
- tool/visual-diff.md: 截图 diff 工作流(design-distill 工具)+ 实现侧三路径
  现状(golden 被 google_fonts 阻塞 / screencapture 受 macOS chrome 限制)+ 推荐

注: tablet 形态在 macOS 桌面平台不触发(只 desktop/mobile),运行验证需 iPad。

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-16 09:38:18 +08:00

71 lines
2.6 KiB
Dart
Raw Permalink 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.
// content_top_bar.dart — desktop/tablet 内容区顶栏(标题 + 在线状态 + 主题切换)
//
// 对照 ui_kits/desktop/dapp.jsxheight 52、下边框;左标题(display 17)
// 右「● 已连接 CODE / ○ 未连接」(mono 12) + moon/sun 主题切换。
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../pangolin_theme.dart';
import '../state/app_providers.dart';
import '../state/connection_provider.dart';
import '../state/nodes_provider.dart';
import 'pangolin_icons.dart';
class ContentTopBar extends ConsumerWidget {
const ContentTopBar({super.key, required this.title, this.onBack, this.showThemeToggle = true, this.titleSize = 17});
final String title;
final VoidCallback? onBack;
final bool showThemeToggle;
final double titleSize;
@override
Widget build(BuildContext context, WidgetRef ref) {
final c = context.pangolin;
final conn = ref.watch(connectionProvider);
final node = ref.watch(effectiveNodeProvider);
final mode = ref.watch(themeModeProvider);
final isDark = mode == ThemeMode.dark;
return Container(
height: 52,
padding: const EdgeInsets.symmetric(horizontal: 24),
decoration: BoxDecoration(border: Border(bottom: BorderSide(color: c.border))),
child: Row(children: [
if (onBack != null) ...[
IconButton(
onPressed: onBack,
icon: Icon(PangolinIcons.arrowLeft, size: 20, color: c.fg1),
padding: EdgeInsets.zero,
constraints: const BoxConstraints(minWidth: 32, minHeight: 32),
),
const SizedBox(width: 4),
],
Text(title,
style: PangolinText.h3.copyWith(color: c.fg1, fontWeight: FontWeight.w700, fontSize: titleSize)),
const Spacer(),
Text(
conn.phase == VpnPhase.on ? '${node.code}' : '',
style: PangolinText.mono.copyWith(
fontSize: 12,
fontWeight: FontWeight.w600,
color: conn.phase == VpnPhase.on ? c.success : c.fg3,
),
),
if (showThemeToggle) ...[
const SizedBox(width: 12),
InkWell(
onTap: () => ref.read(themeModeProvider.notifier).state =
isDark ? ThemeMode.light : ThemeMode.dark,
borderRadius: BorderRadius.circular(PangolinRadius.sm),
child: Padding(
padding: const EdgeInsets.all(6),
child: Icon(isDark ? PangolinIcons.sun : PangolinIcons.moon, size: 18, color: c.fg2),
),
),
],
]),
);
}
}