feat:参照研听的基础工程
This commit is contained in:
@@ -0,0 +1,15 @@
|
||||
import 'package:flutter_remix/flutter_remix.dart';
|
||||
|
||||
// flutter_remix 0.0.3: icon class is FlutterRemix
|
||||
class AppIcons {
|
||||
static const assetsFill = FlutterRemix.wallet_3_fill;
|
||||
static const assetsLine = FlutterRemix.wallet_3_line;
|
||||
static const marketFill = FlutterRemix.line_chart_fill;
|
||||
static const marketLine = FlutterRemix.line_chart_line;
|
||||
static const newsFill = FlutterRemix.article_fill;
|
||||
static const newsLine = FlutterRemix.article_line;
|
||||
static const meFill = FlutterRemix.user_3_fill;
|
||||
static const meLine = FlutterRemix.user_3_line;
|
||||
static const arrowRight = FlutterRemix.arrow_right_s_line;
|
||||
static const arrowLeft = FlutterRemix.arrow_left_s_line;
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
/// 字号刻度常量。
|
||||
/// 颜色在用处通过 ShadTheme.of(context).colorScheme 取,此处只定义尺寸/粗细/行高。
|
||||
abstract class AppText {
|
||||
/// App 大标题: 34px / w800 / lh 1.15
|
||||
static const TextStyle appTitle = TextStyle(
|
||||
fontSize: 34,
|
||||
fontWeight: FontWeight.w800,
|
||||
height: 1.15,
|
||||
);
|
||||
|
||||
/// 区块标题: 22px / w700
|
||||
static const TextStyle sectionTitle = TextStyle(
|
||||
fontSize: 22,
|
||||
fontWeight: FontWeight.w700,
|
||||
);
|
||||
|
||||
/// 卡片标题: 19px / w620 / lh 1.4
|
||||
static const TextStyle cardTitle = TextStyle(
|
||||
fontSize: 19,
|
||||
fontWeight: FontWeight.w600, // 最接近 w620
|
||||
height: 1.4,
|
||||
);
|
||||
|
||||
/// 列表标题: 16.5px / w600
|
||||
static const TextStyle listTitle = TextStyle(
|
||||
fontSize: 16.5,
|
||||
fontWeight: FontWeight.w600,
|
||||
);
|
||||
|
||||
/// 正文: 15px / w400 / lh 1.6
|
||||
static const TextStyle body = TextStyle(
|
||||
fontSize: 15,
|
||||
fontWeight: FontWeight.w400,
|
||||
height: 1.6,
|
||||
);
|
||||
|
||||
/// meta 信息: 13px / w400
|
||||
static const TextStyle meta = TextStyle(
|
||||
fontSize: 13,
|
||||
fontWeight: FontWeight.w400,
|
||||
);
|
||||
|
||||
/// chip 筛选: 15px / w500
|
||||
static const TextStyle chip = TextStyle(
|
||||
fontSize: 15,
|
||||
fontWeight: FontWeight.w500,
|
||||
);
|
||||
|
||||
/// badge 标签: 12px / w500
|
||||
static const TextStyle badge = TextStyle(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w500,
|
||||
height: 1.5,
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:shadcn_ui/shadcn_ui.dart';
|
||||
|
||||
const jinzhiLightScheme = ShadColorScheme(
|
||||
background: Color(0xFFFBFAF7),
|
||||
foreground: Color(0xFF1A1A17),
|
||||
card: Color(0xFFFFFFFF),
|
||||
cardForeground: Color(0xFF1A1A17),
|
||||
popover: Color(0xFFFFFFFF),
|
||||
popoverForeground: Color(0xFF1A1A17),
|
||||
primary: Color(0xFFB5862A),
|
||||
primaryForeground: Color(0xFFFFFFFF),
|
||||
secondary: Color(0xFFF6ECD6),
|
||||
secondaryForeground: Color(0xFF7A5B12),
|
||||
muted: Color(0xFFF1EFE9),
|
||||
mutedForeground: Color(0xFF8A8780),
|
||||
accent: Color(0xFFF6ECD6),
|
||||
accentForeground: Color(0xFF7A5B12),
|
||||
destructive: Color(0xFFC0392B),
|
||||
destructiveForeground: Color(0xFFFFFFFF),
|
||||
border: Color(0xFFECEAE3),
|
||||
input: Color(0xFFECEAE3),
|
||||
ring: Color(0xFFB5862A),
|
||||
selection: Color(0xFF1A1A17),
|
||||
);
|
||||
|
||||
/// Hero 卡描边 = demo `--brand-soft-border`(比 brand-soft 填充更深一档的绿)。
|
||||
/// ShadColorScheme 无对应 slot,单列于此(色值仍集中在 theme,widget 不写 hex);
|
||||
/// widget 按 brightness 取值。light=oklch(0.9 0.07 128)、dark=oklch(0.42 0.07 131)。
|
||||
const jinzhiBrandSoftBorderLight = Color(0xFFE3D6B4);
|
||||
const jinzhiBrandSoftBorderDark = Color(0xFF5E4A22);
|
||||
|
||||
Color brandSoftBorder(Brightness b) => b == Brightness.dark
|
||||
? jinzhiBrandSoftBorderDark
|
||||
: jinzhiBrandSoftBorderLight;
|
||||
|
||||
/// Hero(brand-soft 绿底)上的副/弱文本色。
|
||||
/// 规范:次级文本是**中性 muted**,不挪用语义色(accentForeground 是链接/强调专用)。
|
||||
/// 浅绿底上灰 muted(#8E8E93) 对比不足,故用 foreground 降透明的**中性深灰**
|
||||
/// (叠在绿底上自然带轻微绿调、和谐且达 AA);深色底仍用灰 muted(已够对比)。
|
||||
Color brandSoftMutedForeground(Brightness b, ShadColorScheme cs) =>
|
||||
b == Brightness.dark
|
||||
? cs.mutedForeground
|
||||
: cs.foreground.withValues(alpha: 0.7);
|
||||
|
||||
/// 危险警示卡 soft-tint(demo `.da-warn`,与 brand-soft 同语言的 destructive 变体)。
|
||||
const jinzhiDestructiveSoftLight = Color(0xFFFBEDEA);
|
||||
const jinzhiDestructiveSoftBorderLight = Color(0xFFE8C7BF);
|
||||
const jinzhiDestructiveSoftDark = Color(0x1AEF4444);
|
||||
const jinzhiDestructiveSoftBorderDark = Color(0x52EF4444);
|
||||
|
||||
Color destructiveSoft(Brightness b) => b == Brightness.dark
|
||||
? jinzhiDestructiveSoftDark
|
||||
: jinzhiDestructiveSoftLight;
|
||||
|
||||
Color destructiveSoftBorder(Brightness b) => b == Brightness.dark
|
||||
? jinzhiDestructiveSoftBorderDark
|
||||
: jinzhiDestructiveSoftBorderLight;
|
||||
|
||||
const jinzhiDarkScheme = ShadColorScheme(
|
||||
background: Color(0xFF0F0F0F),
|
||||
foreground: Color(0xFFF0F0F0),
|
||||
card: Color(0xFF1A1A1A),
|
||||
cardForeground: Color(0xFFF0F0F0),
|
||||
popover: Color(0xFF1A1A1A),
|
||||
popoverForeground: Color(0xFFF0F0F0),
|
||||
primary: Color(0xFFD9B45D),
|
||||
primaryForeground: Color(0xFF1A1A17),
|
||||
secondary: Color(0xFF27272A),
|
||||
secondaryForeground: Color(0xFFF0F0F0),
|
||||
muted: Color(0xFF262626),
|
||||
mutedForeground: Color(0xFFA1A1AA),
|
||||
accent: Color(0xFF3A2A0D),
|
||||
accentForeground: Color(0xFFD9B45D),
|
||||
destructive: Color(0xFFEF4444),
|
||||
destructiveForeground: Color(0xFFFFFFFF),
|
||||
border: Color(0x1FFFFFFF),
|
||||
input: Color(0x26FFFFFF),
|
||||
ring: Color(0xFFD9B45D),
|
||||
selection: Color(0xFFF0F0F0),
|
||||
);
|
||||
@@ -0,0 +1,10 @@
|
||||
class Spacing {
|
||||
static const page = 20.0;
|
||||
static const cardPadding = 18.0;
|
||||
static const cardGap = 14.0;
|
||||
static const sectionGap = 30.0;
|
||||
static const radiusBase = 7.2; // 0.45rem --radius
|
||||
static const radiusBadge = 3.2; // --radius-sm (badge / tag)
|
||||
static const radiusBtn = 5.2; // --radius-md (button / input)
|
||||
static const radiusCard = 11.2; // --radius-xl (card / hero 容器)
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
import '../storage/storage_service.dart';
|
||||
import '../storage/storage_keys.dart';
|
||||
|
||||
part 'theme_controller.g.dart';
|
||||
|
||||
@riverpod
|
||||
class ThemeModeController extends _$ThemeModeController {
|
||||
@override
|
||||
ThemeMode build() {
|
||||
final v = StorageService.to.getString(storageThemeMode);
|
||||
return switch (v) {
|
||||
'light' => ThemeMode.light,
|
||||
'dark' => ThemeMode.dark,
|
||||
_ => ThemeMode.system,
|
||||
};
|
||||
}
|
||||
|
||||
Future<void> set(ThemeMode mode) async {
|
||||
state = mode;
|
||||
await StorageService.to.setString(storageThemeMode, mode.name);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user