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;