From 245d39ddcab4117e570bbab4132ece4f1eea0e80 Mon Sep 17 00:00:00 2001 From: Luke Date: Mon, 12 Feb 2024 22:38:25 +0000 Subject: [PATCH] Added theme support for Widgetbook. This had been casuing issues where the theme mode was not rendering the correct widgets. This also lead to the discovery of theme issues on checkbox and avatar, which have been fixed. --- .../components/accordion_widgetbook.dart | 43 +++--- .../components/avatar_widgetbook.dart | 2 - .../components/badges_widgetbook.dart | 6 - .../components/banner_widgetbook.dart | 1 - .../components/bottom_sheet_widgetbook.dart | 2 - .../components/button_widgetbook.dart | 24 ++-- .../components/checkbox_widgetbook.dart | 94 +++++++++++-- .../components/chip_widgetbook.dart | 29 ++-- example/widgetbook/test/test_components.dart | 46 ++----- .../widgetbook/theme/color_widgetbook.dart | 112 ++++++++------- .../theme/typography_widgetbook.dart | 24 ++-- example/widgetbook/widgetbook.dart | 129 +++++++++++++----- lib/src/components/avatars/avatar.dart | 8 +- lib/src/components/badges/status_label.dart | 6 +- lib/src/components/banners/system_banner.dart | 1 + lib/src/components/checkbox/checkbox.dart | 34 ++--- 16 files changed, 336 insertions(+), 225 deletions(-) diff --git a/example/widgetbook/components/accordion_widgetbook.dart b/example/widgetbook/components/accordion_widgetbook.dart index 5df1a2d8..7943cda6 100644 --- a/example/widgetbook/components/accordion_widgetbook.dart +++ b/example/widgetbook/components/accordion_widgetbook.dart @@ -11,28 +11,29 @@ WidgetbookComponent accordionWidgetBook() { useCases: [ WidgetbookUseCase( name: 'Accordion', - builder: (context) => WidgetbookTestWidget( - themeMode: ThemeMode.dark, - widget: Padding( - padding: const EdgeInsets.all(20), - child: ZetaAccordion( - child: context.knobs.boolean(label: 'Disabled') - ? null - : Column( - children: [ - ListTile(title: Text('Item One')), - ListTile(title: Text('Item two')), - ListTile(title: Text('Item three')), - ListTile(title: Text('Item four')), - ], - ), - title: context.knobs.string(label: 'Accordion Title', initialValue: 'Title'), - contained: context.knobs.boolean(label: 'Contained', initialValue: false), - isOpen: context.knobs.boolean(label: 'Open', initialValue: false), - rounded: context.knobs.boolean(label: 'Rounded', initialValue: false), + builder: (context) { + return WidgetbookTestWidget( + widget: Padding( + padding: const EdgeInsets.all(20), + child: ZetaAccordion( + child: context.knobs.boolean(label: 'Disabled') + ? null + : Column( + children: [ + ListTile(title: Text('Item One')), + ListTile(title: Text('Item two')), + ListTile(title: Text('Item three')), + ListTile(title: Text('Item four')), + ], + ), + title: context.knobs.string(label: 'Accordion Title', initialValue: 'Title'), + contained: context.knobs.boolean(label: 'Contained', initialValue: false), + isOpen: context.knobs.boolean(label: 'Open', initialValue: false), + rounded: context.knobs.boolean(label: 'Rounded', initialValue: false), + ), ), - ), - ), + ); + }, ), ], ); diff --git a/example/widgetbook/components/avatar_widgetbook.dart b/example/widgetbook/components/avatar_widgetbook.dart index 8e16b1ab..e2a8d1f8 100644 --- a/example/widgetbook/components/avatar_widgetbook.dart +++ b/example/widgetbook/components/avatar_widgetbook.dart @@ -15,7 +15,6 @@ WidgetbookComponent avatarWidgetBook() { final Widget image = Image.network('https://i.ytimg.com/vi/KItsWUzFUOs/maxresdefault.jpg', fit: BoxFit.cover); return WidgetbookTestWidget( - themeMode: ThemeMode.dark, widget: Column( children: [ Padding( @@ -40,7 +39,6 @@ WidgetbookComponent avatarWidgetBook() { name: 'Initials Avatar', builder: (context) { return WidgetbookTestWidget( - themeMode: ThemeMode.dark, widget: Column( children: [ Padding( diff --git a/example/widgetbook/components/badges_widgetbook.dart b/example/widgetbook/components/badges_widgetbook.dart index 798902a2..ce3a3562 100644 --- a/example/widgetbook/components/badges_widgetbook.dart +++ b/example/widgetbook/components/badges_widgetbook.dart @@ -13,7 +13,6 @@ WidgetbookComponent badgeWidgetBook() { name: 'Status Label', builder: (context) { return WidgetbookTestWidget( - themeMode: ThemeMode.dark, widget: Column( children: [ Padding( @@ -48,7 +47,6 @@ WidgetbookComponent badgeWidgetBook() { WidgetbookUseCase( name: 'Priority Pill', builder: (context) => WidgetbookTestWidget( - themeMode: ThemeMode.dark, widget: Column( children: [ Padding( @@ -66,7 +64,6 @@ WidgetbookComponent badgeWidgetBook() { WidgetbookUseCase( name: 'Badge', builder: (context) => WidgetbookTestWidget( - themeMode: ThemeMode.dark, widget: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ @@ -85,7 +82,6 @@ WidgetbookComponent badgeWidgetBook() { WidgetbookUseCase( name: 'Indicators', builder: (context) => WidgetbookTestWidget( - themeMode: ThemeMode.dark, widget: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ @@ -121,7 +117,6 @@ WidgetbookComponent badgeWidgetBook() { WidgetbookUseCase( name: 'Tags', builder: (context) => WidgetbookTestWidget( - themeMode: ThemeMode.dark, widget: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ @@ -140,7 +135,6 @@ WidgetbookComponent badgeWidgetBook() { WidgetbookUseCase( name: 'Workcloud Indicators', builder: (context) => WidgetbookTestWidget( - themeMode: ThemeMode.dark, widget: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ diff --git a/example/widgetbook/components/banner_widgetbook.dart b/example/widgetbook/components/banner_widgetbook.dart index cf549758..4bec293f 100644 --- a/example/widgetbook/components/banner_widgetbook.dart +++ b/example/widgetbook/components/banner_widgetbook.dart @@ -49,7 +49,6 @@ WidgetbookComponent BannerWidgetBook() { WidgetbookUseCase( name: 'In Page Banner', builder: (context) => WidgetbookTestWidget( - themeMode: ThemeMode.dark, widget: Padding( padding: EdgeInsets.all(20), child: Column( diff --git a/example/widgetbook/components/bottom_sheet_widgetbook.dart b/example/widgetbook/components/bottom_sheet_widgetbook.dart index 53ef7ded..986796ea 100644 --- a/example/widgetbook/components/bottom_sheet_widgetbook.dart +++ b/example/widgetbook/components/bottom_sheet_widgetbook.dart @@ -12,7 +12,6 @@ WidgetbookComponent bottomSheetWidgetBook() { WidgetbookUseCase( name: 'Content', builder: (context) => WidgetbookTestWidget( - themeMode: ThemeMode.dark, widget: Padding( padding: const EdgeInsets.all(20), child: _bottomSheet(context), @@ -24,7 +23,6 @@ WidgetbookComponent bottomSheetWidgetBook() { builder: (context) { final sheet = _bottomSheet(context); return WidgetbookTestWidget( - themeMode: ThemeMode.dark, widget: Padding( padding: const EdgeInsets.all(20), child: ElevatedButton( diff --git a/example/widgetbook/components/button_widgetbook.dart b/example/widgetbook/components/button_widgetbook.dart index ac7bc83d..afbec8dd 100644 --- a/example/widgetbook/components/button_widgetbook.dart +++ b/example/widgetbook/components/button_widgetbook.dart @@ -13,15 +13,21 @@ WidgetbookComponent buttonWidgetBook() { name: 'Button', builder: (context) { return WidgetbookTestWidget( - widget: Padding( - padding: EdgeInsets.all(20), - child: ZetaButton( - label: context.knobs.string(label: 'Text', initialValue: 'Button'), - onPressed: context.knobs.boolean(label: 'Disabled') ? null : () {}, - borderType: context.knobs.boolean(label: 'Rounded') ? ZetaWidgetBorder.rounded : ZetaWidgetBorder.sharp, - size: context.knobs.list(label: 'Size', options: ZetaWidgetSize.values), - type: context.knobs.list(label: 'Type', options: ZetaButtonType.values), - ), + widget: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Padding( + padding: EdgeInsets.all(20), + child: ZetaButton( + label: context.knobs.string(label: 'Text', initialValue: 'Button'), + onPressed: context.knobs.boolean(label: 'Disabled') ? null : () {}, + borderType: + context.knobs.boolean(label: 'Rounded') ? ZetaWidgetBorder.rounded : ZetaWidgetBorder.sharp, + size: context.knobs.list(label: 'Size', options: ZetaWidgetSize.values), + type: context.knobs.list(label: 'Type', options: ZetaButtonType.values), + ), + ), + ], ), ); }, diff --git a/example/widgetbook/components/checkbox_widgetbook.dart b/example/widgetbook/components/checkbox_widgetbook.dart index 87f79678..38218b07 100644 --- a/example/widgetbook/components/checkbox_widgetbook.dart +++ b/example/widgetbook/components/checkbox_widgetbook.dart @@ -10,23 +10,87 @@ WidgetbookComponent checkboxWidgetBook() { name: 'Checkbox', useCases: [ WidgetbookUseCase( - name: 'Checkbox', - builder: (context) => WidgetbookTestWidget( - widget: Column( - children: [ - Padding( - padding: EdgeInsets.only(top: 10), - child: ZetaCheckbox( - value: context.knobs.booleanOrNull(label: 'Checked'), - onChanged: context.knobs.boolean(label: 'Enabled', initialValue: true) ? (_) {} : null, - rounded: context.knobs.boolean(label: 'Rounded'), - label: context.knobs.string(label: 'Label', initialValue: 'Checkbox'), + name: 'Checked', + builder: (context) { + return WidgetbookTestWidget( + widget: Column( + children: [ + Padding( + padding: EdgeInsets.only(top: 10), + child: _CheckState(context: context, initialState: true), ), - ), - ], - ), - ), + ], + ), + ); + }, + ), + WidgetbookUseCase( + name: 'Indeterminate', + builder: (context) { + return WidgetbookTestWidget( + widget: Column( + children: [ + Padding( + padding: EdgeInsets.only(top: 10), + child: _CheckState(context: context, initialState: null), + ), + ], + ), + ); + }, + ), + WidgetbookUseCase( + name: 'Unchecked', + builder: (context) { + return WidgetbookTestWidget( + widget: Column( + children: [ + Padding( + padding: EdgeInsets.only(top: 10), + child: _CheckState(context: context, initialState: false), + ), + ], + ), + ); + }, ), ], ); } + +class _CheckState extends StatefulWidget { + final BuildContext context; + final bool? initialState; + const _CheckState({required this.context, this.initialState}); + + @override + State<_CheckState> createState() => __CheckStateState(); +} + +class __CheckStateState extends State<_CheckState> { + bool? b = null; + + @override + void initState() { + super.initState(); + b = widget.initialState; + } + + @override + Widget build(BuildContext _) { + dynamic onChanged = + context.knobs.boolean(label: 'Enabled', initialValue: true) ? (b2) => setState(() => b = b2) : null; + + return Column( + children: [ + ZetaCheckbox( + value: b, + onChanged: onChanged, + useIndeterminate: context.knobs.boolean(label: 'Use Indeterminate', initialValue: true), + rounded: context.knobs.boolean(label: 'Rounded'), + label: context.knobs.string(label: 'Label', initialValue: 'Checkbox'), + ), + ], + ); + } +} diff --git a/example/widgetbook/components/chip_widgetbook.dart b/example/widgetbook/components/chip_widgetbook.dart index 9a11ea42..89fc8ea3 100644 --- a/example/widgetbook/components/chip_widgetbook.dart +++ b/example/widgetbook/components/chip_widgetbook.dart @@ -30,16 +30,25 @@ WidgetbookComponent chipWidgetBook() { }, ); return WidgetbookTestWidget( - widget: ZetaInputChip( - label: context.knobs.string(label: 'Label', initialValue: 'Label'), - leading: context.knobs.boolean(label: 'Avatar') - ? ZetaAvatar( - initials: 'AZ', - size: ZetaAvatarSize.xs, - ) - : null, - rounded: context.knobs.boolean(label: 'Rounded'), - trailing: trailing != null ? Icon(trailing) : null, + widget: Padding( + padding: const EdgeInsets.all(20), + child: Row( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + ZetaInputChip( + label: context.knobs.string(label: 'Label', initialValue: 'Label'), + leading: context.knobs.boolean(label: 'Avatar') + ? ZetaAvatar( + initials: 'AZ', + size: ZetaAvatarSize.xs, + ) + : null, + rounded: context.knobs.boolean(label: 'Rounded'), + trailing: trailing != null ? Icon(trailing) : null, + ), + ], + ), ), ); }, diff --git a/example/widgetbook/test/test_components.dart b/example/widgetbook/test/test_components.dart index bfd99ce2..c6d62693 100644 --- a/example/widgetbook/test/test_components.dart +++ b/example/widgetbook/test/test_components.dart @@ -1,17 +1,14 @@ import 'package:flutter/material.dart'; -import 'package:zeta_flutter/zeta_flutter.dart'; class WidgetbookTestWidget extends StatelessWidget { final Size? screenSize; final Widget widget; - final ThemeMode? themeMode; final bool removeBody; const WidgetbookTestWidget({ required this.widget, this.screenSize, super.key, - this.themeMode, this.removeBody = false, }); @@ -19,39 +16,18 @@ class WidgetbookTestWidget extends StatelessWidget { Widget build(BuildContext context) { final size = screenSize ?? const Size(1280, 720); - return ZetaProvider( - initialThemeMode: themeMode ?? ThemeMode.system, - builder: (context, theme, __) { - return Builder( - builder: (context) { - return MaterialApp( - debugShowCheckedModeBanner: false, - theme: ThemeData( - fontFamily: theme.fontFamily, - colorScheme: theme.colorsLight.toScheme(), - textTheme: zetaTextTheme, + return Scaffold( + backgroundColor: Colors.transparent, + body: removeBody + ? widget + : SizedBox( + width: size.width, + height: size.height, + child: MediaQuery( + data: MediaQueryData(size: Size(size.width, size.height)), + child: SingleChildScrollView(child: widget), ), - darkTheme: ThemeData( - fontFamily: theme.fontFamily, - colorScheme: theme.colorsDark.toScheme(), - textTheme: zetaTextTheme, - ), - home: Scaffold( - body: removeBody - ? widget - : SizedBox( - width: size.width, - height: size.height, - child: MediaQuery( - data: MediaQueryData(size: Size(size.width, size.height)), - child: SingleChildScrollView(child: widget), - ), - ), - ), - ); - }, - ); - }, + ), ); } } diff --git a/example/widgetbook/theme/color_widgetbook.dart b/example/widgetbook/theme/color_widgetbook.dart index 8beaf9cb..1a7a5553 100644 --- a/example/widgetbook/theme/color_widgetbook.dart +++ b/example/widgetbook/theme/color_widgetbook.dart @@ -16,15 +16,6 @@ WidgetbookComponent colorWidgetBook() { ); }, ), - WidgetbookUseCase( - name: 'Dark Mode', - builder: (BuildContext context) { - return ZetaProvider( - initialThemeMode: ThemeMode.dark, - builder: (_, __, ___) => ColorBody(), - ); - }, - ) ], ); } @@ -84,58 +75,63 @@ class ColorBody extends StatelessWidget { 'info': colors.info, }; - return Container( - padding: const EdgeInsets.symmetric(horizontal: ZetaSpacing.l), - child: SingleChildScrollView( - child: Column( - children: [ - const SizedBox(height: ZetaSpacing.l), - MyRow(children: textIcon, title: 'Text and icon styles'), - MyRow(children: border, title: 'Border styles'), - MyRow(children: links, title: 'Links'), - MyRow(children: backdrop, title: 'Backdrop colors'), - MyRow(children: alerts, title: 'Alert colors'), - Row(children: [Text('Full color swatches', style: ZetaTextStyles.displayMedium)]) - .paddingVertical(ZetaSpacing.x8), - ...swatches.entries.map( - (value) { - return Row( - children: List.generate(10, (index) => 100 - (10 * index)).map( - (e) { - return Expanded( - child: Container( - height: constraints.maxWidth / 10, - color: value.value[e], - child: FittedBox( - fit: BoxFit.scaleDown, - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - DefaultTextStyle( - style: ZetaTextStyles.bodyMedium.copyWith( - color: calculateTextColor(value.value[e] ?? Colors.white), - ), - child: Column( - children: [ - Text('${value.key.toLowerCase().replaceAll(' ', '')}-$e'), - Text( - value.value[e].toString().replaceAll('Color(0xff', '#').substring(0, 7), - ), - ], + return DefaultTextStyle( + style: ZetaTextStyles.displayMedium.apply( + color: Zeta.of(context).colors.cool, + decoration: TextDecoration.none, + ), + child: Container( + padding: const EdgeInsets.symmetric(horizontal: ZetaSpacing.l), + child: SingleChildScrollView( + child: Column( + children: [ + const SizedBox(height: ZetaSpacing.l), + MyRow(children: textIcon, title: 'Text and icon styles'), + MyRow(children: border, title: 'Border styles'), + MyRow(children: links, title: 'Links'), + MyRow(children: backdrop, title: 'Backdrop colors'), + MyRow(children: alerts, title: 'Alert colors'), + Row(children: [Text('Full color swatches')]).paddingVertical(ZetaSpacing.x8), + ...swatches.entries.map( + (value) { + return Row( + children: List.generate(10, (index) => 100 - (10 * index)).map( + (e) { + return Expanded( + child: Container( + height: constraints.maxWidth / 10, + color: value.value[e], + child: FittedBox( + fit: BoxFit.scaleDown, + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + DefaultTextStyle( + style: ZetaTextStyles.bodyMedium.copyWith( + color: calculateTextColor(value.value[e] ?? Colors.white), + ), + child: Column( + children: [ + Text('${value.key.toLowerCase().replaceAll(' ', '')}-$e'), + Text( + value.value[e].toString().replaceAll('Color(0xff', '#').substring(0, 7), + ), + ], + ), ), - ), - ], + ], + ), ), ), - ), - ); - }, - ).toList(), - ); - }, - ), - const SizedBox(height: ZetaSpacing.l), - ], + ); + }, + ).toList(), + ); + }, + ), + const SizedBox(height: ZetaSpacing.l), + ], + ), ), ), ); diff --git a/example/widgetbook/theme/typography_widgetbook.dart b/example/widgetbook/theme/typography_widgetbook.dart index 6eb20fe5..dc1b8a22 100644 --- a/example/widgetbook/theme/typography_widgetbook.dart +++ b/example/widgetbook/theme/typography_widgetbook.dart @@ -28,17 +28,19 @@ WidgetbookComponent textWidgetBook() { useCases: [ WidgetbookUseCase( name: 'Text styles', - builder: (context) => Container( - color: Theme.of(context).colorScheme.background, - padding: const EdgeInsets.all(ZetaSpacing.l), - child: Text( - context.knobs.string(label: 'Text', initialValue: 'The quick brown fox jumps over the lazy dog.'), - style: context.knobs.list( - label: 'Sizes', - labelBuilder: (p0) => dedicatedSizes.entries.firstWhere((element) => element.value == p0).key, - options: dedicatedSizes.values.toList(), - ), - ), + builder: (context) => Text( + context.knobs.string(label: 'Text', initialValue: 'The quick brown fox jumps over the lazy dog.'), + style: context.knobs + .list( + label: 'Sizes', + labelBuilder: (p0) => dedicatedSizes.entries.firstWhere((element) => element.value == p0).key, + options: dedicatedSizes.values.toList(), + ) + .apply( + color: Zeta.of(context).colors.textDefault, + fontStyle: FontStyle.normal, + decoration: TextDecoration.none, + ), ), ), ], diff --git a/example/widgetbook/widgetbook.dart b/example/widgetbook/widgetbook.dart index 507d869a..7d670471 100644 --- a/example/widgetbook/widgetbook.dart +++ b/example/widgetbook/widgetbook.dart @@ -20,45 +20,100 @@ class HotReload extends StatelessWidget { @override Widget build(BuildContext context) { - return ZetaProvider( - builder: (context, theme, colors) { - return Widgetbook.material( - directories: [ - WidgetbookCategory( - name: 'Components', - isInitiallyExpanded: false, - children: [ - badgeWidgetBook(), - avatarWidgetBook(), - checkboxWidgetBook(), - buttonWidgetBook(), - BannerWidgetBook(), - accordionWidgetBook(), - chipWidgetBook(), - passwordInputWidgetBook(), - bottomSheetWidgetBook(), - ]..sort((a, b) => a.name.compareTo(b.name)), - ), - WidgetbookCategory( - name: 'Theme', - isInitiallyExpanded: false, - children: [textWidgetBook(), colorWidgetBook(), checkboxWidgetBook()], - ), + return Widgetbook( + appBuilder: (context, child) => child, + directories: [ + WidgetbookCategory( + name: 'Components', + isInitiallyExpanded: false, + children: [ + badgeWidgetBook(), + avatarWidgetBook(), + checkboxWidgetBook(), + buttonWidgetBook(), + BannerWidgetBook(), + accordionWidgetBook(), + chipWidgetBook(), + passwordInputWidgetBook(), + bottomSheetWidgetBook(), + ]..sort((a, b) => a.name.compareTo(b.name)), + ), + WidgetbookCategory( + name: 'Theme', + isInitiallyExpanded: false, + children: [textWidgetBook(), colorWidgetBook()]..sort((a, b) => a.name.compareTo(b.name)), + ), + ], + addons: [ + DeviceFrameAddon( + devices: [ + Devices.windows.wideMonitor, + Devices.macOS.wideMonitor, + Devices.ios.iPad, + Devices.ios.iPhone13, + Zebra.ec30, + Zebra.ec50, ], - addons: [ - DeviceFrameAddon( - devices: [ - Devices.windows.wideMonitor, - Devices.macOS.wideMonitor, - Devices.ios.iPad, - Devices.ios.iPhone13, - Zebra.ec30, - Zebra.ec50, - ], - ), + ), + ThemeAddon( + themes: [ + WidgetbookTheme(name: 'Light Mode', data: _Theme(isDark: false, isAAA: false)), + WidgetbookTheme(name: 'Dark Mode', data: _Theme(isDark: true, isAAA: false)), + WidgetbookTheme(name: 'Light Mode AAA', data: _Theme(isDark: false, isAAA: true)), + WidgetbookTheme(name: 'Dark Mode AAA', data: _Theme(isDark: true, isAAA: true)), ], - ); - }, + themeBuilder: (context, theme, child) { + _Theme _theme = theme; + // Wrap use cases with the custom theme's InheritedWidget + return ZetaProvider( + initialContrast: _theme.isAAA ? ZetaContrast.aaa : ZetaContrast.aa, + initialThemeMode: _theme.isDark ? ThemeMode.dark : ThemeMode.light, + builder: (context, theme, themeMode) { + return Builder( + builder: (context) { + final dark = theme.colorsDark.toScheme(); + final light = theme.colorsLight.toScheme(); + + print(child); + return MaterialApp( + debugShowCheckedModeBanner: false, + themeMode: themeMode, + theme: ThemeData( + useMaterial3: true, + scaffoldBackgroundColor: light.background, + colorScheme: light, + textTheme: zetaTextTheme, + brightness: Brightness.light, + ), + darkTheme: ThemeData( + useMaterial3: true, + scaffoldBackgroundColor: dark.background, + colorScheme: dark, + textTheme: zetaTextTheme, + brightness: Brightness.dark, + ), + builder: (context, child) { + return ColoredBox( + color: Zeta.of(context).colors.surfacePrimary, + child: child, + ); + }, + home: child, + ); + }, + ); + }, + ); + }, + ), + ], ); } } + +class _Theme { + final bool isDark; + final bool isAAA; + + _Theme({required this.isDark, required this.isAAA}); +} diff --git a/lib/src/components/avatars/avatar.dart b/lib/src/components/avatars/avatar.dart index 376c9f28..5a2fa7e2 100644 --- a/lib/src/components/avatars/avatar.dart +++ b/lib/src/components/avatars/avatar.dart @@ -146,7 +146,13 @@ class ZetaAvatar extends StatelessWidget { ), child: ClipRRect(borderRadius: ZetaRadius.full, clipBehavior: Clip.hardEdge, child: innerContent), ) - : innerContent, + : DecoratedBox( + decoration: BoxDecoration( + borderRadius: ZetaRadius.full, + color: backgroundColor ?? zetaColors.surfaceHovered, + ), + child: innerContent, + ), ), if (upperBadge != null) Positioned( diff --git a/lib/src/components/badges/status_label.dart b/lib/src/components/badges/status_label.dart index e403d0a2..acb035d5 100644 --- a/lib/src/components/badges/status_label.dart +++ b/lib/src/components/badges/status_label.dart @@ -43,7 +43,11 @@ class ZetaStatusLabel extends StatelessWidget { child: Row( mainAxisSize: MainAxisSize.min, children: [ - Icon(customIcon ?? Icons.circle, size: ZetaSpacing.x2, color: colors.icon), + Icon( + customIcon ?? Icons.circle, + size: customIcon != null ? ZetaSpacing.x5 : ZetaSpacing.x2, + color: colors.icon, + ), const SizedBox(width: ZetaSpacing.xs), Text( label, diff --git a/lib/src/components/banners/system_banner.dart b/lib/src/components/banners/system_banner.dart index 40f2cc34..e6b40dff 100644 --- a/lib/src/components/banners/system_banner.dart +++ b/lib/src/components/banners/system_banner.dart @@ -35,6 +35,7 @@ class ZetaSystemBanner extends MaterialBanner { bool titleStart = false, Widget? trailing, }) : super( + dividerColor: Colors.transparent, content: Builder( builder: (context) { final backgroundColor = _backgroundColorFromType(context, type); diff --git a/lib/src/components/checkbox/checkbox.dart b/lib/src/components/checkbox/checkbox.dart index 96c4c18d..350f49b0 100644 --- a/lib/src/components/checkbox/checkbox.dart +++ b/lib/src/components/checkbox/checkbox.dart @@ -31,6 +31,7 @@ class ZetaCheckbox extends FormField { useIndeterminate: useIndeterminate, value: value, error: !field.isValid, + enabled: onChanged != null, ); }, ); @@ -75,18 +76,19 @@ class ZetaCheckboxFormFieldState extends FormFieldState { class _Checkbox extends StatefulWidget { const _Checkbox({ this.value = false, - this.onChanged, + required this.onChanged, this.label, this.rounded = true, this.useIndeterminate = false, this.error = false, + required this.enabled, }); /// Whether the checkbox is selected, unselected or null (indeterminate) final bool? value; /// Called when the value of the checkbox should change. - final ValueChanged? onChanged; + final ValueChanged onChanged; /// The label displayed next to the checkbox final String? label; @@ -101,6 +103,8 @@ class _Checkbox extends StatefulWidget { final bool error; + final bool enabled; + @override State<_Checkbox> createState() => _CheckboxState(); @override @@ -108,17 +112,16 @@ class _Checkbox extends StatefulWidget { super.debugFillProperties(properties); properties ..add(DiagnosticsProperty('value', value)) - ..add(ObjectFlagProperty?>.has('onChanged', onChanged)) ..add(StringProperty('label', label)) ..add(DiagnosticsProperty('rounded', rounded)) ..add(DiagnosticsProperty('useIndeterminate', useIndeterminate)) - ..add(DiagnosticsProperty('error', error)); + ..add(DiagnosticsProperty('error', error)) + ..add(DiagnosticsProperty('enabled', enabled)) + ..add(ObjectFlagProperty>.has('onChanged', onChanged)); } } class _CheckboxState extends State<_Checkbox> { - bool get _enabled => widget.onChanged != null; - bool? get _value => widget.useIndeterminate ? widget.value : (widget.value ?? false); bool? get _updatedValue { @@ -141,18 +144,17 @@ class _CheckboxState extends State<_Checkbox> { @override Widget build(BuildContext context) { return Semantics( - checked: _value ?? false, mixed: widget.useIndeterminate, - enabled: _enabled, + enabled: widget.enabled, child: MouseRegion( - cursor: _enabled ? SystemMouseCursors.click : SystemMouseCursors.forbidden, + cursor: widget.enabled ? SystemMouseCursors.click : SystemMouseCursors.forbidden, onEnter: (event) => setState(() => _isHovered = true), onExit: (event) => setState(() => _isHovered = false), - child: _enabled + child: widget.enabled ? FocusableActionDetector( onFocusChange: (bool focus) => setState(() => _isFocused = focus), child: GestureDetector( - onTap: _enabled ? () => widget.onChanged?.call(_updatedValue) : null, + onTap: widget.enabled ? () => widget.onChanged.call(_updatedValue) : null, child: _buildContent(context), ), ) @@ -174,7 +176,7 @@ class _CheckboxState extends State<_Checkbox> { : widget.rounded ? ZetaIcons.remove_round : ZetaIcons.remove_sharp, - color: _enabled ? theme.colors.white : theme.colors.textDisabled, + color: widget.enabled ? theme.colors.white : theme.colors.textDisabled, size: ZetaSpacing.x3_5, ); @@ -186,7 +188,7 @@ class _CheckboxState extends State<_Checkbox> { duration: const Duration(milliseconds: 200), decoration: BoxDecoration( boxShadow: [ - if (_isFocused && _enabled) + if (_isFocused && widget.enabled) BoxShadow( spreadRadius: 2, blurStyle: BlurStyle.solid, @@ -194,7 +196,7 @@ class _CheckboxState extends State<_Checkbox> { ), ], color: _getBackground(theme), - border: _enabled ? Border.all(color: _getBorderColor(theme), width: ZetaSpacing.x0_5) : null, + border: widget.enabled ? Border.all(color: _getBorderColor(theme), width: ZetaSpacing.x0_5) : null, borderRadius: widget.rounded ? ZetaRadius.minimal : ZetaRadius.none, ), width: ZetaSpacing.x5, @@ -215,8 +217,8 @@ class _CheckboxState extends State<_Checkbox> { Color _getBackground(Zeta theme) { final ZetaColorSwatch color = widget.error ? theme.colors.error : theme.colors.primary; - - if (!_enabled || (_value != null && !_value!)) return theme.colors.surfacePrimary; + if (!widget.enabled) return theme.colors.surfaceDisabled; + if (_value != null && !_value!) return theme.colors.surfacePrimary; if (_isHovered) return color.hover; return color;