diff --git a/example/example.md b/example/example.md index b15b08dc..2b3abf32 100644 --- a/example/example.md +++ b/example/example.md @@ -3,10 +3,13 @@ To use Zeta components in you app, first the whole app must be wrapped with `ZetaProvider`. The easiest way to do this is with the custom builder `ZetaProvider.custom`. You can provide initial values for `ThemeData`, `ThemeMode`, `contrast` and `ZetaThemeData`. -* `initialThemeData` allows you to extend an existing Flutter themeData to use alongside the `Zeta` theme. -* `initialThemeMode` sets whether the app starts in light or dark mode, or uses the device default. -* `initialContrast` sets whether the app starts with standard (WCAG AA) contrast, or if it attempts to use the more accessible contrast (WCAG AAA). -* `initialZetaThemeData` allows you to override the Zeta theme with a custom theme. +* `initialThemeData` (optional) allows you to extend an existing Flutter themeData to use alongside the `Zeta` theme. +* `initialThemeMode` (optional) sets whether the app starts in light or dark mode, or uses the device default. +* `initialContrast` (optional) sets whether the app starts with standard (WCAG AA) contrast, or if it attempts to use the more accessible contrast (WCAG AAA). +* `initialZetaThemeData` (optional) allows you to override the Zeta theme with a custom theme. +* `initialLightThemeData` and `initialDarkThemeData` (optional) allows you to use existing ThemeData objects withing zeta +* `builder` (required) is used to construct the app with all Zeta themes injected. + ```dart return ZetaProvider.base( diff --git a/example/lib/main.dart b/example/lib/main.dart index 3692f8f5..3bffbb27 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -37,15 +37,10 @@ class ZetaExample extends StatelessWidget { @override Widget build(BuildContext context) { - final initialThemeData = null; - final initialRounded = true; - return ZetaProvider.base( initialZetaThemeData: initialZetaThemeData, initialThemeMode: initialThemeMode, initialContrast: initialContrast, - initialThemeData: initialThemeData, - initialRounded: initialRounded, builder: (context, lightTheme, darkTheme, themeMode) { return MaterialApp.router( routerConfig: router, diff --git a/example/lib/pages/components/progress_example.dart b/example/lib/pages/components/progress_example.dart index fdc0ef81..18309cb3 100644 --- a/example/lib/pages/components/progress_example.dart +++ b/example/lib/pages/components/progress_example.dart @@ -84,7 +84,6 @@ class Wrapper extends StatefulWidget { }); final int stepsCompleted; - final ZetaProgressBarType? type; final bool? isThin; final String? label; diff --git a/example/lib/pages/components/stepper_example.dart b/example/lib/pages/components/stepper_example.dart index b0bcd1b5..e782f386 100644 --- a/example/lib/pages/components/stepper_example.dart +++ b/example/lib/pages/components/stepper_example.dart @@ -12,7 +12,6 @@ class StepperExample extends StatefulWidget { } class _StepperExampleState extends State { - int edHorizontalStep = 0; int _sharpHorizontalStep = 0; int _verticalStep = 0; @@ -33,38 +32,6 @@ class _StepperExampleState extends State { child: SingleChildScrollView( child: Column( children: [ - SizedBox( - height: 150, - child: ZetaStepper( - currentStep: edHorizontalStep, - onStepTapped: (index) => setState(() => edHorizontalStep = index), - steps: [ - ZetaStep( - type: _getForStepIndex( - currentStep: edHorizontalStep, - stepIndex: 0, - ), - title: Text("Title"), - content: Text("Content"), - ), - ZetaStep( - type: _getForStepIndex( - currentStep: edHorizontalStep, - stepIndex: 1, - ), - title: Text("Title 2"), - ), - ZetaStep( - type: _getForStepIndex( - currentStep: edHorizontalStep, - stepIndex: 2, - ), - title: Text("Title 3"), - content: Text("Content 3"), - ), - ], - ), - ), SizedBox( height: 150, child: ZetaStepper( diff --git a/example/lib/utils/rounded_switch.dart b/example/lib/utils/rounded_switch.dart index 21410853..66a67aed 100644 --- a/example/lib/utils/rounded_switch.dart +++ b/example/lib/utils/rounded_switch.dart @@ -23,7 +23,7 @@ class ZetaRoundedSwitch extends StatelessWidget { size: ZetaAvatarSize.xxs, initials: e ? '●' : '■', initialTextStyle: TextStyle( - fontSize: 14, + fontSize: 28, letterSpacing: ZetaSpacing.none, color: Zeta.of(context).colors.primary, fontWeight: FontWeight.w500, diff --git a/example/lib/utils/theme_color_switch.dart b/example/lib/utils/theme_color_switch.dart index 1de614cc..c205ed11 100644 --- a/example/lib/utils/theme_color_switch.dart +++ b/example/lib/utils/theme_color_switch.dart @@ -40,7 +40,6 @@ class ZetaThemeColorSwitch extends StatelessWidget { child: DropdownButton( value: zeta.themeData.identifier, elevation: 0, - alignment: Alignment.center, padding: EdgeInsets.all(8), icon: Nothing(), dropdownColor: zeta.colors.borderDisabled, diff --git a/lib/src/theme/constants.dart b/lib/src/theme/constants.dart index 92d3d64b..bbb6f11e 100644 --- a/lib/src/theme/constants.dart +++ b/lib/src/theme/constants.dart @@ -1,12 +1,12 @@ import 'color_swatch.dart'; -/// Default font family for Zeta System +/// Default font family for Zeta System. const kZetaFontFamily = 'packages/zeta_flutter/IBMPlexSans'; -/// Primary color shade index for [ZetaColorSwatch] +/// Primary color shade index for [ZetaColorSwatch]. const kZetaSwatchPrimaryIndex = 60; -/// Target contrast values for different color shades of [ZetaColorSwatch] +/// Target contrast values for different color shades of [ZetaColorSwatch]. const kZetaSwatchTargetContrasts = { 100: 17.42, 90: 13.99, @@ -19,3 +19,6 @@ const kZetaSwatchTargetContrasts = { 20: 1.09, 10: 1.02, }; + +/// Default icon size for Zeta System. +const double kZetaIconSize = 24; diff --git a/lib/src/zeta_provider.dart b/lib/src/zeta_provider.dart index 520418f0..c94c9ff0 100644 --- a/lib/src/zeta_provider.dart +++ b/lib/src/zeta_provider.dart @@ -39,19 +39,21 @@ class ZetaProvider extends StatefulWidget with Diagnosticable { this.initialRounded = true, }) : initialZetaThemeData = initialThemeData ?? ZetaThemeData(), baseBuilder = _emptyBase, - initialThemeData = null; + initialLightThemeData = null, + initialDarkThemeData = null; /// ZetaProvider constructor that returns light and dark [ThemeData]s ready to be consumed. /// /// The [builder] argument is required. The [initialThemeMode], [initialContrast], - /// and [initialThemeData] arguments provide initial values. + /// and [initialLightThemeData] arguments provide initial values. ZetaProvider.base({ super.key, required ZetaBaseAppBuilder builder, this.initialThemeMode = ThemeMode.system, this.initialContrast = ZetaContrast.aa, ZetaThemeData? initialZetaThemeData, - this.initialThemeData, + this.initialLightThemeData, + this.initialDarkThemeData, this.initialRounded = true, }) : baseBuilder = builder, initialZetaThemeData = initialZetaThemeData ?? ZetaThemeData(), @@ -91,8 +93,11 @@ class ZetaProvider extends StatefulWidget with Diagnosticable { /// It provides the structure for loading and saving themes in Zeta application. final ZetaThemeService? themeService; - /// [ThemeData] used in [ZetaProvider.base] constructor as the foundation for a custom theme. - final ThemeData? initialThemeData; + /// Light [ThemeData] used in [ZetaProvider.base] constructor as the foundation for a custom theme. + final ThemeData? initialLightThemeData; + + /// Dark [ThemeData] used in [ZetaProvider.base] constructor as the foundation for a custom theme. + final ThemeData? initialDarkThemeData; /// Sets whether app should start with components in their rounded or sharp variants. final bool initialRounded; @@ -110,8 +115,9 @@ class ZetaProvider extends StatefulWidget with Diagnosticable { ..add(EnumProperty('initialContrast', initialContrast)) ..add(DiagnosticsProperty('themeService', themeService)) ..add(ObjectFlagProperty.has('customBuilder', baseBuilder)) - ..add(DiagnosticsProperty('initialThemeData', initialThemeData)) - ..add(DiagnosticsProperty('initialRounded', initialRounded)); + ..add(DiagnosticsProperty('initialThemeData', initialLightThemeData)) + ..add(DiagnosticsProperty('initialRounded', initialRounded)) + ..add(DiagnosticsProperty('initialDarkThemeData', initialDarkThemeData)); } /// Retrieves the [ZetaProviderState] from the provided context. @@ -158,8 +164,11 @@ class ZetaProviderState extends State with Diagnosticable, Widgets /// {@macro zeta-component-rounded} late bool _rounded; - /// Represents the late initialization of the ThemeData object. - late ThemeData? _themeData; + /// Represents the late initialization of the light [ThemeData] object. + late ThemeData? _lightThemeData; + + /// Represents the late initialization of the dark [ThemeData] object. + late ThemeData? _darkThemeData; /// Represents a nullable brightness value to be used for brightness change debouncing. Brightness? _debounceBrightness; @@ -194,8 +203,11 @@ class ZetaProviderState extends State with Diagnosticable, Widgets // Apply the initial contrast to the theme data. _zetaThemeData = widget.initialZetaThemeData.apply(contrast: _contrast); - // Set the initial theme data. - _themeData = widget.initialThemeData; + // Set the initial light [ThemeData]. + _lightThemeData = widget.initialLightThemeData; + + // Set the initial light [ThemeData]. + _darkThemeData = widget.initialDarkThemeData; } /// Clean up function to be called when this object is removed from the tree. @@ -256,11 +268,13 @@ class ZetaProviderState extends State with Diagnosticable, Widgets context, generateZetaTheme( brightness: Brightness.light, - existingTheme: _themeData ?? ThemeData(colorScheme: _zetaThemeData.colorsLight.toScheme()), + existingTheme: _lightThemeData, + colorScheme: _lightThemeData?.colorScheme ?? _zetaThemeData.colorsLight.toScheme(), ), generateZetaTheme( brightness: Brightness.dark, - existingTheme: _themeData ?? ThemeData(colorScheme: _zetaThemeData.colorsDark.toScheme()), + existingTheme: _darkThemeData, + colorScheme: _darkThemeData?.colorScheme ?? _zetaThemeData.colorsDark.toScheme(), ), _themeMode, ), @@ -282,14 +296,14 @@ class ZetaProviderState extends State with Diagnosticable, Widgets super.didUpdateWidget(oldWidget); if (oldWidget.initialContrast != widget.initialContrast || oldWidget.initialThemeMode != widget.initialThemeMode || - oldWidget.initialThemeData != widget.initialThemeData || + oldWidget.initialLightThemeData != widget.initialLightThemeData || oldWidget.initialZetaThemeData != widget.initialZetaThemeData || oldWidget.initialRounded != widget.initialRounded) { setState(() { _themeMode = widget.initialThemeMode; _contrast = widget.initialContrast; _zetaThemeData = widget.initialZetaThemeData.apply(contrast: _contrast); - _themeData = widget.initialThemeData; + _lightThemeData = widget.initialLightThemeData; _rounded = widget.initialRounded; }); } @@ -352,16 +366,38 @@ class ZetaProviderState extends State with Diagnosticable, Widgets /// Creates a variant of [ThemeData] with added [Zeta] styles. ThemeData generateZetaTheme({ required Brightness brightness, + required ColorScheme colorScheme, ThemeData? existingTheme, String? fontFamily, }) { + if (existingTheme != null) { + // Apply the Zeta styles to the existing theme, ignoring fields that are the same as the default ThemeData. + return ThemeData( + brightness: brightness, + useMaterial3: existingTheme.useMaterial3, + fontFamily: fontFamily ?? + (existingTheme.textTheme.bodyMedium?.fontFamily == ThemeData().textTheme.bodyMedium?.fontFamily + ? null + : existingTheme.textTheme.bodyMedium?.fontFamily), + scaffoldBackgroundColor: (existingTheme.colorScheme.surfaceTertiary == ThemeData().colorScheme.surfaceTertiary + ? null + : existingTheme.colorScheme.surfaceTertiary) ?? + colorScheme.surfaceTertiary, + colorScheme: + ((existingTheme.colorScheme == ThemeData().colorScheme ? null : existingTheme.colorScheme) ?? colorScheme) + .copyWith(brightness: brightness), + textTheme: (existingTheme.textTheme == ThemeData().textTheme ? null : existingTheme.textTheme) ?? zetaTextTheme, + iconTheme: (existingTheme.iconTheme == ThemeData().iconTheme ? null : existingTheme.iconTheme) ?? + const IconThemeData(size: kZetaIconSize), + ); + } return ThemeData( - useMaterial3: existingTheme?.useMaterial3 ?? true, + useMaterial3: true, fontFamily: fontFamily ?? kZetaFontFamily, - brightness: existingTheme?.brightness ?? brightness, - scaffoldBackgroundColor: existingTheme?.colorScheme.surfaceTertiary, - colorScheme: existingTheme?.colorScheme, - textTheme: existingTheme?.textTheme ?? zetaTextTheme, - iconTheme: existingTheme?.iconTheme ?? const IconThemeData(size: 20), + brightness: brightness, + scaffoldBackgroundColor: colorScheme.surfaceTertiary, + colorScheme: colorScheme.copyWith(brightness: brightness), + textTheme: zetaTextTheme, + iconTheme: const IconThemeData(size: kZetaIconSize), ); } diff --git a/test/src/components/in_page_banner/golden/in_page_banner_negative.png b/test/src/components/in_page_banner/golden/in_page_banner_negative.png index 5f808d48..3088dce8 100644 Binary files a/test/src/components/in_page_banner/golden/in_page_banner_negative.png and b/test/src/components/in_page_banner/golden/in_page_banner_negative.png differ diff --git a/test/src/zeta_provider_test.dart b/test/src/zeta_provider_test.dart index efbe26f9..38f65a99 100644 --- a/test/src/zeta_provider_test.dart +++ b/test/src/zeta_provider_test.dart @@ -216,7 +216,7 @@ void main() { ), ), ); -//TODO: This does not work as expected + await tester.pumpAndSettle(const Duration(milliseconds: 250)); // Verifying through the public interface of Zeta widget