diff --git a/flutter_monisuo/lib/core/theme/app_color_scheme.dart b/flutter_monisuo/lib/core/theme/app_color_scheme.dart index 4ae466f..2bc62eb 100644 --- a/flutter_monisuo/lib/core/theme/app_color_scheme.dart +++ b/flutter_monisuo/lib/core/theme/app_color_scheme.dart @@ -1,118 +1,171 @@ import 'package:flutter/material.dart'; import 'package:shadcn_ui/shadcn_ui.dart'; -/// 现代化颜色系统 - 支持明暗主题 +/// "The Kinetic Vault" & "The Ethereal Terminal" 双主题颜色系统 +/// +/// 深色主题: "The Kinetic Vault" - 高端加密编辑风格 +/// 浅色主题: "The Ethereal Terminal" - 高端金融科技风格 /// /// 设计原则: -/// - Vercel/Linear 风格的现代简约设计 -/// - 深色主题:#0A0A0B 背景,微妙阴影 -/// - 浅色主题:纯白背景,清晰边框 -/// - 所有对比度 >= 4.5:1 (WCAG AA) +/// - 无边框规则: 禁止 1px solid 边框,使用层次色变化 +/// - 层次化设计: 通过 surface-container 层次而非阴影 +/// - 渐变 CTA: primary → primary_container (135度) class AppColorScheme { AppColorScheme._(); // ============================================ - // 品牌色 - 青绿色 (明暗通用) + // 深色主题 - "The Kinetic Vault" // ============================================ - /// 主品牌色 - 深色主题 - static const Color primaryDark = Color(0xFF00D4AA); + /// 背景基色 - 最深 + static const Color darkBackground = Color(0xFF0b0e14); - /// 主品牌色 - 浅色主题 - static const Color primaryLight = Color(0xFF00B894); + /// Surface 层次 (从低到高) + static const Color darkSurfaceLowest = Color(0xFF0d1017); + static const Color darkSurfaceLow = Color(0xFF10131a); + static const Color darkSurface = Color(0xFF151921); + static const Color darkSurfaceHigh = Color(0xFF1a1f2a); + static const Color darkSurfaceHighest = Color(0xFF22262f); + + /// Ghost Border - 后备边框 + static const Color darkOutlineVariant = Color(0xFF45484f); + + /// Primary - Neon Blue (主要交互) + static const Color darkPrimary = Color(0xFF72dcff); + static const Color darkPrimaryContainer = Color(0xFF4ac8f0); + + /// Secondary - Electric Purple (次要强调) + static const Color darkSecondary = Color(0xFFdd8bfb); + static const Color darkSecondaryContainer = Color(0xFF2d1f3d); + + /// Tertiary - Emerald Green (仅用于成功/盈利/买入) + static const Color darkTertiary = Color(0xFFafffd1); + static const Color darkTertiaryContainer = Color(0xFF1a3d2d); + + /// 文本色 + static const Color darkOnSurface = Color(0xFFecedf6); + static const Color darkOnSurfaceVariant = Color(0xFFa9abb3); + static const Color darkOnSurfaceMuted = Color(0xFF6b6d75); // ============================================ - // 语义色 - 涨跌 (明暗通用) + // 浅色主题 - "The Ethereal Terminal" // ============================================ - /// 涨/买入 - 绿色 - static const Color up = Color(0xFF00C853); + /// 背景基色 - 珍珠白 + static const Color lightBackground = Color(0xFFf5f7f9); - /// 跌/卖出 - 红色 + /// Surface 层次 (从低到高) + static const Color lightSurfaceLowest = Color(0xFFffffff); // Elevated (pop) + static const Color lightSurfaceLow = Color(0xFFeef1f3); // Softly recessed + static const Color lightSurface = Color(0xFFf5f7f9); // Base canvas + static const Color lightSurfaceHigh = Color(0xFFe8ebef); // Elevated + static const Color lightSurfaceHighest = Color(0xFFd9dde0); // Navigation anchor + + /// Ghost Border + static const Color lightOutlineVariant = Color(0xFFc4c8cc); + + /// Primary - Plasma (主要交互) + static const Color lightPrimary = Color(0xFF0050d4); + static const Color lightPrimaryContainer = Color(0xFF7b9cff); + + /// Secondary - Pulse indicator + static const Color lightSecondary = Color(0xFF8319da); + static const Color lightSecondaryContainer = Color(0xFFe8d4fa); + + /// Tertiary - Success (买入/盈利) + static const Color lightTertiary = Color(0xFF00a878); + static const Color lightTertiaryContainer = Color(0xFFd4f5e9); + + /// 文本色 + static const Color lightOnSurface = Color(0xFF2c2f31); + static const Color lightOnSurfaceVariant = Color(0xFF5a5d60); + static const Color lightOnSurfaceMuted = Color(0xFF8a8d90); + + // ============================================ + // 语义色 - 明暗通用 + // ============================================ + + /// 涨/买入/成功 + static const Color up = darkTertiary; + static const Color success = darkTertiary; + + /// 跌/卖出/错误 static const Color down = Color(0xFFFF5252); - - /// 成功 - static const Color success = Color(0xFF00C853); + static const Color error = down; /// 警告 static const Color warning = Color(0xFFFF9800); - /// 错误 - static const Color error = Color(0xFFFF5252); - /// 信息 static const Color info = Color(0xFF2196F3); // ============================================ - // 深色主题颜色 (Vercel/Linear 风格) + // 渐变预设 // ============================================ - static const Color _darkBackground = Color(0xFF0A0A0B); - static const Color _darkCardBackground = Color(0xFF111113); - static const Color _darkSecondary = Color(0xFF1C1C1F); - static const Color _darkMuted = Color(0xFF27272A); - static const Color _darkBorder = Color(0xFF27272A); - static const Color _darkTextPrimary = Color(0xFFFFFFFF); - static const Color _darkTextSecondary = Color(0xFFA1A1AA); - static const Color _darkTextHint = Color(0xFF71717A); + /// 深色 CTA 渐变 (primary → primary_container, 135度) + static const LinearGradient darkCtaGradient = LinearGradient( + colors: [darkPrimary, darkPrimaryContainer], + begin: Alignment(-0.7, -0.7), + end: Alignment(0.7, 0.7), + ); - // ============================================ - // 浅色主题颜色 - // ============================================ + /// 浅色 CTA 渐变 (Plasma) + static const LinearGradient lightCtaGradient = LinearGradient( + colors: [lightPrimary, lightPrimaryContainer], + begin: Alignment(-0.7, -0.7), + end: Alignment(0.7, 0.7), + ); - static const Color _lightBackground = Color(0xFFFFFFFF); - static const Color _lightCardBackground = Color(0xFFFAFAFA); - static const Color _lightSecondary = Color(0xFFF4F4F5); - static const Color _lightMuted = Color(0xFFE4E4E7); - static const Color _lightBorder = Color(0xFFE4E4E7); - static const Color _lightTextPrimary = Color(0xFF0A0A0B); - static const Color _lightTextSecondary = Color(0xFF52525B); - static const Color _lightTextHint = Color(0xFF71717A); + /// 兼容别名 + static const LinearGradient ctaGradient = darkCtaGradient; + + /// 买入按钮渐变 + static const LinearGradient buyGradient = LinearGradient( + colors: [darkTertiary, Color(0xFF7de8b8)], + begin: Alignment(-0.7, -0.7), + end: Alignment(0.7, 0.7), + ); + + /// 卖出按钮渐变 + static const LinearGradient sellGradient = LinearGradient( + colors: [down, Color(0xFFe84545)], + begin: Alignment(-0.7, -0.7), + end: Alignment(0.7, 0.7), + ); + + /// 资产卡片渐变 + static const LinearGradient assetCardGradient = LinearGradient( + colors: [darkPrimary, darkSecondary], + begin: Alignment.topLeft, + end: Alignment.bottomRight, + ); // ============================================ // Shadcn ColorScheme - 深色主题 // ============================================ static ShadColorScheme get darkShad => ShadColorScheme( - // 背景与前景 - background: _darkBackground, - foreground: _darkTextPrimary, - - // 卡片 - card: _darkCardBackground, - cardForeground: _darkTextPrimary, - - // 弹出层 - popover: _darkCardBackground, - popoverForeground: _darkTextPrimary, - - // 主色 - primary: primaryDark, - primaryForeground: _darkTextPrimary, - - // 次要色 - secondary: _darkSecondary, - secondaryForeground: _darkTextPrimary, - - // 静音色 - muted: _darkMuted, - mutedForeground: _darkTextSecondary, - - // 强调色 - accent: primaryDark.withValues(alpha: 0.15), - accentForeground: primaryDark, - - // 危险色 + background: darkBackground, + foreground: darkOnSurface, + card: darkSurface, + cardForeground: darkOnSurface, + popover: darkSurfaceHigh, + popoverForeground: darkOnSurface, + primary: darkPrimary, + primaryForeground: darkBackground, + secondary: darkSecondary, + secondaryForeground: darkOnSurface, + muted: darkSurfaceHigh, + mutedForeground: darkOnSurfaceVariant, + accent: darkPrimary.withValues(alpha: 0.15), + accentForeground: darkPrimary, destructive: error, - destructiveForeground: _darkTextPrimary, - - // 边框与输入 - border: _darkBorder, - input: _darkBorder, - ring: primaryDark, - - // 选择色 - selection: primaryDark.withValues(alpha: 0.3), + destructiveForeground: darkOnSurface, + border: darkOutlineVariant.withValues(alpha: 0.15), + input: darkOutlineVariant.withValues(alpha: 0.15), + ring: darkPrimary, + selection: darkPrimary.withValues(alpha: 0.3), ); // ============================================ @@ -120,45 +173,26 @@ class AppColorScheme { // ============================================ static ShadColorScheme get lightShad => ShadColorScheme( - // 背景与前景 - background: _lightBackground, - foreground: _lightTextPrimary, - - // 卡片 - card: _lightCardBackground, - cardForeground: _lightTextPrimary, - - // 弹出层 - popover: _lightBackground, - popoverForeground: _lightTextPrimary, - - // 主色 - primary: primaryLight, - primaryForeground: _lightBackground, - - // 次要色 - secondary: _lightSecondary, - secondaryForeground: _lightTextPrimary, - - // 静音色 - muted: _lightMuted, - mutedForeground: _lightTextSecondary, - - // 强调色 - accent: primaryLight.withValues(alpha: 0.15), - accentForeground: primaryLight, - - // 危险色 + background: lightBackground, + foreground: lightOnSurface, + card: lightSurfaceLowest, + cardForeground: lightOnSurface, + popover: lightSurfaceLowest, + popoverForeground: lightOnSurface, + primary: lightPrimary, + primaryForeground: Color(0xFFFFFFFF), + secondary: lightSecondary, + secondaryForeground: lightOnSurface, + muted: lightSurfaceHigh, + mutedForeground: lightOnSurfaceVariant, + accent: lightPrimary.withValues(alpha: 0.1), + accentForeground: lightPrimary, destructive: error, - destructiveForeground: _lightBackground, - - // 边框与输入 - border: _lightBorder, - input: _lightBorder, - ring: primaryLight, - - // 选择色 - selection: primaryLight.withValues(alpha: 0.3), + destructiveForeground: Color(0xFFFFFFFF), + border: lightOutlineVariant.withValues(alpha: 0.5), + input: lightOutlineVariant.withValues(alpha: 0.3), + ring: lightPrimary, + selection: lightPrimary.withValues(alpha: 0.2), ); // ============================================ @@ -166,15 +200,22 @@ class AppColorScheme { // ============================================ static ColorScheme get darkMaterial => ColorScheme.dark( - primary: primaryDark, - onPrimary: _darkTextPrimary, - secondary: _darkSecondary, - onSecondary: _darkTextPrimary, + primary: darkPrimary, + onPrimary: darkBackground, + secondary: darkSecondary, + onSecondary: darkOnSurface, + tertiary: darkTertiary, + onTertiary: darkBackground, error: error, - onError: _darkTextPrimary, - surface: _darkCardBackground, - onSurface: _darkTextPrimary, - surfaceContainerHighest: _darkBackground, + onError: darkOnSurface, + surface: darkSurface, + onSurface: darkOnSurface, + surfaceContainerLowest: darkSurfaceLowest, + surfaceContainerLow: darkSurfaceLow, + surfaceContainer: darkSurface, + surfaceContainerHigh: darkSurfaceHigh, + surfaceContainerHighest: darkSurfaceHighest, + outlineVariant: darkOutlineVariant, ); // ============================================ @@ -182,16 +223,81 @@ class AppColorScheme { // ============================================ static ColorScheme get lightMaterial => ColorScheme.light( - primary: primaryLight, - onPrimary: _lightBackground, - secondary: _lightSecondary, - onSecondary: _lightTextPrimary, + primary: lightPrimary, + onPrimary: Color(0xFFFFFFFF), + secondary: lightSecondary, + onSecondary: Color(0xFFFFFFFF), + tertiary: lightTertiary, + onTertiary: Color(0xFFFFFFFF), error: error, - onError: _lightBackground, - surface: _lightCardBackground, - onSurface: _lightTextPrimary, - surfaceContainerHighest: _lightBackground, + onError: Color(0xFFFFFFFF), + surface: lightSurface, + onSurface: lightOnSurface, + surfaceContainerLowest: lightSurfaceLowest, + surfaceContainerLow: lightSurfaceLow, + surfaceContainer: lightSurface, + surfaceContainerHigh: lightSurfaceHigh, + surfaceContainerHighest: lightSurfaceHighest, + outlineVariant: lightOutlineVariant, ); + + // ============================================ + // 兼容性常量 (已废弃,保留向后兼容) + // ============================================ + + @Deprecated('Use darkPrimary instead') + static const Color primaryDark = darkPrimary; + + @Deprecated('Use lightPrimary instead') + static const Color primaryLight = lightPrimary; + + @Deprecated('Use darkBackground instead') + static const Color _darkBackground = darkBackground; + + @Deprecated('Use darkSurface instead') + static const Color _darkCardBackground = darkSurface; + + @Deprecated('Use darkSurfaceHigh instead') + static const Color _darkSecondary = darkSurfaceHigh; + + @Deprecated('Use darkSurfaceHigh instead') + static const Color _darkMuted = darkSurfaceHigh; + + @Deprecated('Use darkOutlineVariant instead') + static const Color _darkBorder = darkOutlineVariant; + + @Deprecated('Use darkOnSurface instead') + static const Color _darkTextPrimary = darkOnSurface; + + @Deprecated('Use darkOnSurfaceVariant instead') + static const Color _darkTextSecondary = darkOnSurfaceVariant; + + @Deprecated('Use darkOnSurfaceMuted instead') + static const Color _darkTextHint = darkOnSurfaceMuted; + + @Deprecated('Use lightBackground instead') + static const Color _lightBackground = lightBackground; + + @Deprecated('Use lightSurfaceLowest instead') + static const Color _lightCardBackground = lightSurfaceLowest; + + @Deprecated('Use lightSurfaceHigh instead') + static const Color _lightSecondary = lightSurfaceHigh; + + @Deprecated('Use lightSurfaceHigh instead') + static const Color _lightMuted = lightSurfaceHigh; + + @Deprecated('Use lightOutlineVariant instead') + static const Color _lightBorder = lightOutlineVariant; + + @Deprecated('Use lightOnSurface instead') + static const Color _lightTextPrimary = lightOnSurface; + + @Deprecated('Use lightOnSurfaceVariant instead') + static const Color _lightTextSecondary = lightOnSurfaceVariant; + + @Deprecated('Use lightOnSurfaceMuted instead') + static const Color _lightTextHint = lightOnSurfaceMuted; } /// 创建 Shadcn 深色主题 diff --git a/flutter_monisuo/lib/core/theme/app_spacing.dart b/flutter_monisuo/lib/core/theme/app_spacing.dart index 4edc535..5cf9953 100644 --- a/flutter_monisuo/lib/core/theme/app_spacing.dart +++ b/flutter_monisuo/lib/core/theme/app_spacing.dart @@ -67,7 +67,13 @@ class AppSpacing { static SizedBox vertical(double spacing) => SizedBox(height: spacing); } -/// 圆角系统 - 基于 modernization-v2.md 规范 +/// 圆角系统 - "The Kinetic Vault" & "The Ethereal Terminal" 规范 +/// +/// 设计规则: +/// - 按钮: xxl (24px / 1.5rem) +/// - 卡片: xl (16px) +/// - 输入框: md (8px) +/// - 标签: sm (4px) class AppRadius { AppRadius._(); @@ -78,19 +84,19 @@ class AppRadius { /// 小圆角 - 4px (标签、小组件) static const double sm = 4.0; - /// 中圆角 - 8px (按钮、输入框) + /// 中圆角 - 8px (输入框) static const double md = 8.0; - /// 大圆角 - 12px (卡片) + /// 大圆角 - 12px (卡片 - 旧版) static const double lg = 12.0; /// 特大圆角 - 16px (大卡片) static const double xl = 16.0; - /// 超大圆角 - 24px (模态框、底部抽屉) + /// 超大圆角 - 24px (按钮、模态框、底部抽屉) static const double xxl = 24.0; - /// 圆形 - 9999px + /// 圆形 - 9999px (Pill buttons) static const double full = 9999.0; // ============================================ diff --git a/flutter_monisuo/lib/core/theme/app_theme.dart b/flutter_monisuo/lib/core/theme/app_theme.dart index 84e4663..8676a6f 100644 --- a/flutter_monisuo/lib/core/theme/app_theme.dart +++ b/flutter_monisuo/lib/core/theme/app_theme.dart @@ -3,294 +3,429 @@ import 'package:google_fonts/google_fonts.dart'; import 'app_color_scheme.dart'; import 'app_spacing.dart'; -/// 应用主题配置 - 基于 modernization-v2.md 规范 +/// "The Kinetic Vault" & "The Ethereal Terminal" 主题配置 class AppTheme { AppTheme._(); // ============================================ - // 深色主题 + // 深色主题 - "The Kinetic Vault" // ============================================ static ThemeData get darkTheme { return ThemeData( useMaterial3: true, brightness: Brightness.dark, - scaffoldBackgroundColor: AppColorScheme.darkShad.background, - primaryColor: AppColorScheme.primaryDark, + scaffoldBackgroundColor: AppColorScheme.darkBackground, + primaryColor: AppColorScheme.darkPrimary, colorScheme: AppColorScheme.darkMaterial, + + // AppBar - 无边框规则 appBarTheme: AppBarTheme( - backgroundColor: AppColorScheme.darkShad.background, - foregroundColor: AppColorScheme.darkShad.foreground, + backgroundColor: AppColorScheme.darkBackground, + foregroundColor: AppColorScheme.darkOnSurface, elevation: 0, + scrolledUnderElevation: 0, centerTitle: true, - titleTextStyle: GoogleFonts.inter( + titleTextStyle: GoogleFonts.spaceGrotesk( fontSize: 18, fontWeight: FontWeight.w600, - color: AppColorScheme.darkShad.foreground, + color: AppColorScheme.darkOnSurface, ), ), + + // 卡片 - 无边框,使用 surface 层次 + cardTheme: CardThemeData( + color: AppColorScheme.darkSurface, + elevation: 0, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(AppRadius.xl), + ), + ), + + // 输入框 - Ghost Border 风格 inputDecorationTheme: InputDecorationTheme( filled: true, - fillColor: AppColorScheme.darkShad.card, + fillColor: AppColorScheme.darkSurfaceLow, border: OutlineInputBorder( borderRadius: BorderRadius.circular(AppRadius.md), - borderSide: BorderSide(color: AppColorScheme.darkShad.border), + borderSide: BorderSide( + color: AppColorScheme.darkOutlineVariant.withValues(alpha: 0.15), + ), ), enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(AppRadius.md), - borderSide: BorderSide(color: AppColorScheme.darkShad.border), + borderSide: BorderSide( + color: AppColorScheme.darkOutlineVariant.withValues(alpha: 0.15), + ), ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(AppRadius.md), - borderSide: BorderSide(color: AppColorScheme.primaryDark, width: 2), + borderSide: const BorderSide(color: AppColorScheme.darkPrimary, width: 2), ), - hintStyle: TextStyle(color: AppColorScheme.darkShad.mutedForeground), + hintStyle: TextStyle(color: AppColorScheme.darkOnSurfaceMuted), contentPadding: const EdgeInsets.symmetric( horizontal: AppSpacing.md, vertical: 14, ), ), + + // 按钮 - 渐变 CTA,大圆角 elevatedButtonTheme: ElevatedButtonThemeData( style: ElevatedButton.styleFrom( - backgroundColor: AppColorScheme.primaryDark, - foregroundColor: Colors.white, + backgroundColor: AppColorScheme.darkPrimary, + foregroundColor: AppColorScheme.darkBackground, minimumSize: const Size(double.infinity, 48), padding: const EdgeInsets.symmetric(vertical: 14), shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(AppRadius.md), + borderRadius: BorderRadius.circular(AppRadius.xxl), ), - textStyle: GoogleFonts.inter( + elevation: 0, + textStyle: GoogleFonts.manrope( fontSize: 16, fontWeight: FontWeight.w600, ), ), ), + textButtonTheme: TextButtonThemeData( style: TextButton.styleFrom( - foregroundColor: AppColorScheme.primaryDark, + foregroundColor: AppColorScheme.darkPrimary, ), ), + + // 分割线 - 使用层次而非边框 dividerTheme: DividerThemeData( - color: AppColorScheme.darkShad.border, + color: AppColorScheme.darkOutlineVariant.withValues(alpha: 0.1), thickness: 1, ), - cardTheme: CardThemeData( - color: AppColorScheme.darkShad.card, + + // 底部导航 + bottomNavigationBarTheme: BottomNavigationBarThemeData( + backgroundColor: AppColorScheme.darkSurface, + selectedItemColor: AppColorScheme.darkPrimary, + unselectedItemColor: AppColorScheme.darkOnSurfaceVariant, + type: BottomNavigationBarType.fixed, elevation: 0, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(AppRadius.lg), - ), ), ); } // ============================================ - // 浅色主题 + // 浅色主题 - "The Ethereal Terminal" // ============================================ static ThemeData get lightTheme { return ThemeData( useMaterial3: true, brightness: Brightness.light, - scaffoldBackgroundColor: AppColorScheme.lightShad.background, - primaryColor: AppColorScheme.primaryLight, + scaffoldBackgroundColor: AppColorScheme.lightBackground, + primaryColor: AppColorScheme.lightPrimary, colorScheme: AppColorScheme.lightMaterial, + + // AppBar - 珍珠白 appBarTheme: AppBarTheme( - backgroundColor: AppColorScheme.lightShad.background, - foregroundColor: AppColorScheme.lightShad.foreground, + backgroundColor: AppColorScheme.lightBackground, + foregroundColor: AppColorScheme.lightOnSurface, elevation: 0, + scrolledUnderElevation: 0, centerTitle: true, - titleTextStyle: GoogleFonts.inter( + titleTextStyle: GoogleFonts.spaceGrotesk( fontSize: 18, fontWeight: FontWeight.w600, - color: AppColorScheme.lightShad.foreground, + color: AppColorScheme.lightOnSurface, ), ), + + // 卡片 - Elevated (pop) on pearl background + cardTheme: CardThemeData( + color: AppColorScheme.lightSurfaceLowest, + elevation: 0, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(AppRadius.xl), + ), + ), + + // 输入框 - 底部线条风格 inputDecorationTheme: InputDecorationTheme( filled: true, - fillColor: AppColorScheme.lightShad.card, - border: OutlineInputBorder( + fillColor: AppColorScheme.lightSurfaceLow, + border: UnderlineInputBorder( borderRadius: BorderRadius.circular(AppRadius.md), - borderSide: BorderSide(color: AppColorScheme.lightShad.border), + borderSide: BorderSide( + color: AppColorScheme.lightOutlineVariant.withValues(alpha: 0.5), + width: 2, + ), ), - enabledBorder: OutlineInputBorder( + enabledBorder: UnderlineInputBorder( borderRadius: BorderRadius.circular(AppRadius.md), - borderSide: BorderSide(color: AppColorScheme.lightShad.border), + borderSide: BorderSide( + color: AppColorScheme.lightOutlineVariant.withValues(alpha: 0.5), + width: 2, + ), ), - focusedBorder: OutlineInputBorder( + focusedBorder: UnderlineInputBorder( borderRadius: BorderRadius.circular(AppRadius.md), - borderSide: BorderSide(color: AppColorScheme.primaryLight, width: 2), + borderSide: const BorderSide(color: AppColorScheme.lightPrimary, width: 2), ), - hintStyle: TextStyle(color: AppColorScheme.lightShad.mutedForeground), + hintStyle: TextStyle(color: AppColorScheme.lightOnSurfaceMuted), contentPadding: const EdgeInsets.symmetric( horizontal: AppSpacing.md, vertical: 14, ), ), + + // 按钮 - Plasma 渐变,full 圆角 elevatedButtonTheme: ElevatedButtonThemeData( style: ElevatedButton.styleFrom( - backgroundColor: AppColorScheme.primaryLight, - foregroundColor: Colors.white, + backgroundColor: AppColorScheme.lightPrimary, + foregroundColor: const Color(0xFFFFFFFF), minimumSize: const Size(double.infinity, 48), padding: const EdgeInsets.symmetric(vertical: 14), shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(AppRadius.md), + borderRadius: BorderRadius.circular(AppRadius.xxl), ), - textStyle: GoogleFonts.inter( + elevation: 0, + textStyle: GoogleFonts.manrope( fontSize: 16, fontWeight: FontWeight.w600, ), ), ), + textButtonTheme: TextButtonThemeData( style: TextButton.styleFrom( - foregroundColor: AppColorScheme.primaryLight, + foregroundColor: AppColorScheme.lightPrimary, ), ), + + // 分割线 - 不使用,用留白代替 dividerTheme: DividerThemeData( - color: AppColorScheme.lightShad.border, + color: AppColorScheme.lightOutlineVariant.withValues(alpha: 0.2), thickness: 1, ), - cardTheme: CardThemeData( - color: AppColorScheme.lightShad.card, + + // 底部导航 + bottomNavigationBarTheme: BottomNavigationBarThemeData( + backgroundColor: AppColorScheme.lightSurfaceHighest, + selectedItemColor: AppColorScheme.lightPrimary, + unselectedItemColor: AppColorScheme.lightOnSurfaceVariant, + type: BottomNavigationBarType.fixed, elevation: 0, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(AppRadius.lg), - ), ), ); } } -/// 文本样式 - 使用 Google Fonts +/// "The Kinetic Vault" & "The Ethereal Terminal" 文字样式系统 +/// +/// Display/Headlines: Space Grotesk (编辑风格) +/// Body/Labels: Manrope (实用风格) class AppTextStyles { AppTextStyles._(); // ============================================ - // 标题样式 - Inter 字体 + // Display - 编辑风格 (Space Grotesk) // ============================================ - static TextStyle displayLarge(BuildContext context) => GoogleFonts.inter( - fontSize: 32, + /// D1 - 大标题 (48px) - Hero moments + static TextStyle displayLarge(BuildContext context) => GoogleFonts.spaceGrotesk( + fontSize: 48, fontWeight: FontWeight.w700, color: Theme.of(context).colorScheme.onSurface, + height: 1.1, + letterSpacing: -0.02, ); - static TextStyle displayMedium(BuildContext context) => GoogleFonts.inter( + /// D2 - 中标题 (36px) + static TextStyle displayMedium(BuildContext context) => GoogleFonts.spaceGrotesk( + fontSize: 36, + fontWeight: FontWeight.w600, + color: Theme.of(context).colorScheme.onSurface, + height: 1.2, + letterSpacing: -0.01, + ); + + /// D3 - 小标题 (28px) + static TextStyle displaySmall(BuildContext context) => GoogleFonts.spaceGrotesk( + fontSize: 28, + fontWeight: FontWeight.w600, + color: Theme.of(context).colorScheme.onSurface, + height: 1.25, + ); + + // ============================================ + // Headline - 编辑风格 (Space Grotesk) + // ============================================ + + static TextStyle headlineLarge(BuildContext context) => GoogleFonts.spaceGrotesk( fontSize: 24, fontWeight: FontWeight.w600, color: Theme.of(context).colorScheme.onSurface, + height: 1.3, ); - static TextStyle displaySmall(BuildContext context) => GoogleFonts.inter( + static TextStyle headlineMedium(BuildContext context) => GoogleFonts.spaceGrotesk( fontSize: 20, fontWeight: FontWeight.w600, color: Theme.of(context).colorScheme.onSurface, + height: 1.35, + ); + + static TextStyle headlineSmall(BuildContext context) => GoogleFonts.spaceGrotesk( + fontSize: 18, + fontWeight: FontWeight.w500, + color: Theme.of(context).colorScheme.onSurface, + height: 1.4, ); // ============================================ - // 正文样式 - Inter 字体 + // Body - 实用风格 (Manrope) // ============================================ - static TextStyle bodyLarge(BuildContext context) => GoogleFonts.inter( + static TextStyle bodyLarge(BuildContext context) => GoogleFonts.manrope( fontSize: 16, fontWeight: FontWeight.w400, color: Theme.of(context).colorScheme.onSurface, + height: 1.5, ); - static TextStyle bodyMedium(BuildContext context) => GoogleFonts.inter( + static TextStyle bodyMedium(BuildContext context) => GoogleFonts.manrope( fontSize: 14, fontWeight: FontWeight.w400, color: Theme.of(context).colorScheme.onSurface, + height: 1.5, ); - static TextStyle bodySmall(BuildContext context) => GoogleFonts.inter( + static TextStyle bodySmall(BuildContext context) => GoogleFonts.manrope( fontSize: 12, fontWeight: FontWeight.w400, - color: Theme.of(context).colorScheme.onSurface, + color: Theme.of(context).colorScheme.onSurfaceVariant, + height: 1.45, ); // ============================================ - // 数字样式 - JetBrains Mono 等宽字体 + // Label - 实用风格 (Manrope) // ============================================ - static TextStyle numberLarge(BuildContext context) => GoogleFonts.jetBrainsMono( - fontSize: 20, - fontWeight: FontWeight.w600, - color: Theme.of(context).colorScheme.onSurface, - ); - - static TextStyle numberMedium(BuildContext context) => GoogleFonts.jetBrainsMono( - fontSize: 16, - fontWeight: FontWeight.w500, - color: Theme.of(context).colorScheme.onSurface, - ); - - static TextStyle numberSmall(BuildContext context) => GoogleFonts.jetBrainsMono( + static TextStyle labelLarge(BuildContext context) => GoogleFonts.manrope( fontSize: 14, fontWeight: FontWeight.w500, color: Theme.of(context).colorScheme.onSurface, + height: 1.4, + ); + + static TextStyle labelMedium(BuildContext context) => GoogleFonts.manrope( + fontSize: 12, + fontWeight: FontWeight.w500, + color: Theme.of(context).colorScheme.onSurfaceVariant, + height: 1.4, + ); + + static TextStyle labelSmall(BuildContext context) => GoogleFonts.manrope( + fontSize: 11, + fontWeight: FontWeight.w500, + color: Theme.of(context).colorScheme.onSurfaceVariant, + height: 1.4, ); // ============================================ - // 便捷静态样式(兼容旧代码) + // 数字/金额 - Space Grotesk (等宽特性) // ============================================ + static TextStyle numberLarge(BuildContext context) => GoogleFonts.spaceGrotesk( + fontSize: 24, + fontWeight: FontWeight.w600, + color: Theme.of(context).colorScheme.onSurface, + height: 1.2, + fontFeatures: const [FontFeature.tabularFigures()], + ); + + static TextStyle numberMedium(BuildContext context) => GoogleFonts.spaceGrotesk( + fontSize: 18, + fontWeight: FontWeight.w500, + color: Theme.of(context).colorScheme.onSurface, + height: 1.25, + fontFeatures: const [FontFeature.tabularFigures()], + ); + + static TextStyle numberSmall(BuildContext context) => GoogleFonts.spaceGrotesk( + fontSize: 14, + fontWeight: FontWeight.w500, + color: Theme.of(context).colorScheme.onSurface, + height: 1.3, + fontFeatures: const [FontFeature.tabularFigures()], + ); + + // ============================================ + // 兼容旧代码的静态样式 (已废弃) + // ============================================ + + @Deprecated('Use displaySmall instead') static const TextStyle heading1 = TextStyle( fontSize: 28, fontWeight: FontWeight.bold, color: Color(0xFFFFFFFF), ); + @Deprecated('Use headlineLarge instead') static const TextStyle heading2 = TextStyle( fontSize: 24, fontWeight: FontWeight.bold, color: Color(0xFFFFFFFF), ); + @Deprecated('Use headlineMedium instead') static const TextStyle heading3 = TextStyle( fontSize: 18, fontWeight: FontWeight.w600, color: Color(0xFFFFFFFF), ); + @Deprecated('Use headlineSmall instead') static const TextStyle heading4 = TextStyle( fontSize: 16, fontWeight: FontWeight.w600, color: Color(0xFFFFFFFF), ); + @Deprecated('Use bodyLarge instead') static const TextStyle body1 = TextStyle( fontSize: 16, color: Color(0xFFFFFFFF), ); + @Deprecated('Use bodyMedium instead') static const TextStyle body2 = TextStyle( fontSize: 14, color: Color(0xFFFFFFFF), ); + @Deprecated('Use labelSmall instead') static const TextStyle caption = TextStyle( fontSize: 12, color: Color(0xFFA1A1AA), ); + @Deprecated('Use labelSmall instead') static const TextStyle hint = TextStyle( fontSize: 14, color: Color(0xFF71717A), ); + @Deprecated('Use numberMedium instead') static const TextStyle price = TextStyle( fontSize: 20, fontWeight: FontWeight.bold, color: Color(0xFFFFFFFF), ); + @Deprecated('Use numberSmall with color instead') static const TextStyle change = TextStyle( fontSize: 14, fontWeight: FontWeight.w600, ); + @Deprecated('Use numberSmall instead') static const TextStyle number = TextStyle( fontSize: 16, fontWeight: FontWeight.w500, diff --git a/flutter_monisuo/lib/ui/components/asset_card.dart b/flutter_monisuo/lib/ui/components/asset_card.dart index 5cff1cf..3bc2af1 100644 --- a/flutter_monisuo/lib/ui/components/asset_card.dart +++ b/flutter_monisuo/lib/ui/components/asset_card.dart @@ -1,8 +1,16 @@ import 'package:flutter/material.dart'; import 'package:shadcn_ui/shadcn_ui.dart'; +import 'package:flutter_animate/flutter_animate.dart'; import '../../core/theme/app_color_scheme.dart'; +import '../../core/theme/app_spacing.dart'; /// 资产卡片组件 - 用于显示资产总览 +/// +/// 设计规则 ("The Kinetic Vault"): +/// - 渐变背景: Neon Blue → Electric Purple +/// - 圆角: xl (16px) +/// - 无边框,使用渐变层次 +/// - 微妙阴影: 10% black, blur 10px class AssetCard extends StatelessWidget { final String title; final String balance; @@ -13,16 +21,16 @@ class AssetCard extends StatelessWidget { final Gradient? gradient; final VoidCallback? onTap; - // 默认渐变色 - 使用品牌青绿色 + /// 默认渐变色 - Neon Blue → Electric Purple static const defaultGradient = LinearGradient( - colors: [AppColorScheme.primaryDark, Color(0xFF00B894)], + colors: [AppColorScheme.darkPrimary, AppColorScheme.darkSecondary], begin: Alignment.topLeft, end: Alignment.bottomRight, ); - // 深色渐变 - static const darkGradient = LinearGradient( - colors: [Color(0xFF1E3A5F), Color(0xFF0D253F)], + /// 翡翠渐变 - 用于盈利展示 + static const emeraldGradient = LinearGradient( + colors: [AppColorScheme.darkTertiary, Color(0xFF7de8b8)], begin: Alignment.topLeft, end: Alignment.bottomRight, ); @@ -48,10 +56,10 @@ class AssetCard extends StatelessWidget { onTap: onTap, child: Container( width: double.infinity, - padding: const EdgeInsets.all(24), + padding: const EdgeInsets.all(AppSpacing.lg), decoration: BoxDecoration( gradient: cardGradient, - borderRadius: BorderRadius.circular(20), + borderRadius: BorderRadius.circular(AppRadius.xl), boxShadow: [ BoxShadow( color: Colors.black.withValues(alpha: 0.1), @@ -79,18 +87,19 @@ class AssetCard extends StatelessWidget { ), ], ), - const SizedBox(height: 8), - // 余额 + const SizedBox(height: AppSpacing.sm), + // 余额 - 大标题 Text( balance, style: theme.textTheme.h1.copyWith( fontWeight: FontWeight.bold, color: Colors.white, + fontSize: 32, ), ), // 盈亏信息 if (profit != null) ...[ - const SizedBox(height: 12), + const SizedBox(height: AppSpacing.md), Row( children: [ Icon( @@ -108,7 +117,7 @@ class AssetCard extends StatelessWidget { ], // 子项 if (items != null && items!.isNotEmpty) ...[ - const SizedBox(height: 20), + const SizedBox(height: AppSpacing.lg), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: items!.map((item) => _buildItem(item)).toList(), @@ -154,6 +163,11 @@ class AssetItem { } /// 简洁资产卡片 - 用于列表中显示 +/// +/// 设计规则: +/// - 使用 surface 层次而非边框 +/// - 圆角: xl (16px) +/// - 涨跌标签: 15% 透明度背景 class AssetCardCompact extends StatelessWidget { final String title; final String balance; @@ -176,7 +190,7 @@ class AssetCardCompact extends StatelessWidget { final isValueUp = isUp ?? true; return ShadCard( - padding: const EdgeInsets.all(16), + padding: const EdgeInsets.all(AppSpacing.md), child: InkWell( onTap: onTap, child: Row( @@ -204,7 +218,7 @@ class AssetCardCompact extends StatelessWidget { padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 6), decoration: BoxDecoration( color: getChangeBackgroundColor(isValueUp), - borderRadius: BorderRadius.circular(6), + borderRadius: BorderRadius.circular(AppRadius.sm), ), child: Text( change!, diff --git a/flutter_monisuo/lib/ui/components/coin_card.dart b/flutter_monisuo/lib/ui/components/coin_card.dart index bc09285..084d258 100644 --- a/flutter_monisuo/lib/ui/components/coin_card.dart +++ b/flutter_monisuo/lib/ui/components/coin_card.dart @@ -1,8 +1,14 @@ import 'package:flutter/material.dart'; import 'package:shadcn_ui/shadcn_ui.dart'; import '../../core/theme/app_color_scheme.dart'; +import '../../core/theme/app_spacing.dart'; /// 币种卡片组件 - 用于显示币种信息 +/// +/// 设计规则: +/// - 使用 surface 层次而非边框 +/// - 圆角: xl (16px) 卡片, sm (4px) 涨跌标签 +/// - 涨跌标签: 15% 透明度背景 class CoinCard extends StatelessWidget { final String code; final String name; @@ -28,12 +34,12 @@ class CoinCard extends StatelessWidget { final theme = ShadTheme.of(context); return ShadCard( - padding: const EdgeInsets.all(16), + padding: const EdgeInsets.all(AppSpacing.md), child: InkWell( onTap: onTap, child: Row( children: [ - // 图标 + // 图标 - 圆形 Container( width: 44, height: 44, @@ -52,7 +58,7 @@ class CoinCard extends StatelessWidget { ), ), ), - const SizedBox(width: 12), + const SizedBox(width: AppSpacing.sm), // 名称 Expanded( child: Column( @@ -71,12 +77,12 @@ class CoinCard extends StatelessWidget { ], ), ), - // 涨跌幅 + // 涨跌幅 - Dynamic Chip Container( padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 6), decoration: BoxDecoration( color: getChangeBackgroundColor(isUp), - borderRadius: BorderRadius.circular(6), + borderRadius: BorderRadius.circular(AppRadius.sm), ), child: Text( change, diff --git a/flutter_monisuo/lib/ui/components/gradient_button.dart b/flutter_monisuo/lib/ui/components/gradient_button.dart new file mode 100644 index 0000000..eb597bd --- /dev/null +++ b/flutter_monisuo/lib/ui/components/gradient_button.dart @@ -0,0 +1,223 @@ +import 'package:flutter/material.dart'; +import '../../core/theme/app_color_scheme.dart'; +import '../../core/theme/app_spacing.dart'; + +/// 渐变按钮组件 - 支持 CTA 渐变效果 +/// +/// 设计规则: +/// - 渐变方向: 135度 (primary → primary_container) +/// - 圆角: xxl (24px / 1.5rem) +/// - 无边框 +class GradientButton extends StatelessWidget { + final String text; + final VoidCallback? onPressed; + final bool isLoading; + final bool isFullWidth; + final LinearGradient? gradient; + final IconData? icon; + final double height; + + const GradientButton({ + super.key, + required this.text, + this.onPressed, + this.isLoading = false, + this.isFullWidth = true, + this.gradient, + this.icon, + this.height = 48, + }); + + /// CTA 按钮 - 使用主题渐变 + factory GradientButton.cta({ + Key? key, + required String text, + VoidCallback? onPressed, + bool isLoading = false, + bool isFullWidth = true, + IconData? icon, + bool isDark = true, + }) { + return GradientButton( + key: key, + text: text, + onPressed: onPressed, + isLoading: isLoading, + isFullWidth: isFullWidth, + icon: icon, + gradient: isDark ? AppColorScheme.darkCtaGradient : AppColorScheme.lightCtaGradient, + ); + } + + /// 买入按钮 - 翡翠绿渐变 + factory GradientButton.buy({ + Key? key, + required String text, + VoidCallback? onPressed, + bool isLoading = false, + bool isFullWidth = true, + IconData? icon, + }) { + return GradientButton( + key: key, + text: text, + onPressed: onPressed, + isLoading: isLoading, + isFullWidth: isFullWidth, + icon: icon ?? Icons.arrow_downward_rounded, + gradient: AppColorScheme.buyGradient, + ); + } + + /// 卖出按钮 - 红色渐变 + factory GradientButton.sell({ + Key? key, + required String text, + VoidCallback? onPressed, + bool isLoading = false, + bool isFullWidth = true, + IconData? icon, + }) { + return GradientButton( + key: key, + text: text, + onPressed: onPressed, + isLoading: isLoading, + isFullWidth: isFullWidth, + icon: icon ?? Icons.arrow_upward_rounded, + gradient: AppColorScheme.sellGradient, + ); + } + + @override + Widget build(BuildContext context) { + final buttonGradient = gradient ?? AppColorScheme.darkCtaGradient; + + return Container( + width: isFullWidth ? double.infinity : null, + height: height, + decoration: BoxDecoration( + gradient: buttonGradient, + borderRadius: BorderRadius.circular(AppRadius.xxl), + ), + child: Material( + color: Colors.transparent, + child: InkWell( + onTap: isLoading ? null : onPressed, + borderRadius: BorderRadius.circular(AppRadius.xxl), + child: Center( + child: Row( + mainAxisSize: isFullWidth ? MainAxisSize.max : MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + if (isLoading) + const SizedBox( + width: 20, + height: 20, + child: CircularProgressIndicator( + strokeWidth: 2, + color: Colors.white, + ), + ) + else ...[ + if (icon != null) ...[ + Icon(icon, size: 18, color: Colors.white), + SizedBox(width: AppSpacing.sm), + ], + Text( + text, + style: const TextStyle( + color: Colors.white, + fontSize: 16, + fontWeight: FontWeight.w600, + ), + ), + ], + ], + ), + ), + ), + ), + ); + } +} + +/// Ghost 按钮 - 次要操作 +/// +/// 设计规则: +/// - Ghost Border: 15% opacity outline-variant +/// - 圆角: xxl (24px) +/// - 主色文字 +class GhostButton extends StatelessWidget { + final String text; + final VoidCallback? onPressed; + final bool isLoading; + final bool isFullWidth; + final IconData? icon; + + const GhostButton({ + super.key, + required this.text, + this.onPressed, + this.isLoading = false, + this.isFullWidth = true, + this.icon, + }); + + @override + Widget build(BuildContext context) { + final isDark = Theme.of(context).brightness == Brightness.dark; + final textColor = isDark ? AppColorScheme.darkPrimary : AppColorScheme.lightPrimary; + final borderColor = isDark + ? AppColorScheme.darkOutlineVariant.withValues(alpha: 0.15) + : AppColorScheme.lightOutlineVariant.withValues(alpha: 0.3); + + return Container( + width: isFullWidth ? double.infinity : null, + height: 48, + decoration: BoxDecoration( + color: Colors.transparent, + border: Border.all(color: borderColor, width: 1), + borderRadius: BorderRadius.circular(AppRadius.xxl), + ), + child: Material( + color: Colors.transparent, + child: InkWell( + onTap: isLoading ? null : onPressed, + borderRadius: BorderRadius.circular(AppRadius.xxl), + child: Center( + child: Row( + mainAxisSize: isFullWidth ? MainAxisSize.max : MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + if (isLoading) + SizedBox( + width: 20, + height: 20, + child: CircularProgressIndicator( + strokeWidth: 2, + color: textColor, + ), + ) + else ...[ + if (icon != null) ...[ + Icon(icon, size: 18, color: textColor), + SizedBox(width: AppSpacing.sm), + ], + Text( + text, + style: TextStyle( + color: textColor, + fontSize: 16, + fontWeight: FontWeight.w600, + ), + ), + ], + ], + ), + ), + ), + ), + ); + } +} diff --git a/flutter_monisuo/lib/ui/components/trade_button.dart b/flutter_monisuo/lib/ui/components/trade_button.dart index 70d04d1..2ba783b 100644 --- a/flutter_monisuo/lib/ui/components/trade_button.dart +++ b/flutter_monisuo/lib/ui/components/trade_button.dart @@ -1,8 +1,14 @@ import 'package:flutter/material.dart'; -import 'package:shadcn_ui/shadcn_ui.dart'; import '../../core/theme/app_color_scheme.dart'; +import '../../core/theme/app_spacing.dart'; /// 交易按钮组件 - 买入/卖出按钮 +/// +/// 设计规则: +/// - 渐变按钮: 135度渐变 +/// - 圆角: xxl (24px / 1.5rem) +/// - 买入: 翡翠绿渐变 +/// - 卖出: 红色渐变 class TradeButton extends StatelessWidget { final bool isBuy; final String? coinCode; @@ -39,44 +45,57 @@ class TradeButton extends StatelessWidget { @override Widget build(BuildContext context) { - final color = isBuy ? AppColorScheme.up : AppColorScheme.down; - final text = isBuy ? '买入${coinCode != null ? ' $coinCode' : ''}' : '卖出${coinCode != null ? ' $coinCode' : ''}'; - final icon = isBuy ? LucideIcons.arrowDownToLine : LucideIcons.arrowUpFromLine; + final gradient = isBuy ? AppColorScheme.buyGradient : AppColorScheme.sellGradient; + final text = isBuy + ? '买入${coinCode != null ? ' $coinCode' : ''}' + : '卖出${coinCode != null ? ' $coinCode' : ''}'; - final button = ShadButton( - backgroundColor: color, - onPressed: isLoading ? null : onPressed, - child: Row( - mainAxisSize: fullWidth ? MainAxisSize.max : MainAxisSize.min, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - if (isLoading) - const SizedBox.square( - dimension: 16, - child: CircularProgressIndicator( - strokeWidth: 2, - color: Colors.white, - ), - ) - else - Icon(icon, size: 18, color: Colors.white), - const SizedBox(width: 8), - Text( - text, - style: const TextStyle( - color: Colors.white, - fontSize: 16, - fontWeight: FontWeight.w600, + return Container( + width: fullWidth ? double.infinity : null, + height: 48, + decoration: BoxDecoration( + gradient: gradient, + borderRadius: BorderRadius.circular(AppRadius.xxl), + ), + child: Material( + color: Colors.transparent, + child: InkWell( + onTap: isLoading ? null : onPressed, + borderRadius: BorderRadius.circular(AppRadius.xxl), + child: Center( + child: Row( + mainAxisSize: fullWidth ? MainAxisSize.max : MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + if (isLoading) + const SizedBox.square( + dimension: 16, + child: CircularProgressIndicator( + strokeWidth: 2, + color: Colors.white, + ), + ) + else + Icon( + isBuy ? Icons.arrow_downward_rounded : Icons.arrow_upward_rounded, + size: 18, + color: Colors.white, + ), + const SizedBox(width: 8), + Text( + text, + style: const TextStyle( + color: Colors.white, + fontSize: 16, + fontWeight: FontWeight.w600, + ), + ), + ], ), ), - ], + ), ), ); - - if (fullWidth) { - return SizedBox(width: double.infinity, child: button); - } - return button; } } @@ -108,7 +127,7 @@ class TradeButtonGroup extends StatelessWidget { isLoading: isBuyLoading, ), ), - const SizedBox(width: 12), + const SizedBox(width: AppSpacing.sm), Expanded( child: TradeButton.sell( coinCode: coinCode,