diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml index df90b783..30591e87 100644 --- a/.github/workflows/pull-request.yml +++ b/.github/workflows/pull-request.yml @@ -95,7 +95,7 @@ jobs: - name: Build example app run: | cd example - flutter build web -o ../build --no-tree-shake-icons + flutter build web -t widgetbook/main.dart -o ../build --no-tree-shake-icons - uses: FirebaseExtended/action-hosting-deploy@v0 with: repoToken: "${{ secrets.GITHUB_TOKEN }}" diff --git a/example/pubspec.yaml b/example/pubspec.yaml index 6b891784..00110aaa 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -12,6 +12,7 @@ dependencies: sdk: flutter go_router: ^11.1.2 google_fonts: ^6.1.0 + path_drawing: ^1.0.1 shared_preferences: ^2.2.2 zeta_flutter: path: ../ diff --git a/example/widgetbook/components/accordion_widgetbook.dart b/example/widgetbook/components/accordion_widgetbook.dart deleted file mode 100644 index 5df1a2d8..00000000 --- a/example/widgetbook/components/accordion_widgetbook.dart +++ /dev/null @@ -1,39 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:widgetbook/widgetbook.dart'; -import 'package:zeta_flutter/zeta_flutter.dart'; - -import '../test/test_components.dart'; - -WidgetbookComponent accordionWidgetBook() { - return WidgetbookComponent( - isInitiallyExpanded: false, - name: 'Accordion', - 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), - ), - ), - ), - ), - ], - ); -} diff --git a/example/widgetbook/components/checkbox_widgetbook.dart b/example/widgetbook/components/checkbox_widgetbook.dart deleted file mode 100644 index 87f79678..00000000 --- a/example/widgetbook/components/checkbox_widgetbook.dart +++ /dev/null @@ -1,32 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:widgetbook/widgetbook.dart'; -import 'package:zeta_flutter/zeta_flutter.dart'; - -import '../test/test_components.dart'; - -WidgetbookComponent checkboxWidgetBook() { - return WidgetbookComponent( - isInitiallyExpanded: false, - 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'), - ), - ), - ], - ), - ), - ), - ], - ); -} diff --git a/example/widgetbook/pages/assets/icon_widgetbook.dart b/example/widgetbook/pages/assets/icon_widgetbook.dart new file mode 100644 index 00000000..897eb07d --- /dev/null +++ b/example/widgetbook/pages/assets/icon_widgetbook.dart @@ -0,0 +1,63 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:widgetbook/widgetbook.dart'; +import 'package:zeta_flutter/zeta_flutter.dart'; + +import '../../test/test_components.dart'; + +WidgetbookComponent iconWidgetbook() { + return WidgetbookComponent( + isInitiallyExpanded: false, + name: 'Icons', + useCases: [ + WidgetbookUseCase( + name: 'All Icons', + builder: (context) { + Map icons = + (context.knobs.boolean(label: 'Rounded', initialValue: true)) ? iconsRounded : iconsSharp; + + return WidgetbookTestWidget( + removeBody: true, + widget: SingleChildScrollView( + child: Center( + child: Column( + children: [ + Text('Tap icon to copy name to clipboard', style: ZetaTextStyles.titleMedium) + .paddingAll(ZetaSpacing.l), + Wrap( + spacing: ZetaSpacing.l, + runSpacing: ZetaSpacing.l, + children: icons.entries.map( + (e) { + final nameArr = e.key.split('_')..removeLast(); + return Container( + width: 100, + height: 100, + child: InkWell( + borderRadius: ZetaRadius.rounded, + hoverColor: Zeta.of(context).colors.surfaceHovered, + onTap: () async { + await Clipboard.setData(ClipboardData(text: 'ZetaIcons.' + e.key)); + }, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon(e.value, size: 40), + Text(nameArr.join(' '), textAlign: TextAlign.center) + ], + ), + ), + ); + }, + ).toList(), + ), + ], + ), + ), + ), + ); + }, + ), + ], + ); +} diff --git a/example/widgetbook/pages/components/accordion_widgetbook.dart b/example/widgetbook/pages/components/accordion_widgetbook.dart new file mode 100644 index 00000000..d7297153 --- /dev/null +++ b/example/widgetbook/pages/components/accordion_widgetbook.dart @@ -0,0 +1,40 @@ +import 'package:flutter/material.dart'; +import 'package:widgetbook/widgetbook.dart'; +import 'package:zeta_flutter/zeta_flutter.dart'; + +import '../../test/test_components.dart'; + +WidgetbookComponent accordionWidgetBook() { + return WidgetbookComponent( + isInitiallyExpanded: false, + name: 'Accordion', + useCases: [ + WidgetbookUseCase( + name: 'Accordion', + 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/pages/components/avatar_widgetbook.dart similarity index 95% rename from example/widgetbook/components/avatar_widgetbook.dart rename to example/widgetbook/pages/components/avatar_widgetbook.dart index 8e16b1ab..0a91e51c 100644 --- a/example/widgetbook/components/avatar_widgetbook.dart +++ b/example/widgetbook/pages/components/avatar_widgetbook.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import 'package:widgetbook/widgetbook.dart'; import 'package:zeta_flutter/zeta_flutter.dart'; -import '../test/test_components.dart'; +import '../../test/test_components.dart'; WidgetbookComponent avatarWidgetBook() { return WidgetbookComponent( @@ -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/pages/components/badges_widgetbook.dart similarity index 96% rename from example/widgetbook/components/badges_widgetbook.dart rename to example/widgetbook/pages/components/badges_widgetbook.dart index 798902a2..6cdafb88 100644 --- a/example/widgetbook/components/badges_widgetbook.dart +++ b/example/widgetbook/pages/components/badges_widgetbook.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import 'package:widgetbook/widgetbook.dart'; import 'package:zeta_flutter/zeta_flutter.dart'; -import '../test/test_components.dart'; +import '../../test/test_components.dart'; WidgetbookComponent badgeWidgetBook() { return WidgetbookComponent( @@ -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/pages/components/banner_widgetbook.dart similarity index 97% rename from example/widgetbook/components/banner_widgetbook.dart rename to example/widgetbook/pages/components/banner_widgetbook.dart index cf549758..de5b538c 100644 --- a/example/widgetbook/components/banner_widgetbook.dart +++ b/example/widgetbook/pages/components/banner_widgetbook.dart @@ -2,9 +2,9 @@ import 'package:flutter/material.dart'; import 'package:widgetbook/widgetbook.dart'; import 'package:zeta_flutter/zeta_flutter.dart'; -import '../test/test_components.dart'; +import '../../test/test_components.dart'; -WidgetbookComponent BannerWidgetBook() { +WidgetbookComponent bannerWidgetBook() { return WidgetbookComponent( isInitiallyExpanded: false, name: 'Banners', @@ -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/pages/components/bottom_sheet_widgetbook.dart similarity index 94% rename from example/widgetbook/components/bottom_sheet_widgetbook.dart rename to example/widgetbook/pages/components/bottom_sheet_widgetbook.dart index 53ef7ded..a305ebcf 100644 --- a/example/widgetbook/components/bottom_sheet_widgetbook.dart +++ b/example/widgetbook/pages/components/bottom_sheet_widgetbook.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import 'package:widgetbook/widgetbook.dart'; import 'package:zeta_flutter/zeta_flutter.dart'; -import '../test/test_components.dart'; +import '../../test/test_components.dart'; WidgetbookComponent bottomSheetWidgetBook() { return WidgetbookComponent( @@ -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/pages/components/button_widgetbook.dart similarity index 77% rename from example/widgetbook/components/button_widgetbook.dart rename to example/widgetbook/pages/components/button_widgetbook.dart index ac7bc83d..74161006 100644 --- a/example/widgetbook/components/button_widgetbook.dart +++ b/example/widgetbook/pages/components/button_widgetbook.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import 'package:widgetbook/widgetbook.dart'; import 'package:zeta_flutter/zeta_flutter.dart'; -import '../test/test_components.dart'; +import '../../test/test_components.dart'; WidgetbookComponent buttonWidgetBook() { return WidgetbookComponent( @@ -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/pages/components/checkbox_widgetbook.dart b/example/widgetbook/pages/components/checkbox_widgetbook.dart new file mode 100644 index 00000000..eeef1945 --- /dev/null +++ b/example/widgetbook/pages/components/checkbox_widgetbook.dart @@ -0,0 +1,96 @@ +import 'package:flutter/material.dart'; +import 'package:widgetbook/widgetbook.dart'; +import 'package:zeta_flutter/zeta_flutter.dart'; + +import '../../test/test_components.dart'; + +WidgetbookComponent checkboxWidgetBook() { + return WidgetbookComponent( + isInitiallyExpanded: false, + name: 'Checkbox', + useCases: [ + WidgetbookUseCase( + 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/pages/components/chip_widgetbook.dart similarity index 73% rename from example/widgetbook/components/chip_widgetbook.dart rename to example/widgetbook/pages/components/chip_widgetbook.dart index 9a11ea42..e4f1a9f4 100644 --- a/example/widgetbook/components/chip_widgetbook.dart +++ b/example/widgetbook/pages/components/chip_widgetbook.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import 'package:widgetbook/widgetbook.dart'; import 'package:zeta_flutter/zeta_flutter.dart'; -import '../test/test_components.dart'; +import '../../test/test_components.dart'; WidgetbookComponent chipWidgetBook() { return WidgetbookComponent( @@ -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/components/password_input_widgetbook.dart b/example/widgetbook/pages/components/password_input_widgetbook.dart similarity index 98% rename from example/widgetbook/components/password_input_widgetbook.dart rename to example/widgetbook/pages/components/password_input_widgetbook.dart index 539c2baa..eca168ef 100644 --- a/example/widgetbook/components/password_input_widgetbook.dart +++ b/example/widgetbook/pages/components/password_input_widgetbook.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import 'package:widgetbook/widgetbook.dart'; import 'package:zeta_flutter/zeta_flutter.dart'; -import '../test/test_components.dart'; +import '../../test/test_components.dart'; WidgetbookComponent passwordInputWidgetBook() { return WidgetbookComponent( diff --git a/example/widgetbook/pages/theme/color_widgetbook.dart b/example/widgetbook/pages/theme/color_widgetbook.dart new file mode 100644 index 00000000..5afd0cfa --- /dev/null +++ b/example/widgetbook/pages/theme/color_widgetbook.dart @@ -0,0 +1,140 @@ +import 'package:flutter/material.dart'; +import 'package:widgetbook/widgetbook.dart'; +import 'package:zeta_example/pages/theme/color_example.dart'; +import 'package:zeta_flutter/zeta_flutter.dart'; + +WidgetbookComponent colorWidgetBook() { + return WidgetbookComponent( + name: 'Colors', + useCases: [ + WidgetbookUseCase( + name: 'Colors', + builder: (BuildContext context) { + return ZetaProvider( + initialThemeMode: ThemeMode.light, + builder: (_, __, ___) => ColorBody(), + ); + }, + ), + ], + ); +} + +class ColorBody extends StatelessWidget { + const ColorBody({ + super.key, + }); + + @override + Widget build(BuildContext context) { + return LayoutBuilder(builder: (_, constraints) { + final colors = Zeta.of(context).colors; + + final Map swatches = { + 'Blue': colors.blue, + 'Green': colors.green, + 'Red': colors.red, + 'Orange': colors.orange, + 'Purple': colors.purple, + 'Yellow': colors.yellow, + 'Teal': colors.teal, + 'Pink': colors.pink, + 'Grey Warm': colors.warm, + 'Grey Cool': colors.cool, + }; + final Map textIcon = { + 'textDefault': colors.textDefault, + 'textSubtle': colors.textSubtle, + 'textDisabled': colors.textDisabled, + 'textInverse': colors.textInverse, + }; + final Map border = { + 'borderDefault': colors.borderDefault, + 'borderSubtle': colors.borderSubtle, + 'borderDisabled': colors.borderDisabled, + 'borderSelected': colors.borderSelected, + }; + final Map links = { + 'linkDefault': colors.link, + 'linkVisited': colors.linkVisited, + }; + final Map backdrop = { + 'surfacePrimary': colors.surfacePrimary, + 'surfaceDisabled': colors.surfaceDisabled, + 'surfaceHovered': colors.surfaceHovered, + 'surfaceSecondary': colors.surfaceSecondary, + 'surfaceTertiary': colors.surfaceTertiary, + 'surfaceSelectedHovered': colors.surfaceSelectedHovered, + 'surfaceSelected': colors.surfaceSelected, + }; + + final Map alerts = { + 'positive': colors.positive, + 'negative': colors.negative, + 'warning': colors.warning, + 'info': colors.info, + }; + + 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), + ], + ), + ), + ), + ); + }); + } +} diff --git a/example/widgetbook/pages/theme/radius_widgetbook.dart b/example/widgetbook/pages/theme/radius_widgetbook.dart new file mode 100644 index 00000000..ccb63a73 --- /dev/null +++ b/example/widgetbook/pages/theme/radius_widgetbook.dart @@ -0,0 +1,75 @@ +import 'package:flutter/material.dart'; +import 'package:widgetbook/widgetbook.dart'; + +import 'package:zeta_flutter/zeta_flutter.dart'; + +WidgetbookComponent radiusWidgetbook() { + return WidgetbookComponent( + name: 'Radius', + useCases: [ + WidgetbookUseCase( + name: 'Radius', + builder: (context) => SingleChildScrollView( + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Column( + children: radii.entries + .map((obj) => _RadiiDemo(obj)) + .divide(const SizedBox.square(dimension: ZetaSpacing.l)) + .toList(), + ).paddingTop(ZetaSpacing.l), + ], + ), + ), + ), + ], + ); +} + +Map radii = { + 'none': ZetaRadius.none, + 'minimal': ZetaRadius.minimal, + 'rounded': ZetaRadius.rounded, + 'wide': ZetaRadius.wide, + 'full': ZetaRadius.full, +}; + +class _RadiiDemo extends StatelessWidget { + final MapEntry obj; + const _RadiiDemo(this.obj); + + @override + Widget build(BuildContext context) { + final colors = Zeta.of(context).colors; + + return Container( + width: 250, + height: 250, + decoration: BoxDecoration( + borderRadius: obj.value, + color: Zeta.of(context).colors.blue.shade30, + border: Border.all(color: colors.blue.shade80, width: 3), + ), + child: Center( + child: Container( + decoration: BoxDecoration( + borderRadius: obj.value, + color: Zeta.of(context).colors.surfacePrimary, + border: Border.all(color: colors.blue.shade50, width: 3), + ), + padding: EdgeInsets.all(ZetaSpacing.b), + child: Text( + 'ZetaRadius.' + obj.key, + style: ZetaTextStyles.titleMedium.apply( + color: Zeta.of(context).colors.textDefault, + fontStyle: FontStyle.normal, + decoration: TextDecoration.none, + ), + ), + ), + ), + ); + } +} diff --git a/example/widgetbook/pages/theme/spacing_widgetbook.dart b/example/widgetbook/pages/theme/spacing_widgetbook.dart new file mode 100644 index 00000000..53a08235 --- /dev/null +++ b/example/widgetbook/pages/theme/spacing_widgetbook.dart @@ -0,0 +1,138 @@ +import 'package:flutter/material.dart'; +import 'package:path_drawing/path_drawing.dart'; +import 'package:widgetbook/widgetbook.dart'; + +import 'package:zeta_flutter/zeta_flutter.dart'; + +WidgetbookComponent spacingWidgetBook() { + return WidgetbookComponent( + name: 'Spacing', + useCases: [ + WidgetbookUseCase( + name: 'Named spaces', + builder: (context) => SingleChildScrollView( + child: Row( + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: namedSpacings.entries.map((obj) => _SpacingDemo(obj)).toList(), + ) + ], + ), + ), + ), + WidgetbookUseCase( + name: 'Value spaces', + builder: (context) => SingleChildScrollView( + child: Row( + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: valueSpacings.entries.map((obj) => _SpacingDemo(obj)).toList(), + ) + ], + ), + ), + ), + ], + ); +} + +Map namedSpacings = { + 'xxs': ZetaSpacing.xxs, + 'xs': ZetaSpacing.xs, + 's': ZetaSpacing.s, + 'b': ZetaSpacing.b, + 'm': ZetaSpacing.m, + 'l': ZetaSpacing.l, + 'xl': ZetaSpacing.xl, + 'xxl': ZetaSpacing.xxl, + 'xxxl': ZetaSpacing.xxxl, +}; +Map valueSpacings = { + 'x1': ZetaSpacing.x1, + 'x2': ZetaSpacing.x2, + 'x3': ZetaSpacing.x3, + 'x3.5': ZetaSpacing.x3_5, + 'x4': ZetaSpacing.x4, + 'x5': ZetaSpacing.x5, + 'x6': ZetaSpacing.x6, + 'x7': ZetaSpacing.x7, + 'x8': ZetaSpacing.x8, + 'x9': ZetaSpacing.x9, + 'x10': ZetaSpacing.x10, + 'x11': ZetaSpacing.x11, + 'x12': ZetaSpacing.x12, + 'x13': ZetaSpacing.x13, + 'x14': ZetaSpacing.x14, + 'x16': ZetaSpacing.x16, + 'x20': ZetaSpacing.x20, + 'x24': ZetaSpacing.x24, +}; + +class _SpacingDemo extends StatelessWidget { + final MapEntry size; + + const _SpacingDemo(this.size); + + @override + Widget build(BuildContext context) { + final colors = Zeta.of(context).colors; + return Container( + color: colors.blue.shade30, + margin: EdgeInsets.all(ZetaSpacing.m), + child: CustomPaint( + painter: _TagPainter(color: colors.pink), + child: LayoutBuilder(builder: (context, c2) { + return Container( + margin: EdgeInsets.all(size.value), + padding: EdgeInsets.all(ZetaSpacing.s), + color: colors.surfacePrimary, + child: Text( + 'ZetaSpacing.' + size.key, + style: ZetaTextStyles.titleMedium.apply( + color: Zeta.of(context).colors.textDefault, + fontStyle: FontStyle.normal, + decoration: TextDecoration.none, + ), + ), + ); + }), + ), + ); + } +} + +class _TagPainter extends CustomPainter { + const _TagPainter({ + required this.color, + }); + + final Color color; + + @override + void paint(Canvas canvas, Size size) { + final Paint paint = Paint() + ..color = color + ..style = PaintingStyle.stroke; + + final horizontal = Path() + ..moveTo(0, (size.height / 2)) + ..lineTo(size.width, (size.height / 2)) + ..close(); + + final vertical = Path() + ..moveTo(size.width / 2, 0) + ..lineTo(size.width / 2, size.height) + ..close(); + + canvas.drawPath(dashPath(horizontal, dashArray: CircularIntervalList([2, 3])), paint); + canvas.drawPath( + dashPath(vertical, dashArray: CircularIntervalList([2, 3]), dashOffset: DashOffset.absolute(size.height)), + paint, + ); + } + + @override + bool shouldRepaint(covariant CustomPainter oldDelegate) => false; +} diff --git a/example/widgetbook/pages/theme/typography_widgetbook.dart b/example/widgetbook/pages/theme/typography_widgetbook.dart new file mode 100644 index 00000000..e2c281c1 --- /dev/null +++ b/example/widgetbook/pages/theme/typography_widgetbook.dart @@ -0,0 +1,71 @@ +import 'package:flutter/material.dart'; +import 'package:widgetbook/widgetbook.dart'; + +import 'package:zeta_flutter/zeta_flutter.dart'; + +WidgetbookComponent textWidgetBook() { + final Map allTypes = { + 'Display large': ZetaTextStyles.displayLarge, + 'Display medium': ZetaTextStyles.displayMedium, + 'Display small': ZetaTextStyles.displaySmall, + 'Heading 1': ZetaTextStyles.heading1, + 'Heading 2': ZetaTextStyles.heading2, + 'Heading 3': ZetaTextStyles.heading3, + 'Title large': ZetaTextStyles.titleLarge, + 'Title medium': ZetaTextStyles.titleMedium, + 'Title small': ZetaTextStyles.titleSmall, + 'Body large': ZetaTextStyles.bodyLarge, + 'Body medium': ZetaTextStyles.bodyMedium, + 'Body small': ZetaTextStyles.bodySmall, + 'Label large': ZetaTextStyles.labelLarge, + 'Label medium': ZetaTextStyles.labelMedium, + 'Label small': ZetaTextStyles.labelSmall, + 'Label indicator': ZetaTextStyles.labelIndicator, + 'Label tiny': ZetaTextStyles.labelTiny, + }; + return WidgetbookComponent( + name: 'Typography', + useCases: [ + WidgetbookUseCase( + name: 'Individual text styles', + 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) => allTypes.entries.firstWhere((element) => element.value == p0).key, + options: allTypes.values.toList(), + ) + .apply( + color: Zeta.of(context).colors.textDefault, + fontStyle: FontStyle.normal, + decoration: TextDecoration.none, + ), + ), + ), + WidgetbookUseCase( + name: 'All text styles', + builder: (context) => SingleChildScrollView( + scrollDirection: Axis.vertical, + child: Row( + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: allTypes.keys.map( + (e) { + return Text( + e, + style: allTypes[e]?.apply( + color: Zeta.of(context).colors.textDefault, + fontStyle: FontStyle.normal, + decoration: TextDecoration.none, + ), + ).paddingAll(ZetaSpacing.b); + }, + ).toList()), + ], + ), + )), + ], + ); +} 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 deleted file mode 100644 index 8beaf9cb..00000000 --- a/example/widgetbook/theme/color_widgetbook.dart +++ /dev/null @@ -1,144 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:widgetbook/widgetbook.dart'; -import 'package:zeta_example/pages/theme/color_example.dart'; -import 'package:zeta_flutter/zeta_flutter.dart'; - -WidgetbookComponent colorWidgetBook() { - return WidgetbookComponent( - name: 'Colors', - useCases: [ - WidgetbookUseCase( - name: 'Light Mode', - builder: (BuildContext context) { - return ZetaProvider( - initialThemeMode: ThemeMode.light, - builder: (_, __, ___) => ColorBody(), - ); - }, - ), - WidgetbookUseCase( - name: 'Dark Mode', - builder: (BuildContext context) { - return ZetaProvider( - initialThemeMode: ThemeMode.dark, - builder: (_, __, ___) => ColorBody(), - ); - }, - ) - ], - ); -} - -class ColorBody extends StatelessWidget { - const ColorBody({ - super.key, - }); - - @override - Widget build(BuildContext context) { - return LayoutBuilder(builder: (_, constraints) { - final colors = Zeta.of(context).colors; - - final Map swatches = { - 'Blue': colors.blue, - 'Green': colors.green, - 'Red': colors.red, - 'Orange': colors.orange, - 'Purple': colors.purple, - 'Yellow': colors.yellow, - 'Teal': colors.teal, - 'Pink': colors.pink, - 'Grey Warm': colors.warm, - 'Grey Cool': colors.cool, - }; - final Map textIcon = { - 'textDefault': colors.textDefault, - 'textSubtle': colors.textSubtle, - 'textDisabled': colors.textDisabled, - 'textInverse': colors.textInverse, - }; - final Map border = { - 'borderDefault': colors.borderDefault, - 'borderSubtle': colors.borderSubtle, - 'borderDisabled': colors.borderDisabled, - 'borderSelected': colors.borderSelected, - }; - final Map links = { - 'linkDefault': colors.link, - 'linkVisited': colors.linkVisited, - }; - final Map backdrop = { - 'surfacePrimary': colors.surfacePrimary, - 'surfaceDisabled': colors.surfaceDisabled, - 'surfaceHovered': colors.surfaceHovered, - 'surfaceSecondary': colors.surfaceSecondary, - 'surfaceTertiary': colors.surfaceTertiary, - 'surfaceSelectedHovered': colors.surfaceSelectedHovered, - 'surfaceSelected': colors.surfaceSelected, - }; - - final Map alerts = { - 'positive': colors.positive, - 'negative': colors.negative, - 'warning': colors.warning, - '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), - ), - ], - ), - ), - ], - ), - ), - ), - ); - }, - ).toList(), - ); - }, - ), - const SizedBox(height: ZetaSpacing.l), - ], - ), - ), - ); - }); - } -} diff --git a/example/widgetbook/theme/typography_widgetbook.dart b/example/widgetbook/theme/typography_widgetbook.dart deleted file mode 100644 index 6eb20fe5..00000000 --- a/example/widgetbook/theme/typography_widgetbook.dart +++ /dev/null @@ -1,46 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:widgetbook/widgetbook.dart'; - -import 'package:zeta_flutter/zeta_flutter.dart'; - -WidgetbookComponent textWidgetBook() { - final dedicatedSizes = { - 'Display large': ZetaTextStyles.displayLarge, - 'Display medium': ZetaTextStyles.displayMedium, - 'Display small': ZetaTextStyles.displaySmall, - 'Heading 1': ZetaTextStyles.heading1, - 'Heading 2': ZetaTextStyles.heading2, - 'Heading 3': ZetaTextStyles.heading3, - 'Title large': ZetaTextStyles.titleLarge, - 'Title medium': ZetaTextStyles.titleMedium, - 'Title small': ZetaTextStyles.titleSmall, - 'Body large': ZetaTextStyles.bodyLarge, - 'Body medium': ZetaTextStyles.bodyMedium, - 'Body small': ZetaTextStyles.bodySmall, - 'Label large': ZetaTextStyles.labelLarge, - 'Label medium': ZetaTextStyles.labelMedium, - 'Label small': ZetaTextStyles.labelSmall, - 'Label indicator': ZetaTextStyles.labelIndicator, - 'Label tiny': ZetaTextStyles.labelTiny, - }; - return WidgetbookComponent( - name: 'Typography', - 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(), - ), - ), - ), - ), - ], - ); -} diff --git a/example/widgetbook/widgetbook.dart b/example/widgetbook/widgetbook.dart index 507d869a..8d467c86 100644 --- a/example/widgetbook/widgetbook.dart +++ b/example/widgetbook/widgetbook.dart @@ -2,17 +2,20 @@ import 'package:flutter/material.dart'; import 'package:widgetbook/widgetbook.dart'; import 'package:zeta_flutter/zeta_flutter.dart'; -import 'components/accordion_widgetbook.dart'; -import 'components/avatar_widgetbook.dart'; -import 'components/badges_widgetbook.dart'; -import 'components/bottom_sheet_widgetbook.dart'; -import 'components/button_widgetbook.dart'; -import 'components/checkbox_widgetbook.dart'; -import 'theme/color_widgetbook.dart'; -import 'components/banner_widgetbook.dart'; -import 'components/chip_widgetbook.dart'; -import 'components/password_input_widgetbook.dart'; -import 'theme/typography_widgetbook.dart'; +import 'pages/assets/icon_widgetbook.dart'; +import 'pages/components/accordion_widgetbook.dart'; +import 'pages/components/avatar_widgetbook.dart'; +import 'pages/components/badges_widgetbook.dart'; +import 'pages/components/bottom_sheet_widgetbook.dart'; +import 'pages/components/button_widgetbook.dart'; +import 'pages/components/checkbox_widgetbook.dart'; +import 'pages/theme/color_widgetbook.dart'; +import 'pages/components/banner_widgetbook.dart'; +import 'pages/components/chip_widgetbook.dart'; +import 'pages/components/password_input_widgetbook.dart'; +import 'pages/theme/radius_widgetbook.dart'; +import 'pages/theme/spacing_widgetbook.dart'; +import 'pages/theme/typography_widgetbook.dart'; import 'utils/zebra.dart'; class HotReload extends StatelessWidget { @@ -20,45 +23,105 @@ 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(), spacingWidgetBook(), radiusWidgetbook()] + ..sort((a, b) => a.name.compareTo(b.name)), + ), + WidgetbookCategory( + name: 'Assets', + isInitiallyExpanded: false, + children: [iconWidgetbook()]..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; + 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;