From cb3770520d21b6e1de4f0bb928d800b12fc49042 Mon Sep 17 00:00:00 2001 From: Luke Walton Date: Mon, 2 Sep 2024 13:18:53 +0100 Subject: [PATCH] fix: A variety of small bug fixes (#168) ci: Update passing score to 90% chore: Update third party licenses fix: Add PlatformIs to not use dart:io fix: Border sizes fix: Spacings in example app --- .github/workflows/pull-request.yml | 2 +- LICENSE-3RD-PARTY | 42 +++++++- example/lib/home.dart | 52 ++++++---- example/lib/pages/theme/spacing_example.dart | 56 +++++------ .../pages/assets/icon_widgetbook.dart | 2 +- example/widgetbook/pages/introduction.dart | 2 +- lib/src/components/avatars/avatar.dart | 2 +- lib/src/components/badges/indicator.dart | 2 +- lib/src/components/banner/banner.dart | 4 +- .../components/breadcrumbs/breadcrumbs.dart | 2 +- .../components/button_group/button_group.dart | 2 +- lib/src/components/buttons/button_style.dart | 2 +- lib/src/components/chat_item/chat_item.dart | 15 +-- lib/src/components/chips/chip.dart | 2 +- lib/src/components/dial_pad/dial_pad.dart | 2 +- lib/src/components/fabs/fab.dart | 2 +- .../global_header/global_header.dart | 2 +- .../list_item/notification_list_item.dart | 7 +- lib/src/components/radio/radio.dart | 4 +- lib/src/components/stepper/stepper.dart | 2 +- lib/src/components/switch/zeta_switch.dart | 11 +-- .../text_input/internal_text_input.dart | 4 +- .../components/top_app_bar/top_app_bar.dart | 2 +- lib/src/theme/tokens.dart | 7 +- lib/src/utils/platform/platform_is.dart | 95 +++++++++++++++++++ .../utils/platform/universal_platform_vm.dart | 35 +++++++ .../platform/universal_platform_web.dart | 54 +++++++++++ lib/src/utils/utils.dart | 1 + pubspec.yaml | 4 +- test/src/components/button/button_test.dart | 2 +- test/src/components/fabs/fab_test.dart | 2 +- 31 files changed, 318 insertions(+), 105 deletions(-) create mode 100644 lib/src/utils/platform/platform_is.dart create mode 100644 lib/src/utils/platform/universal_platform_vm.dart create mode 100644 lib/src/utils/platform/universal_platform_web.dart diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml index 65bd4d26..c58f8ab5 100644 --- a/.github/workflows/pull-request.yml +++ b/.github/workflows/pull-request.yml @@ -24,7 +24,7 @@ jobs: - uses: ZebraDevs/flutter-code-quality@main with: token: ${{secrets.GITHUB_TOKEN}} - coverage-pass-score: '1' + coverage-pass-score: '90' check-secret: diff --git a/LICENSE-3RD-PARTY b/LICENSE-3RD-PARTY index 25659cf2..cee51f99 100644 --- a/LICENSE-3RD-PARTY +++ b/LICENSE-3RD-PARTY @@ -2,7 +2,7 @@ --- -### Flutter +## Flutter Applies to: @@ -37,7 +37,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --- -### tinycolor +## tinycolor Applies to: @@ -53,7 +53,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI --- -### IBM Plex Sans +## IBM Plex Sans Applies to: @@ -67,7 +67,7 @@ This Font Software is licensed under the SIL Open Font License, Version 1.1. This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL -## SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +### SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 PREAMBLE The goals of the Open Font License (OFL) are to stimulate worldwide @@ -151,3 +151,37 @@ INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. + + + +## Mike Rydstrom + +Applies to: + +* platform_is.dart +* universal_platform_vm.dart +* universal_platform_web.dart + +https://gist.github.com/rydmike/1771fe24c050ebfe792fa309371154d8 + +MIT License + +Copyright (c) 2021 Mike Rydstrom + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/example/lib/home.dart b/example/lib/home.dart index 134ee502..72fbbd44 100644 --- a/example/lib/home.dart +++ b/example/lib/home.dart @@ -161,30 +161,40 @@ class _HomeState extends State { child: SingleChildScrollView( child: Column( children: [ - ExpansionTile( - title: Text('Widgets'), - backgroundColor: Zeta.of(context).colors.warm.shade30, - children: _components - .map((item) => ListTile(title: Text(item.name), onTap: () => context.go('/${item.name}'))) - .toList(), - ), - ExpansionTile( - title: Text('Theme'), - backgroundColor: Zeta.of(context).colors.warm.shade30, - children: _theme - .map((item) => ListTile(title: Text(item.name), onTap: () => context.go('/${item.name}'))) - .toList(), - ), - ExpansionTile( - title: Text('Assets'), - backgroundColor: Zeta.of(context).colors.warm.shade30, - children: _assets - .map((item) => ListTile(title: Text(item.name), onTap: () => context.go('/${item.name}'))) - .toList(), - ), + ExampleListTile(name: 'Components', children: _components), + ExampleListTile(name: 'Theme', children: _theme), + ExampleListTile(name: 'Assets', children: _assets), ], ), ), ); } } + +class ExampleListTile extends StatelessWidget { + const ExampleListTile({ + super.key, + required this.children, + required this.name, + }); + + final List children; + final String name; + + @override + Widget build(BuildContext context) { + return ExpansionTile( + title: Text(name), + children: children + .map( + (item) => ListTile( + title: Text(item.name), + onTap: () => context.go('/${item.name}'), + hoverColor: Zeta.of(context).colors.surfaceHover, + tileColor: Zeta.of(context).colors.surfaceDefault, + ), + ) + .toList(), + ); + } +} diff --git a/example/lib/pages/theme/spacing_example.dart b/example/lib/pages/theme/spacing_example.dart index 6ab0e78d..4be2cb92 100644 --- a/example/lib/pages/theme/spacing_example.dart +++ b/example/lib/pages/theme/spacing_example.dart @@ -16,33 +16,33 @@ class SpacingExample extends StatelessWidget { 'medium': Zeta.of(context).spacing.medium, 'large': Zeta.of(context).spacing.large, 'xl': Zeta.of(context).spacing.xl, - '2xl': Zeta.of(context).spacing.xl_2, - '3xl': Zeta.of(context).spacing.xl_3, - '4xl': Zeta.of(context).spacing.xl_4, - '5xl': Zeta.of(context).spacing.xl_5, - '6xl': Zeta.of(context).spacing.xl_6, - '7xl': Zeta.of(context).spacing.xl_7, - '8xl': Zeta.of(context).spacing.xl_8, - '9xl': Zeta.of(context).spacing.xl_9, - '10xl': Zeta.of(context).spacing.xl_10, - '11xl': Zeta.of(context).spacing.xl_11, + 'xl_2': Zeta.of(context).spacing.xl_2, + 'xl_3': Zeta.of(context).spacing.xl_3, + 'xl_4': Zeta.of(context).spacing.xl_4, + 'xl_5': Zeta.of(context).spacing.xl_5, + 'xl_6': Zeta.of(context).spacing.xl_6, + 'xl_7': Zeta.of(context).spacing.xl_7, + 'xl_8': Zeta.of(context).spacing.xl_8, + 'xl_9': Zeta.of(context).spacing.xl_9, + 'xl_10': Zeta.of(context).spacing.xl_10, + 'xl_11': Zeta.of(context).spacing.xl_11, }; Map baseSpacings = { - 'x1': Zeta.of(context).spacing.primitives.x1, - 'x2': Zeta.of(context).spacing.primitives.x2, - 'x3': Zeta.of(context).spacing.primitives.x3, - 'x4': Zeta.of(context).spacing.primitives.x4, - 'x5': Zeta.of(context).spacing.primitives.x5, - 'x6': Zeta.of(context).spacing.primitives.x6, - 'x7': Zeta.of(context).spacing.primitives.x7, - 'x8': Zeta.of(context).spacing.primitives.x8, - 'x9': Zeta.of(context).spacing.primitives.x9, - 'x10': Zeta.of(context).spacing.primitives.x10, - 'x11': Zeta.of(context).spacing.primitives.x11, - 'x12': Zeta.of(context).spacing.primitives.x12, - 'x13': Zeta.of(context).spacing.primitives.x13, - 'x14': Zeta.of(context).spacing.primitives.x14, - 'x15': Zeta.of(context).spacing.primitives.x15, + 'primitives.x1': Zeta.of(context).spacing.primitives.x1, + 'primitives.x2': Zeta.of(context).spacing.primitives.x2, + 'primitives.x3': Zeta.of(context).spacing.primitives.x3, + 'primitives.x4': Zeta.of(context).spacing.primitives.x4, + 'primitives.x5': Zeta.of(context).spacing.primitives.x5, + 'primitives.x6': Zeta.of(context).spacing.primitives.x6, + 'primitives.x7': Zeta.of(context).spacing.primitives.x7, + 'primitives.x8': Zeta.of(context).spacing.primitives.x8, + 'primitives.x9': Zeta.of(context).spacing.primitives.x9, + 'primitives.x10': Zeta.of(context).spacing.primitives.x10, + 'primitives.x11': Zeta.of(context).spacing.primitives.x11, + 'primitives.x12': Zeta.of(context).spacing.primitives.x12, + 'primitives.x13': Zeta.of(context).spacing.primitives.x13, + 'primitives.x14': Zeta.of(context).spacing.primitives.x14, + 'primitives.x15': Zeta.of(context).spacing.primitives.x15, }; return ExampleScaffold( @@ -55,12 +55,12 @@ class SpacingExample extends StatelessWidget { children: [ Column( crossAxisAlignment: CrossAxisAlignment.start, - children: baseSpacings.entries.map((obj) => _SpacingDemo(obj)).toList(), + children: semanticSpacings.entries.map((obj) => _SpacingDemo(obj)).toList(), ), Column( crossAxisAlignment: CrossAxisAlignment.start, - children: semanticSpacings.entries.map((obj) => _SpacingDemo(obj)).toList(), - ) + children: baseSpacings.entries.map((obj) => _SpacingDemo(obj)).toList(), + ), ], ), ), diff --git a/example/widgetbook/pages/assets/icon_widgetbook.dart b/example/widgetbook/pages/assets/icon_widgetbook.dart index e746f90d..81c2ad68 100644 --- a/example/widgetbook/pages/assets/icon_widgetbook.dart +++ b/example/widgetbook/pages/assets/icon_widgetbook.dart @@ -51,7 +51,7 @@ Widget iconsUseCase(BuildContext context) { nameArr, textAlign: TextAlign.center, maxLines: 2, - ) + ), ], ), ), diff --git a/example/widgetbook/pages/introduction.dart b/example/widgetbook/pages/introduction.dart index 3cfe397f..24f553f3 100644 --- a/example/widgetbook/pages/introduction.dart +++ b/example/widgetbook/pages/introduction.dart @@ -32,7 +32,7 @@ class _IntroductionWidgetbookState extends State { return LayoutBuilder(builder: (context, constraints) { final bool largeScreen = constraints.maxWidth > 480; return Scaffold( - backgroundColor: colors.black, + backgroundColor: Colors.black, body: SingleChildScrollView( child: Padding( padding: EdgeInsets.symmetric( diff --git a/lib/src/components/avatars/avatar.dart b/lib/src/components/avatars/avatar.dart index 1437d5f6..a2f7e869 100644 --- a/lib/src/components/avatars/avatar.dart +++ b/lib/src/components/avatars/avatar.dart @@ -326,7 +326,7 @@ extension on ZetaAvatarSize { case ZetaAvatarSize.xs: case ZetaAvatarSize.xxs: case ZetaAvatarSize.xxxs: - return ZetaBorders.borderWidth; + return ZetaBorders.medium; } } diff --git a/lib/src/components/badges/indicator.dart b/lib/src/components/badges/indicator.dart index 53fdc3bd..1fc5564e 100644 --- a/lib/src/components/badges/indicator.dart +++ b/lib/src/components/badges/indicator.dart @@ -113,7 +113,7 @@ class ZetaIndicator extends ZetaStatelessWidget { height: sizePixels + Zeta.of(context).spacing.minimum, decoration: BoxDecoration( border: Border.all( - width: ZetaBorders.borderWidth, + width: ZetaBorders.medium, color: Zeta.of(context).colors.borderSubtle, ), color: (inverse ? foregroundColor : Colors.transparent), diff --git a/lib/src/components/banner/banner.dart b/lib/src/components/banner/banner.dart index bde064d1..bb2be9cf 100644 --- a/lib/src/components/banner/banner.dart +++ b/lib/src/components/banner/banner.dart @@ -1,5 +1,3 @@ -import 'dart:io'; - import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; @@ -65,7 +63,7 @@ class ZetaBanner extends MaterialBanner { builder: (context) { final backgroundColor = _backgroundColorFromType(context, type); final foregroundColor = backgroundColor.onColor; - if (!kIsWeb && Platform.isAndroid && context.mounted) { + if (!kIsWeb && PlatformIs.android && context.mounted) { // ignore: invalid_use_of_visible_for_testing_member final statusBarColor = SystemChrome.latestStyle?.statusBarColor; if (statusBarColor != backgroundColor) { diff --git a/lib/src/components/breadcrumbs/breadcrumbs.dart b/lib/src/components/breadcrumbs/breadcrumbs.dart index e2f7fad5..646bfbb6 100644 --- a/lib/src/components/breadcrumbs/breadcrumbs.dart +++ b/lib/src/components/breadcrumbs/breadcrumbs.dart @@ -321,7 +321,7 @@ class _BreadCrumbsTruncatedState extends State<_BreadCrumbsTruncated> { side: WidgetStateProperty.resolveWith((states) { if (states.contains(WidgetState.focused)) { return BorderSide( - width: ZetaBorders.borderWidth, + width: ZetaBorders.medium, color: colors.primary.shade100, ); } diff --git a/lib/src/components/button_group/button_group.dart b/lib/src/components/button_group/button_group.dart index e3274e4c..3e4c5b8a 100644 --- a/lib/src/components/button_group/button_group.dart +++ b/lib/src/components/button_group/button_group.dart @@ -238,7 +238,7 @@ class _ZetaGroupButtonState extends State { bool finalButton, ) { if (_controller.value.contains(WidgetState.focused)) { - return BorderSide(color: colors.blue.shade50, width: ZetaBorders.borderWidth); + return BorderSide(color: colors.blue.shade50, width: ZetaBorders.medium); } if (_controller.value.contains(WidgetState.disabled)) { return BorderSide(color: colors.cool.shade40); diff --git a/lib/src/components/buttons/button_style.dart b/lib/src/components/buttons/button_style.dart index 4aeee30b..03aeaa7e 100644 --- a/lib/src/components/buttons/button_style.dart +++ b/lib/src/components/buttons/button_style.dart @@ -137,7 +137,7 @@ ButtonStyle buttonStyle( } // TODO(UX-1134): This removes a defualt border when focused, rather than adding a second border when focused. if (states.contains(WidgetState.focused)) { - return BorderSide(color: colors.blue, width: ZetaBorders.borderWidth); + return BorderSide(color: colors.blue, width: ZetaBorders.medium); } if (type.border) { return BorderSide( diff --git a/lib/src/components/chat_item/chat_item.dart b/lib/src/components/chat_item/chat_item.dart index 654b73d7..4241fff5 100644 --- a/lib/src/components/chat_item/chat_item.dart +++ b/lib/src/components/chat_item/chat_item.dart @@ -1,5 +1,4 @@ // ignore_for_file: deprecated_member_use_from_same_package - import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_slidable/flutter_slidable.dart'; @@ -134,22 +133,16 @@ class ZetaChatItem extends ZetaStatelessWidget { // coverage:ignore-start if (onMenuMoreTap != null) { - actions.add( - ZetaSlidableAction(onPressed: onMenuMoreTap, color: colors.purple, icon: ZetaIcons.more_vertical), - ); + actions.add(ZetaSlidableAction.menuMore(onPressed: onMenuMoreTap)); } if (onCallTap != null) { - actions.add( - ZetaSlidableAction(onPressed: onCallTap, color: colors.green, icon: ZetaIcons.phone), - ); + actions.add(ZetaSlidableAction.call(onPressed: onCallTap)); } if (onPttTap != null) { - actions.add( - ZetaSlidableAction(onPressed: onPttTap, color: colors.blue, icon: ZetaIcons.ptt), - ); + actions.add(ZetaSlidableAction.ptt(onPressed: onPttTap)); } if (onDeleteTap != null) { - actions.add(ZetaSlidableAction(onPressed: onDeleteTap, color: colors.red, icon: ZetaIcons.delete)); + actions.add(ZetaSlidableAction.delete(onPressed: onDeleteTap)); } // coverage:ignore-end diff --git a/lib/src/components/chips/chip.dart b/lib/src/components/chips/chip.dart index 12ea4a16..88620cd7 100644 --- a/lib/src/components/chips/chip.dart +++ b/lib/src/components/chips/chip.dart @@ -225,7 +225,7 @@ class _ZetaChipState extends State { BorderSide( color: _controller.value.contains(WidgetState.focused) ? colors.blue.shade50 : colors.borderDefault, width: _controller.value.contains(WidgetState.focused) - ? ZetaBorders.borderWidth + ? ZetaBorders.medium : !selected ? 1 : 0, diff --git a/lib/src/components/dial_pad/dial_pad.dart b/lib/src/components/dial_pad/dial_pad.dart index ebb059d0..31746bda 100644 --- a/lib/src/components/dial_pad/dial_pad.dart +++ b/lib/src/components/dial_pad/dial_pad.dart @@ -198,7 +198,7 @@ class ZetaDialPadButton extends StatelessWidget { decoration: ShapeDecoration( shape: const CircleBorder(), color: colors.warm.shade10, - shadows: [BoxShadow(color: colors.black.withOpacity(0.15), blurRadius: 4, offset: const Offset(0, 2))], + shadows: [BoxShadow(color: Colors.black.withOpacity(0.15), blurRadius: 4, offset: const Offset(0, 2))], ), child: Material( color: Colors.transparent, diff --git a/lib/src/components/fabs/fab.dart b/lib/src/components/fabs/fab.dart index 2f946f4a..b56fb15a 100644 --- a/lib/src/components/fabs/fab.dart +++ b/lib/src/components/fabs/fab.dart @@ -137,7 +137,7 @@ class _ZetaFABState extends State { (Set states) { if (states.contains(WidgetState.focused)) { // TODO(UX-1134): This removes a defualt border when focused, rather than adding a second border when focused. - return BorderSide(color: Zeta.of(context).colors.blue.shade50, width: ZetaBorders.borderWidth); + return BorderSide(color: Zeta.of(context).colors.blue.shade50, width: ZetaBorders.medium); } return null; }, diff --git a/lib/src/components/global_header/global_header.dart b/lib/src/components/global_header/global_header.dart index 50830a34..2cba709c 100644 --- a/lib/src/components/global_header/global_header.dart +++ b/lib/src/components/global_header/global_header.dart @@ -175,7 +175,7 @@ class _GlobalHeaderState extends State { setState(() { _selectedIndex = index; }); - child.handlePress!.call(); + child.handlePress?.call(); }, ), ); diff --git a/lib/src/components/list_item/notification_list_item.dart b/lib/src/components/list_item/notification_list_item.dart index 9e88dc3e..a1559e8e 100644 --- a/lib/src/components/list_item/notification_list_item.dart +++ b/lib/src/components/list_item/notification_list_item.dart @@ -202,13 +202,8 @@ class ZetaNotificationBadge extends StatelessWidget { @override Widget build(BuildContext context) { - final colors = Zeta.of(context).colors; return avatar != null - ? avatar!.copyWith( - size: ZetaAvatarSize.m, - lowerBadge: ZetaAvatarBadge.icon(icon: ZetaIcons.check_mark, color: colors.green), - backgroundColor: colors.purple.shade80, - ) + ? avatar!.copyWith(size: ZetaAvatarSize.m) : icon != null ? ZetaIcon( icon, diff --git a/lib/src/components/radio/radio.dart b/lib/src/components/radio/radio.dart index 38786490..2a82a57e 100644 --- a/lib/src/components/radio/radio.dart +++ b/lib/src/components/radio/radio.dart @@ -174,7 +174,7 @@ class _RadioPainter extends ToggleablePainter { final Paint paint = Paint() ..color = colors.surfacePrimary ..style = PaintingStyle.stroke - ..strokeWidth = Zeta.of(context).spacing.small + ZetaBorders.borderWidth; + ..strokeWidth = Zeta.of(context).spacing.small + ZetaBorders.medium; if (isFocused) canvas.drawCircle(center, _kInnerRadius, paint); // Outer circle @@ -185,7 +185,7 @@ class _RadioPainter extends ToggleablePainter { ? inactiveColor : activeColor ..style = PaintingStyle.stroke - ..strokeWidth = ZetaBorders.borderWidth; + ..strokeWidth = ZetaBorders.medium; canvas.drawCircle(center, _kOuterRadius, paint); // Inner circle diff --git a/lib/src/components/stepper/stepper.dart b/lib/src/components/stepper/stepper.dart index 89e3b7fb..c30badba 100644 --- a/lib/src/components/stepper/stepper.dart +++ b/lib/src/components/stepper/stepper.dart @@ -313,7 +313,7 @@ class _ZetaStepperState extends State with TickerProviderStateMixin right: Zeta.of(context).spacing.large, left: Zeta.of(context).spacing.large, ), - height: ZetaBorders.borderWidth, + height: ZetaBorders.medium, decoration: BoxDecoration( borderRadius: Zeta.of(context).radius.full, color: switch (widget.steps[index].type) { diff --git a/lib/src/components/switch/zeta_switch.dart b/lib/src/components/switch/zeta_switch.dart index 8afaba2b..99d9dcec 100644 --- a/lib/src/components/switch/zeta_switch.dart +++ b/lib/src/components/switch/zeta_switch.dart @@ -1,5 +1,3 @@ -import 'dart:io'; - import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; @@ -62,12 +60,9 @@ class ZetaSwitch extends StatelessWidget { ZetaSwitchType get _variant { if (variant != null) return variant!; - if (kIsWeb) return ZetaSwitchType.web; - return switch (Platform.operatingSystem) { - 'ios' => ZetaSwitchType.ios, - 'android' => ZetaSwitchType.android, - _ => ZetaSwitchType.web, - }; + if (PlatformIs.android) return ZetaSwitchType.android; + if (PlatformIs.iOS) return ZetaSwitchType.ios; + return ZetaSwitchType.web; } Size get _size { diff --git a/lib/src/components/text_input/internal_text_input.dart b/lib/src/components/text_input/internal_text_input.dart index 2a4488b8..05d7a9c1 100644 --- a/lib/src/components/text_input/internal_text_input.dart +++ b/lib/src/components/text_input/internal_text_input.dart @@ -277,11 +277,11 @@ class InternalTextInputState extends State { ); OutlineInputBorder _focusedBorder(bool rounded) => _baseBorder(rounded).copyWith( - borderSide: BorderSide(color: _colors.primary.shade50, width: ZetaBorders.borderWidth), + borderSide: BorderSide(color: _colors.primary.shade50, width: ZetaBorders.medium), ); // TODO(mikecoomber): change to colors.borderPrimary when added OutlineInputBorder _errorBorder(bool rounded) => _baseBorder(rounded).copyWith( - borderSide: BorderSide(color: _colors.error, width: ZetaBorders.borderWidth), + borderSide: BorderSide(color: _colors.error, width: ZetaBorders.medium), ); @override diff --git a/lib/src/components/top_app_bar/top_app_bar.dart b/lib/src/components/top_app_bar/top_app_bar.dart index a1570584..c04ad557 100644 --- a/lib/src/components/top_app_bar/top_app_bar.dart +++ b/lib/src/components/top_app_bar/top_app_bar.dart @@ -182,7 +182,7 @@ class _ZetaTopAppBarState extends State { if (widget.onSearchMicrophoneIconPressed != null) ...[ SizedBox( height: Zeta.of(context).spacing.xl_2, - child: VerticalDivider(width: ZetaBorders.borderWidth, color: colors.cool.shade70), + child: VerticalDivider(width: ZetaBorders.medium, color: colors.cool.shade70), ), IconButton( onPressed: widget.onSearchMicrophoneIconPressed, diff --git a/lib/src/theme/tokens.dart b/lib/src/theme/tokens.dart index 4ec1e093..06b468a8 100644 --- a/lib/src/theme/tokens.dart +++ b/lib/src/theme/tokens.dart @@ -338,6 +338,9 @@ class ZetaAnimationLength { /// Temporary class to hold border values. // TODO(Tokens): Remove this class and design / develop Zeta.of(context).border instead. abstract final class ZetaBorders { - /// Border width - static double get borderWidth => 2; + /// Small border width + static double get small => 0.5; + + /// Medium border width + static double get medium => 2; } diff --git a/lib/src/utils/platform/platform_is.dart b/lib/src/utils/platform/platform_is.dart new file mode 100644 index 00000000..9a15d7cc --- /dev/null +++ b/lib/src/utils/platform/platform_is.dart @@ -0,0 +1,95 @@ +// The content of this file is adapted from Mike Rydstrom: +// https://gist.github.com/rydmike/1771fe24c050ebfe792fa309371154d8 + +import 'universal_platform_web.dart' if (dart.library.io) 'universal_platform_vm.dart'; + +/// A universal platform checker. +/// +/// Can be used to check active physical Flutter platform on all platforms. +/// +/// To check what host platform the app is running on use: +/// +/// * PlatformIs.android +/// * PlatformIs.iOS +/// * PlatformIs.macOS +/// * PlatformIs.windows +/// * PlatformIs.linux +/// * PlatformIs.fuchsia +/// +/// To check the device type use: +/// +/// * PlatformIs.mobile (Android or iOS) +/// * PlatformIs.desktop (Windows, macOS or Linux) +/// +/// Currently Fuchsia is not considered mobile nor desktop, even if it +/// might be so in the future. +/// +/// To check if the Flutter application is running on Web you can use: +/// +/// * PlatformIs.web +/// +/// Alternatively the Flutter foundation compile time constant kIsWeb also +/// works well for that. +/// +/// The platform checks are supported independently on web. You can use +/// PlatformIs windows, iOS, macOS, Android and Linux to check what the host +/// platform is when you are running a Flutter Web application. +/// +/// Checking if we are running on a Fuchsia host in a Web browser, is not yet fully +/// supported. If running in a Web browser on Fuchsia, PlatformIs.web will be true, but +/// PlatformIs.fuchsia will be false. Future versions, when Fuchsia is released, +/// may fix this. +class PlatformIs { + PlatformIs._(); + + /// Web + static bool get web => const UniversalPlatform().web; + + /// Mac OS desktop + static bool get macOS => const UniversalPlatform().macOS; + + /// Windows desktop + static bool get windows => const UniversalPlatform().windows; + + /// Linux desktop + static bool get linux => const UniversalPlatform().linux; + + /// Android + static bool get android => const UniversalPlatform().android; + + /// iOS + static bool get iOS => const UniversalPlatform().iOS; + + /// Fuchsia + static bool get fuchsia => const UniversalPlatform().fuchsia; + + /// Mobile (Android or iOS) + static bool get mobile => PlatformIs.iOS || PlatformIs.android; + + /// Desktop (Windows, macOS, Linux) + static bool get desktop => PlatformIs.macOS || PlatformIs.windows || PlatformIs.linux; +} + +/// Abstract platform interface. +abstract interface class AbstractPlatform { + /// Web + bool get web; + + /// Mac OS + bool get macOS; + + /// Windows + bool get windows; + + /// Linux + bool get linux; + + /// Android + bool get android; + + /// iOS + bool get iOS; + + /// Fuchsia + bool get fuchsia; +} diff --git a/lib/src/utils/platform/universal_platform_vm.dart b/lib/src/utils/platform/universal_platform_vm.dart new file mode 100644 index 00000000..7c25ca2f --- /dev/null +++ b/lib/src/utils/platform/universal_platform_vm.dart @@ -0,0 +1,35 @@ +// The content of this file is adapted from Mike Rydstrom: +// https://gist.github.com/rydmike/1771fe24c050ebfe792fa309371154d8 + +import 'dart:io'; + +import 'platform_is.dart'; + +// NOTE: +// Never import this library directly in the application. The PlatformIs +// class and library uses conditional imports to only import this file on +// VM platform builds. + +/// UniversalPlatform for Flutter VM builds. +/// +/// We are using Dart VM builds, so we use dart:io Platform to +/// get the current platform. +class UniversalPlatform implements AbstractPlatform { + /// Default constructor. + @override + const UniversalPlatform(); + @override + bool get web => false; + @override + bool get macOS => Platform.isMacOS; + @override + bool get windows => Platform.isWindows; + @override + bool get linux => Platform.isLinux; + @override + bool get android => Platform.isAndroid; + @override + bool get iOS => Platform.isIOS; + @override + bool get fuchsia => Platform.isFuchsia; +} diff --git a/lib/src/utils/platform/universal_platform_web.dart b/lib/src/utils/platform/universal_platform_web.dart new file mode 100644 index 00000000..baaac9ae --- /dev/null +++ b/lib/src/utils/platform/universal_platform_web.dart @@ -0,0 +1,54 @@ +// The content of this file is adapted from Mike Rydstrom: +// https://gist.github.com/rydmike/1771fe24c050ebfe792fa309371154d8 + +// ignore: avoid_web_libraries_in_flutter + +import 'package:web/web.dart'; + +import 'platform_is.dart'; + +// NOTE: +// Never import this library directly in the application. The PlatformIs +// class and library uses conditional imports to only import this file on +// Web platform builds. + +final Navigator _nav = window.navigator; + +/// UniversalPlatform for Flutter WEB build. +/// +/// We can use Navigator to get the current platform. +/// +/// This function is borrowed, with minor modifications, from GetX utils library with MIT license. +/// Credits for it belong to its author Jonny Borges https://github.com/jonataslaw +/// https://github.com/jonataslaw/getx/blob/master/lib/get_utils/src/platform/platform_web.dart +class UniversalPlatform implements AbstractPlatform { + /// Default constructor + @override + const UniversalPlatform(); + @override + bool get web => true; + @override + bool get macOS => _nav.appVersion.contains('Mac OS') && !iOS; + @override + bool get windows => _nav.appVersion.contains('Win'); + @override + bool get linux => (_nav.appVersion.contains('Linux') || _nav.appVersion.contains('x11')) && !android; + // Source: https://developer.chrome.com/multidevice/user-agent + @override + bool get android => _nav.appVersion.contains('Android '); + @override + bool get iOS { + // maxTouchPoints is needed to separate iPad iOS13 vs new MacOS + return _hasMatch(_nav.platform, '/iPad|iPhone|iPod/') || (_nav.platform == 'MacIntel' && _nav.maxTouchPoints > 1); + } + + // Theoretically we could be in a Web browser on Fuchsia too, but + // we have no info on how to get that info yet, so we return false. + @override + bool get fuchsia => false; +} + +bool _hasMatch(String? value, String pattern) { + // ignore: avoid_bool_literals_in_conditional_expressions + return (value == null) ? false : RegExp(pattern).hasMatch(value); +} diff --git a/lib/src/utils/utils.dart b/lib/src/utils/utils.dart index 453c6a3e..88621bd1 100644 --- a/lib/src/utils/utils.dart +++ b/lib/src/utils/utils.dart @@ -2,6 +2,7 @@ export 'debounce.dart'; export 'enums.dart'; export 'extensions.dart'; export 'nothing.dart'; +export 'platform/platform_is.dart' show PlatformIs; export 'rounded.dart'; export 'zeta.dart'; export 'zeta_provider.dart'; diff --git a/pubspec.yaml b/pubspec.yaml index 6f2d6a47..05511bcd 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -3,8 +3,8 @@ version: 0.15.2 description: Zeta is the new, formal, standardized Zebra Design System based off the successes of ZDS (Zebra Design System). This package is in pre-release, and so many aspects are incomplete. -homepage: https://github.com/zebradevs/zeta_flutter -repository: https://github.com/zebradevs/zeta_flutter +homepage: https://github.com/ZebraDevs/zeta_flutter +repository: https://github.com/ZebraDevs/zeta_flutter issue_tracker: https://github.com/ZebraDevs/zeta_flutter/issues documentation: https://zeta-ds.web.app/flutter/dartdoc/index.html diff --git a/test/src/components/button/button_test.dart b/test/src/components/button/button_test.dart index 4acf577a..fed28ad8 100644 --- a/test/src/components/button/button_test.dart +++ b/test/src/components/button/button_test.dart @@ -262,7 +262,7 @@ void main() { expect(button.size, ZetaWidgetSize.medium); expect( filledButton.style?.side?.resolve({WidgetState.focused}), - BorderSide(color: ZetaColorBase.blue, width: ZetaBorders.borderWidth), + BorderSide(color: ZetaColorBase.blue, width: ZetaBorders.medium), ); }); testWidgets('debugFillProperties works correctly', (WidgetTester tester) async { diff --git a/test/src/components/fabs/fab_test.dart b/test/src/components/fabs/fab_test.dart index 422ef853..e9e79000 100644 --- a/test/src/components/fabs/fab_test.dart +++ b/test/src/components/fabs/fab_test.dart @@ -147,7 +147,7 @@ void main() { await tester.pumpAndSettle(); expect( filledButton.style?.side?.resolve({WidgetState.focused}), - BorderSide(color: ZetaColorBase.blue[50]!, width: ZetaBorders.borderWidth), + BorderSide(color: ZetaColorBase.blue[50]!, width: ZetaBorders.medium), ); });