forked from mirrors/material_3_expressive
Refactor theme implementation to use ColorScheme.fromSeed for light and dark themes; update README with usage examples and add widgetbook build configuration.
This commit is contained in:
parent
f8b33f7e0d
commit
2f84b1559f
6 changed files with 139 additions and 15 deletions
17
.run/widgetbook build.run.xml
Normal file
17
.run/widgetbook build.run.xml
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
<component name="ProjectRunConfigurationManager">
|
||||||
|
<configuration default="false" name="widgetbook build" type="ShConfigurationType">
|
||||||
|
<option name="SCRIPT_TEXT" value="dart run build_runner build -d" />
|
||||||
|
<option name="INDEPENDENT_SCRIPT_PATH" value="true" />
|
||||||
|
<option name="SCRIPT_PATH" value="" />
|
||||||
|
<option name="SCRIPT_OPTIONS" value="" />
|
||||||
|
<option name="INDEPENDENT_SCRIPT_WORKING_DIRECTORY" value="false" />
|
||||||
|
<option name="SCRIPT_WORKING_DIRECTORY" value="$PROJECT_DIR$/widgetbook" />
|
||||||
|
<option name="INDEPENDENT_INTERPRETER_PATH" value="false" />
|
||||||
|
<option name="INTERPRETER_PATH" value=""C:/Program Files/PowerShell/7/pwsh.exe"" />
|
||||||
|
<option name="INTERPRETER_OPTIONS" value="" />
|
||||||
|
<option name="EXECUTE_IN_TERMINAL" value="true" />
|
||||||
|
<option name="EXECUTE_SCRIPT_FILE" value="false" />
|
||||||
|
<envs />
|
||||||
|
<method v="2" />
|
||||||
|
</configuration>
|
||||||
|
</component>
|
||||||
81
README.md
81
README.md
|
|
@ -33,6 +33,85 @@ flutter run
|
||||||
|
|
||||||
See `melos.yaml`, `analysis_options.yaml`, and the package-level READMEs.
|
See `melos.yaml`, `analysis_options.yaml`, and the package-level READMEs.
|
||||||
|
|
||||||
|
## Using the M3E Theme
|
||||||
|
|
||||||
|
The design tokens and helpers live in the `m3e_design` package. Import it once in files where you access the theme:
|
||||||
|
|
||||||
|
```dart
|
||||||
|
import 'package:m3e_design/m3e_design.dart';
|
||||||
|
```
|
||||||
|
|
||||||
|
- Install the theme once at the app level (one-liner):
|
||||||
|
|
||||||
|
```dart
|
||||||
|
class MyApp extends StatelessWidget {
|
||||||
|
const MyApp({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return MaterialApp(
|
||||||
|
theme: ColorScheme.fromSeed(seedColor: Colors.teal).toM3EThemeData(),
|
||||||
|
home: const MyHomePage(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
- With dynamic color (Android 12+), setting both light and dark themes:
|
||||||
|
|
||||||
|
```dart
|
||||||
|
Widget buildDynamicApp() {
|
||||||
|
return DynamicColorBuilder(
|
||||||
|
builder: (lightDynamic, darkDynamic) {
|
||||||
|
final light = lightDynamic ?? ColorScheme.fromSeed(seedColor: Colors.teal);
|
||||||
|
final dark = darkDynamic ??
|
||||||
|
ColorScheme.fromSeed(seedColor: Colors.teal, brightness: Brightness.dark);
|
||||||
|
return MaterialApp(
|
||||||
|
theme: light.toM3EThemeData(),
|
||||||
|
darkTheme: dark.toM3EThemeData(),
|
||||||
|
home: const MyHomePage(),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
- Access M3E tokens anywhere using the new ThemeData accessor:
|
||||||
|
|
||||||
|
```dart
|
||||||
|
final m3e = Theme.of(context).m3e; // ThemeData extension
|
||||||
|
|
||||||
|
// Examples
|
||||||
|
final br = m3e.shapes.round.sm; // BorderRadius
|
||||||
|
final pad = EdgeInsets.all(m3e.spacing.md); // Spacing scale
|
||||||
|
final bg = m3e.colors.surfaceContainerHigh; // Colors mapped to ColorScheme
|
||||||
|
final curve = m3e.motion.emphasized; // Motion/curves
|
||||||
|
final title = m3e.typography.base.titleLarge; // Typography
|
||||||
|
```
|
||||||
|
|
||||||
|
- Apply a rounded shape to a widget:
|
||||||
|
|
||||||
|
```dart
|
||||||
|
Widget roundedExample(BuildContext context) {
|
||||||
|
return Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Theme.of(context).colorScheme.surface,
|
||||||
|
borderRadius: Theme.of(context).m3e.shapes.round.sm,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
- Optional context sugar if you prefer:
|
||||||
|
|
||||||
|
```dart
|
||||||
|
// Provided by BuildContext extension in m3e_design
|
||||||
|
final m3e = context.m3e;
|
||||||
|
```
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
- In debug, accessing `Theme.of(context).m3e` asserts if the extension isn't installed, helping catch setup issues.
|
||||||
|
- In release, it safely falls back to sensible defaults derived from the active `ColorScheme`.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -49,4 +128,4 @@ cd apps/gallery
|
||||||
flutter run -d chrome
|
flutter run -d chrome
|
||||||
```
|
```
|
||||||
|
|
||||||
_Last updated: 2025-10-23_
|
_Last updated: 2025-10-25_
|
||||||
|
|
|
||||||
|
|
@ -31,20 +31,14 @@ class _GalleryAppState extends State<GalleryApp> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final baseLight = ThemeData(
|
final light = ColorScheme.fromSeed(
|
||||||
useMaterial3: true,
|
seedColor: Colors.purple, brightness: Brightness.light);
|
||||||
colorSchemeSeed: Colors.purple,
|
final dark = ColorScheme.fromSeed(
|
||||||
brightness: Brightness.light,
|
seedColor: Colors.purple, brightness: Brightness.dark);
|
||||||
);
|
|
||||||
final baseDark = ThemeData(
|
|
||||||
useMaterial3: true,
|
|
||||||
colorSchemeSeed: Colors.purple,
|
|
||||||
brightness: Brightness.dark,
|
|
||||||
);
|
|
||||||
return MaterialApp(
|
return MaterialApp(
|
||||||
title: 'M3E Gallery',
|
title: 'M3E Gallery',
|
||||||
theme: withM3ETheme(baseLight),
|
theme: light.toM3EThemeData(),
|
||||||
darkTheme: withM3ETheme(baseDark),
|
darkTheme: dark.toM3EThemeData(),
|
||||||
themeMode: _mode,
|
themeMode: _mode,
|
||||||
home: GalleryHome(
|
home: GalleryHome(
|
||||||
isDark: _mode == ThemeMode.dark,
|
isDark: _mode == ThemeMode.dark,
|
||||||
|
|
@ -56,7 +50,8 @@ class _GalleryAppState extends State<GalleryApp> {
|
||||||
}
|
}
|
||||||
|
|
||||||
class GalleryHome extends StatefulWidget {
|
class GalleryHome extends StatefulWidget {
|
||||||
const GalleryHome({super.key, required this.isDark, required this.onToggleBrightness});
|
const GalleryHome(
|
||||||
|
{super.key, required this.isDark, required this.onToggleBrightness});
|
||||||
|
|
||||||
final bool isDark;
|
final bool isDark;
|
||||||
final VoidCallback onToggleBrightness;
|
final VoidCallback onToggleBrightness;
|
||||||
|
|
@ -77,7 +72,8 @@ class _GalleryHomeState extends State<GalleryHome> {
|
||||||
titleText: 'M3E Gallery',
|
titleText: 'M3E Gallery',
|
||||||
actions: [
|
actions: [
|
||||||
IconButton(
|
IconButton(
|
||||||
tooltip: widget.isDark ? 'Switch to light mode' : 'Switch to dark mode',
|
tooltip:
|
||||||
|
widget.isDark ? 'Switch to light mode' : 'Switch to dark mode',
|
||||||
onPressed: widget.onToggleBrightness,
|
onPressed: widget.onToggleBrightness,
|
||||||
icon: Icon(widget.isDark ? Icons.dark_mode : Icons.light_mode),
|
icon: Icon(widget.isDark ? Icons.dark_mode : Icons.light_mode),
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ dependencies:
|
||||||
m3e_collection:
|
m3e_collection:
|
||||||
path: ../../packages/m3e_collection
|
path: ../../packages/m3e_collection
|
||||||
material_color_utilities: ^0.11.0
|
material_color_utilities: ^0.11.0
|
||||||
|
widgetbook: ^3.18.0
|
||||||
|
|
||||||
flutter:
|
flutter:
|
||||||
uses-material-design: true
|
uses-material-design: true
|
||||||
|
|
|
||||||
30
apps/gallery/pubspec_overrides.yaml
Normal file
30
apps/gallery/pubspec_overrides.yaml
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
# melos_managed_dependency_overrides: app_bar_m3e,button_group_m3e,button_m3e,fab_m3e,icon_button_m3e,loading_indicator_m3e,m3e_collection,m3e_design,navigation_bar_m3e,navigation_rail_m3e,progress_indicator_m3e,slider_m3e,split_button_m3e,toolbar_m3e
|
||||||
|
dependency_overrides:
|
||||||
|
app_bar_m3e:
|
||||||
|
path: ..\\..\\packages\\app_bar_m3e
|
||||||
|
button_group_m3e:
|
||||||
|
path: ..\\..\\packages\\button_group_m3e
|
||||||
|
button_m3e:
|
||||||
|
path: ..\\..\\packages\\button_m3e
|
||||||
|
fab_m3e:
|
||||||
|
path: ..\\..\\packages\\fab_m3e
|
||||||
|
icon_button_m3e:
|
||||||
|
path: ..\\..\\packages\\icon_button_m3e
|
||||||
|
loading_indicator_m3e:
|
||||||
|
path: ..\\..\\packages\\loading_indicator_m3e
|
||||||
|
m3e_collection:
|
||||||
|
path: ..\\..\\packages\\m3e_collection
|
||||||
|
m3e_design:
|
||||||
|
path: ..\\..\\packages\\m3e_design
|
||||||
|
navigation_bar_m3e:
|
||||||
|
path: ..\\..\\packages\\navigation_bar_m3e
|
||||||
|
navigation_rail_m3e:
|
||||||
|
path: ..\\..\\packages\\navigation_rail_m3e
|
||||||
|
progress_indicator_m3e:
|
||||||
|
path: ..\\..\\packages\\progress_indicator_m3e
|
||||||
|
slider_m3e:
|
||||||
|
path: ..\\..\\packages\\slider_m3e
|
||||||
|
split_button_m3e:
|
||||||
|
path: ..\\..\\packages\\split_button_m3e
|
||||||
|
toolbar_m3e:
|
||||||
|
path: ..\\..\\packages\\toolbar_m3e
|
||||||
|
|
@ -2,6 +2,7 @@ name: m3e
|
||||||
packages:
|
packages:
|
||||||
- "packages/*"
|
- "packages/*"
|
||||||
- "apps/*"
|
- "apps/*"
|
||||||
|
- "widgetbook/"
|
||||||
|
|
||||||
command:
|
command:
|
||||||
bootstrap:
|
bootstrap:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue