Files
AI-Health/health_app/lib/widgets/app_menu_item.dart
MingNian 58af5f6d5b feat: UI 清新风全面改造 — 朝露主题 + shadcn_ui + 全局字号放大
- 全新"朝露"主题:深青绿主色(#2D6A4F),暖白底,完整设计Token
- 引入 shadcn_ui 组件库,MaterialApp 注入 ShadTheme
- 新增 4 个公共组件:AppCard、AppMenuItem、AppEmptyState、AppTabChip
- 全面消除硬编码颜色,统一使用 AppTheme Token
- 全局字号 +3~4pt,图标等比放大 +3px
- home/medication/profile/settings/login 等核心页面重写
- 路由和功能逻辑零改动
2026-06-08 18:06:18 +08:00

68 lines
2.3 KiB
Dart
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.

import 'package:flutter/material.dart';
import 'package:shadcn_ui/shadcn_ui.dart';
import '../core/app_theme.dart';
/// 统一菜单项profile_page 和 settings_pages 都共用这个
class AppMenuItem extends StatelessWidget {
final IconData icon;
final String title;
final String? subtitle;
final String? trailing;
final VoidCallback? onTap;
const AppMenuItem({
super.key,
required this.icon,
required this.title,
this.subtitle,
this.trailing,
this.onTap,
});
@override
Widget build(BuildContext context) {
final theme = ShadTheme.of(context);
return GestureDetector(
onTap: onTap,
behavior: HitTestBehavior.opaque,
child: Container(
margin: const EdgeInsets.symmetric(horizontal: 24, vertical: 2),
padding: const EdgeInsets.symmetric(horizontal: 4, vertical: 14),
decoration: BoxDecoration(
color: theme.colorScheme.card,
borderRadius: BorderRadius.circular(AppTheme.rSm),
),
child: Row(children: [
Container(
width: 38,
height: 38,
decoration: BoxDecoration(
color: AppTheme.primaryLight,
borderRadius: BorderRadius.circular(AppTheme.rSm),
),
child: Icon(icon, size: 22, color: AppTheme.primary),
),
const SizedBox(width: AppTheme.sLg),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(title, style: TextStyle(fontSize: 19, fontWeight: FontWeight.w500, color: theme.colorScheme.foreground)),
if (subtitle != null && subtitle!.isNotEmpty)
Padding(
padding: const EdgeInsets.only(top: 2),
child: Text(subtitle!, style: TextStyle(fontSize: 16, color: theme.colorScheme.mutedForeground)),
),
],
),
),
if (trailing != null && trailing!.isNotEmpty)
Text(trailing!, style: TextStyle(fontSize: 17, color: theme.colorScheme.mutedForeground)),
const SizedBox(width: 4),
Icon(LucideIcons.chevronRight, size: 21, color: theme.colorScheme.mutedForeground),
]),
),
);
}
}